LoggingProxy.java
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[] argsthrows 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 }