Project Report: fawkez

Packagesummary org.jcoderz.commons.tracing

org.jcoderz.commons.tracing.TracingProxy

LineHitsNoteSource
1  /*
2   * $Id: LoggingProxy.java 1011 2008-06-16 17:57:36Z amandel $
3   *
4   * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5   *
6   * Redistribution and use in source and binary forms, with or without
7   * modification, are permitted provided that the following conditions are
8   * met:
9   *
10   *    * Redistributions of source code must retain the above copyright
11   *      notice, this list of conditions and the following disclaimer.
12   *    * Redistributions in binary form must reproduce the above
13   *      copyright notice, this list of conditions and the following
14   *      disclaimer in the documentation and/or other materials
15   *      provided with the distribution.
16   *    * Neither the name of the jCoderZ.org Project nor the names of
17   *      its contributors may be used to endorse or promote products
18   *      derived from this software without specific prior written
19   *      permission.
20   *
21   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24   * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25   * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28   * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32   */
33  package org.jcoderz.commons.tracing;
34  
35  import java.lang.reflect.InvocationHandler;
36  import java.lang.reflect.InvocationTargetException;
37  import java.lang.reflect.Method;
38  import java.lang.reflect.Modifier;
39  import java.lang.reflect.Proxy;
40  import java.util.Arrays;
41  import java.util.HashSet;
42  import java.util.Set;
43  
44  import org.jcoderz.commons.ArgumentMalformedException;
45  import org.jcoderz.commons.tracing.Tracer.TracingToken;
46  
47  /**
48   * <p>
49   * This class can be used to proxy any object, providing tracing for 
50   * all <i>interfaces</i> of the object.
51   * </p>
52   * <p>
53   * <b>Note:</b> Java Dynamic Proxies only work on <i>interfaces</i>.
54   * The object returned by the {@link #getProxy(Object)} can be cast to
55   * any interface implemented by the argument or one of its ancestors. It
56   * can't, however, be cast to an implementation class.
57   * </p>
58   *
59   * @author Andreas Mandel
60   */
61 (1)public final class TracingProxy
62        implements InvocationHandler
63  {
64     private final Object mRealObject;
65     private final String mRealObjectClassName;
66     private final Tracer mObjectTracer;
67  
68     /**
69      * Create a proxy that directs all calls to the real object and logs all
70      * method calls with entering/exiting/throwing, using the given logger.
71      *
72      * @param realObject the object for which a proxy is created
73      * @param logger the logger to which calls are logged
74      */
75     private TracingProxy (Object realObject, Tracer tracer)
760    {
770       mRealObject = realObject;
780       mRealObjectClassName = mRealObject.getClass().getName();
790       mObjectTracer = tracer;
800    }
81  
82     /**
83      * Static factory that wraps an object into a proxy depending on the
84      * log level for that object.
85      *
86      * @param obj an object for which a proxy should be created
87      * @return a logging proxy for the obj, if the log level for that
88      *       object is FINER or finest, the object itself otherwise
89      */
90 (2)   public static Object getProxy (Object obj, Class tracerClass)
91     {
920       final String classname = obj.getClass().getName();
930       final Tracer tracer = getTracer(tracerClass, classname);
94  
95        final Object proxy;
960       if (tracer.isTracing())
97        {
98           // collect all interfaces implemented by this objects class and
99           // its super classes
100           // Note: We do not add super-interfaces here....
1010          final Set interfaces = new HashSet();
1020          Class currentClass = obj.getClass();
1030          while (currentClass != null)
104           {
1050             interfaces.addAll(Arrays.asList(currentClass.getInterfaces()));
1060             currentClass = currentClass.getSuperclass();
107           }
108  
1090          proxy = Proxy.newProxyInstance(
110                 obj.getClass().getClassLoader(),
111                 (Class[]) interfaces.toArray(new Class[interfaces.size()]),
112                 new TracingProxy(obj, tracer));
1130       }
114        else
115        {
1160          proxy = obj;
117        }
1180       return proxy;
119     }
120  
121     /**
122      * Log the entering, exiting and throwing events of the proxied object.
123      *
124      * @see java.lang.reflect.InvocationHandler#invoke(
125      *       java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
126      */
127 (3)(4)(5)(6)   public Object invoke (Object proxy, Method method, Object[] args)
128 (7)         throws Throwable
129     {
130        final TracingToken tt;
1310       if (mObjectTracer.isTracing())
132        {
1330          if (args == null || !mObjectTracer.isTracingArguments())
134           {
1350             tt = mObjectTracer.entering(
136                  mRealObjectClassName, method.getName());
137           }
138           else
139           {
1400(8)             tt = mObjectTracer.entering(
141                    mRealObjectClassName, method.getName(), args);
142           }
143        }
144        else
145        {
1460           tt = null;
147        }
148  
1490       final Object result = invokeMethod(method, args, tt);
150  
1510       if (tt != null)
152        {
1530          if (result != null
154               || method.getReturnType() != Void.TYPE
155               || !mObjectTracer.isTracingArguments())
156           {
1570            mObjectTracer.exiting(tt, result);
158           }
159           else
160           {
1610            mObjectTracer.exiting(tt);
162           }
163        }
1640       return result;
165     }
166  
167 (9)   private static Tracer getTracer(Class tracer, String className)
168     {
169         final Tracer result;
170         try
171         {
1720            final Method method
173                 = tracer.getMethod("getTracer", new Class[] {String.class});
1740            if (!Modifier.isStatic(method.getModifiers()))
175             {
1760(10)               throw new ArgumentMalformedException(
177 (11)                   "tracer", tracer, 
178                     "Factory method 'getTracer' must be static.");
179             }
1800            if (!Modifier.isPublic(method.getModifiers()))
181             {
1820(12)               throw new ArgumentMalformedException(
183                     "tracer", tracer,
184                     "Factory method 'getTracer' must be public.");
185             }
1860            result = (Tracer) method.invoke(null, new Object[] {className});
187         }
1880        catch (IllegalArgumentException e)
189         {
1900(13)           throw new ArgumentMalformedException(
191                 "tracer", tracer,
192                 "The static tracer factory did not accept the String argument.",
193                 e);
194         }
1950        catch (IllegalAccessException e)
196         {
1970(14)           throw new ArgumentMalformedException(
198                 "tracer", tracer,
199                 "The static tracer factory did deny access.",
200                 e);
201         }
2020        catch (InvocationTargetException e)
203         {
2040            throw new ArgumentMalformedException(
205                 "tracer", tracer,
206                 "The static tracer factory threw an exception with detail: "
207                 + e.getMessage() + ".",
208                 e);
209         }
2100        catch (SecurityException e)
211         {
2120(15)           throw new ArgumentMalformedException(
213                 "tracer", tracer,
214                 "Failed to look up static factory method.",
215                 e);
216         }
2170        catch (NoSuchMethodException e)
218         {
2190(16)           throw new ArgumentMalformedException(
220                 "tracer", tracer,
221                 "The Tracer implementation must implement a static factory "
222                 + "method 'public Tracer getTracer(String)'.",
223                 e);
2240        }
2250        return result;
226     }
227     
228     private Object invokeMethod (
229         Method method, Object[] args, TracingToken tt)
230         throws Throwable
231     {
232        final Object result;
233        try
234        {
2350          result = method.invoke(mRealObject, args);
236        }
2370       catch (InvocationTargetException x)
238        {
2390          if (tt != null)
240           {
2410             mObjectTracer.throwing(tt, x.getCause());
242           }
2430(17)         throw x.getCause();
244        }
2450       catch (Exception x)
246        {
2470          if (tt != null)
248           {
2490             mObjectTracer.throwing(tt, x);
250           }
2510          throw x;
2520       }
2530       return result;
254     }
255  }

