Project Report: fawkez

Packagesummary org.jcoderz.commons.tracing

org.jcoderz.commons.tracing.ClassTracingInjector

LineHitsNoteSource
1  /*
2   * $Id: ArraysUtil.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 org.jcoderz.commons.tracing.TracingInjector.Matcher;
36  
37  import java.util.Iterator;
38  import java.util.logging.Level;
39  import java.util.logging.Logger;
40  
41  import org.objectweb.asm.Opcodes;
42  import org.objectweb.asm.tree.AbstractInsnNode;
43  import org.objectweb.asm.tree.ClassNode;
44  import org.objectweb.asm.tree.FieldInsnNode;
45  import org.objectweb.asm.tree.FieldNode;
46  import org.objectweb.asm.tree.InsnList;
47  import org.objectweb.asm.tree.InsnNode;
48  import org.objectweb.asm.tree.LabelNode;
49  import org.objectweb.asm.tree.LdcInsnNode;
50  import org.objectweb.asm.tree.LineNumberNode;
51  import org.objectweb.asm.tree.MethodInsnNode;
52  import org.objectweb.asm.tree.MethodNode;
53  
54  /**
55   * Takes care to add Tracing to the methods.
56   * @author mandelan
57   */
58  public class ClassTracingInjector
59  {
60    private static final int STATIC_BLOCK_LINE_NUMBER = 1;
610   private static final String CLASSNAME = ClassTracingInjector.class.getName();
620   private static final Logger logger = Logger.getLogger(CLASSNAME);
63    private final ClassNode mClassNode;
64    private final String mClassName;
650   private boolean mStaticLoggerInserted = false;
66    private MethodNode mStaticInit;
67    private final boolean mJava5;
68    private final boolean mPai;
69  
70    /**
71     *
72     * @param cn
73    * @param java5
74    * @param pai
75    */
76 (1)(2)(3)(4)  public ClassTracingInjector(ClassNode cn, boolean java5, boolean pai)
770   {
780     mPai = pai;
790     mJava5 = java5;
800     mClassNode = cn;
810     mClassName  = cn.name.replace('/', '.');
820   }
83  
84    /**
85     * Injects logging to all methods that match the given matcher.
86     * @param matcher the matcher to identify methods to inject.
87     */
88 (5)  public void inject (Matcher matcher)
89    {
90      // No tracing for interfaces.
910     if ((mClassNode.access & Opcodes.ACC_INTERFACE) == 0)
92      {
930       final Iterator i = mClassNode.methods.iterator();
940       while (i.hasNext())
95        {
960         final MethodNode mn = (MethodNode) i.next();
970         if (matcher.matches(mClassNode, mn))
98          {
990           if (logger.isLoggable(Level.FINEST))
100            {
1010             logger.finest("Will inject tracing into: "
102                  + AsmUtil.toString(mClassNode, mn));
103            }
1040           final MethodTracingInjector mi
105              = new MethodTracingInjector(mn, this);
1060           mi.inject();
1070         }
108          else
109          {
1100           if (logger.isLoggable(Level.FINEST))
111            {
1120             logger.finest("No match: "
113                  + AsmUtil.toString(mClassNode, mn));
114            }
115          }
1160         if ("<clinit>".equals(mn.name) && mStaticInit == null)
117          {
1180           mStaticInit = mn;
119          }
1200       }
1210       if (!mStaticLoggerInserted)
122        {
123          MethodNode mn;
1240         if (mStaticInit == null)
125          {
1260(6)          if (logger.isLoggable(Level.FINEST))
127            {
1280             logger.finest("Creating new static initializer for class: "
129                  + AsmUtil.toString(mClassNode));
130            }
1310           mn = new MethodNode(
132              Opcodes.ACC_STATIC,  "<clinit>", "()V", null, null);
1330           mn.instructions = new InsnList();
1340           final LabelNode start = new LabelNode();
1350           mn.instructions.add(start);
1360(7)          mn.instructions.add(new LineNumberNode(STATIC_BLOCK_LINE_NUMBER, start));
1370           mn.instructions.add(new InsnNode(Opcodes.RETURN));
1380           mClassNode.methods.add(mn);
1390         }
140          else
141          {
1420           mn = mStaticInit;
1430(8)          if (logger.isLoggable(Level.FINEST))
144            {
1450             logger.finest("Using existing static initializer: "
146                  + AsmUtil.toString(mClassNode, mn));
147            }
148          }
1490         final InsnList cmd = new InsnList();
1500         injectStaticLoggerMember(cmd);
151          // get first none label node
1520(9)        AbstractInsnNode first = mn.instructions.getFirst();
153          while (first.getNext() != null
1540             && first.getType() == AbstractInsnNode.LABEL)
155          {
1560           first = first.getNext();
157          }
1580         mn.instructions.insertBefore(first, cmd);
1590         mStaticLoggerInserted = true;
160        }
1610     }
162      else
163      { // No tracing for interfaces.
1640       if (logger.isLoggable(Level.FINEST))
165        {
1660         logger.finest("No tracing in interfaces! "
167              + AsmUtil.toString(mClassNode));
168        }
169  
170      }
1710   }
172  
173 (10)  public ClassNode getClassNode ()
174    {
1750     return mClassNode;
176    }
177  
178 (11)  public String getClassName ()
179    {
1800     return mClassName;
181    }
182  
183    /**
184     *
185     * @param cmd
186    */
187 (12)  public void getStaticLoggerOnStack (InsnList cmd)
188    {
1890     cmd.add(new FieldInsnNode(
190          Opcodes.GETSTATIC,
191          mClassNode.name,
192          TracingInjector.STATIC_LOGGER_FIELD_NAME,
193          "Ljava/util/logging/Logger;"));
1940   }
195  
196    /**
197     * Load the class name reference to the stack.
198     * @param cmd the instruction list where to add the command to.
199     */
200 (13)  public void getClassNameOnStack(InsnList cmd)
201    {
2020     cmd.add(new LdcInsnNode(mClassName));
2030   }
204  
205    /**
206     * Injects the static logger member and takes care for the
207     * static initialization.
208     * @param cmd the command list to add the code to.
209     */
210    public void injectStaticLoggerMember (InsnList cmd)
211    {
2120     if (!mStaticLoggerInserted)
213      {
2140       final FieldNode staticLogger
215          = new FieldNode(
216              Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL
217            + Opcodes.ACC_STATIC + Opcodes.ACC_SYNTHETIC,
218            TracingInjector.STATIC_LOGGER_FIELD_NAME,
219            "Ljava/util/logging/Logger;",
220            null,
221            null);
2220       mClassNode.fields.add(staticLogger);
2230       getClassNameOnStack(cmd);
2240       cmd.add(new MethodInsnNode(
225            Opcodes.INVOKESTATIC,
226            "java/util/logging/Logger",
227            "getLogger",
228            "(Ljava/lang/String;)Ljava/util/logging/Logger;"));
2290       cmd.add(new FieldInsnNode(
230            Opcodes.PUTSTATIC,
231            mClassNode.name,
232            TracingInjector.STATIC_LOGGER_FIELD_NAME,
233            "Ljava/util/logging/Logger;"));
2340       mStaticLoggerInserted = true;
235      }
2360   }
237  
238 (14)(15)  public boolean isJava5()
239    {
2400     return mJava5;
241    }
242  
243 (16)(17)  public boolean isPai()
244    {
2450     return mPai;
246    }
247  }

Findings in this File

c (1) 76 : 30 '(' is not preceded with whitespace.
c (2) 76 : 41 Expected @param tag for 'cn'.
c (3) 76 : 53 Expected @param tag for 'java5'.
c (4) 76 : 68 Expected @param tag for 'pai'.
c (5) 88 : 3 Cyclomatic Complexity is 15 (max allowed is 12).
c (6) 126 : 11 Nested if-else depth is 3 (max allowed is 2).
c (7) 136 : 0 Line is longer than 80 characters.
c (8) 143 : 11 Nested if-else depth is 3 (max allowed is 2).
c (9) 152 : 9 Declaring variables, return values or parameters of type 'AbstractInsnNode' is not allowed.
c (10) 173 : 3 Missing a Javadoc comment.
c (11) 178 : 3 Missing a Javadoc comment.
c (12) 187 : 48 Expected @param tag for 'cmd'.
c (13) 200 : 34 '(' is not preceded with whitespace.
c (14) 238 : 3 Missing a Javadoc comment.
c (15) 238 : 25 '(' is not preceded with whitespace.
c (16) 243 : 3 Missing a Javadoc comment.
c (17) 243 : 23 '(' is not preceded with whitespace.