001 /*
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements. See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership. The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied. See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 *
020 */
021 package org.apache.qpid.server.util;
022
023 import java.lang.reflect.InvocationHandler;
024 import java.lang.reflect.InvocationTargetException;
025 import java.lang.reflect.Method;
026 import java.lang.reflect.Proxy;
027 import java.util.Arrays;
028
029 /**
030 * Dynamic proxy that records invocations in a fixed size circular buffer,
031 * dumping details on hitting an exception.
032 * <p>
033 * Useful in debugging.
034 * <p>
035 */
036 public class LoggingProxy implements InvocationHandler
037 {
038 private final Object _target;
039 private final CircularBuffer _log;
040
041 public LoggingProxy(Object target, int size)
042 {
043 _target = target;
044 _log = new CircularBuffer(size);
045 }
046
047 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
048 {
049 try
050 {
051 entered(method, args);
052 Object result = method.invoke(_target, args);
053 returned(method, result);
054 return result;
055 }
056 catch(InvocationTargetException e)
057 {
058 dump();
059 throw e.getTargetException();
060 }
061 }
062
063 void dump()
064 {
065 _log.dump();
066 }
067
068 CircularBuffer getBuffer()
069 {
070 return _log;
071 }
072
073 private synchronized void entered(Method method, Object[] args)
074 {
075 if (args == null)
076 {
077 _log.add(Thread.currentThread() + ": " + method.getName() + "() entered");
078 }
079 else
080 {
081 _log.add(Thread.currentThread() + ": " + method.getName() + "(" + Arrays.toString(args) + ") entered");
082 }
083 }
084
085 private synchronized void returned(Method method, Object result)
086 {
087 if (method.getReturnType() == Void.TYPE)
088 {
089 _log.add(Thread.currentThread() + ": " + method.getName() + "() returned");
090 }
091 else
092 {
093 _log.add(Thread.currentThread() + ": " + method.getName() + "() returned " + result);
094 }
095 }
096
097 public Object getProxy(Class... c)
098 {
099 return Proxy.newProxyInstance(_target.getClass().getClassLoader(), c, this);
100 }
101
102 public int getBufferSize() {
103 return _log.size();
104 }
105 }
|