Findings in this File

d (1) 61 : 0 Tag @link: can't find getProxy(Object) in org.jcoderz.commons.tracing.TracingProxy
c (2) 90 : 53 Expected @param tag for 'tracerClass'.
c (3) 127 : 0 Expected an @return tag.
c (4) 127 : 33 Expected @param tag for 'proxy'.
c (5) 127 : 47 Expected @param tag for 'method'.
c (6) 127 : 64 Expected @param tag for 'args'.
c (7) 128 : 17 Expected @throws tag for 'Throwable'.
w (8) 140 : 0 Method org.jcoderz.commons.tracing.TracingProxy.invoke(Object, Method, Object[]) assigns a variable in a larger scope then is needed
c (9) 167 : 35 '(' is not preceded with whitespace.
i (10) 176 : 0 method org.jcoderz.commons.tracing.TracingProxy.getTracer(Class, String) throws exception with static message string
i (11) 177 : 20 The String literal "tracer" appears 7 times in this file; the first occurrence is on line 177
i (12) 182 : 0 method org.jcoderz.commons.tracing.TracingProxy.getTracer(Class, String) throws exception with static message string
i (13) 190 : 0 method org.jcoderz.commons.tracing.TracingProxy.getTracer(Class, String) throws exception with static message string
i (14) 197 : 0 method org.jcoderz.commons.tracing.TracingProxy.getTracer(Class, String) throws exception with static message string
i (15) 212 : 0 method org.jcoderz.commons.tracing.TracingProxy.getTracer(Class, String) throws exception with static message string
i (16) 219 : 0 method org.jcoderz.commons.tracing.TracingProxy.getTracer(Class, String) throws exception with static message string
w (17) 243 : 0 Method org.jcoderz.commons.tracing.TracingProxy.invokeMethod(Method, Object[], Tracer$TracingToken) throws alternative exception from catch block without history