Coverage Report - net.sourceforge.cobertura.instrument.ClassInstrumenter
 
Classes in this File Line Coverage Branch Coverage Complexity
ClassInstrumenter
94%
33/35
75%
12/16
1.875
 
 1  
 /*
 2  
  * Cobertura - http://cobertura.sourceforge.net/
 3  
  *
 4  
  * Copyright (C) 2005 Mark Doliner 
 5  
  * Copyright (C) 2006 Jiri Mares 
 6  
  * 
 7  
  * Cobertura is free software; you can redistribute it and/or modify
 8  
  * it under the terms of the GNU General Public License as published
 9  
  * by the Free Software Foundation; either version 2 of the License,
 10  
  * or (at your option) any later version.
 11  
  *
 12  
  * Cobertura is distributed in the hope that it will be useful, but
 13  
  * WITHOUT ANY WARRANTY; without even the implied warranty of
 14  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 15  
  * General Public License for more details.
 16  
  *
 17  
  * You should have received a copy of the GNU General Public License
 18  
  * along with Cobertura; if not, write to the Free Software
 19  
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 20  
  * USA
 21  
  */
 22  
 
 23  
 package net.sourceforge.cobertura.instrument;
 24  
 
 25  
 import java.util.Collection;
 26  
 
 27  
 import net.sourceforge.cobertura.coveragedata.ClassData;
 28  
 import net.sourceforge.cobertura.coveragedata.ProjectData;
 29  
 
 30  
 import org.apache.log4j.Logger;
 31  
 import org.objectweb.asm.ClassAdapter;
 32  
 import org.objectweb.asm.ClassVisitor;
 33  
 import org.objectweb.asm.MethodVisitor;
 34  
 import org.objectweb.asm.Opcodes;
 35  
 
 36  
 class ClassInstrumenter extends ClassAdapter
 37  
 {
 38  
 
 39  4
         private static final Logger logger = Logger
 40  
                         .getLogger(ClassInstrumenter.class);
 41  
 
 42  
         private final static String hasBeenInstrumented = "net/sourceforge/cobertura/coveragedata/HasBeenInstrumented";
 43  
 
 44  
         private Collection ignoreRegexs;
 45  
 
 46  
         private Collection ignoreBranchesRegexs;
 47  
 
 48  
         private ProjectData projectData;
 49  
 
 50  
         private ClassData classData;
 51  
 
 52  
         private String myName;
 53  
 
 54  14
         private boolean instrument = false;
 55  
 
 56  
         public String getClassName()
 57  
         {
 58  9
                 return this.myName;
 59  
         }
 60  
 
 61  
         public boolean isInstrumented()
 62  
         {
 63  14
                 return instrument;
 64  
         }
 65  
 
 66  
         public ClassInstrumenter(ProjectData projectData, final ClassVisitor cv,
 67  
                         final Collection ignoreRegexs, final Collection ignoreBranchesRegexes)
 68  
         {
 69  14
                 super(cv);
 70  14
                 this.projectData = projectData;
 71  14
                 this.ignoreRegexs = ignoreRegexs;
 72  14
                 this.ignoreBranchesRegexs = ignoreBranchesRegexs;
 73  14
         }
 74  
 
 75  
         private boolean arrayContains(Object[] array, Object key)
 76  
         {
 77  22
                 for (int i = 0; i < array.length; i++)
 78  
                 {
 79  9
                         if (array[i].equals(key))
 80  0
                                 return true;
 81  
                 }
 82  
 
 83  13
                 return false;
 84  
         }
 85  
 
 86  
         /**
 87  
          * @param name In the format
 88  
          *             "net/sourceforge/cobertura/coverage/ClassInstrumenter"
 89  
          */
 90  
         public void visit(int version, int access, String name, String signature,
 91  
                         String superName, String[] interfaces)
 92  
         {
 93  14
                 this.myName = name.replace('/', '.');
 94  14
                 this.classData = this.projectData.getOrCreateClassData(this.myName);
 95  14
                 this.classData.setContainsInstrumentationInfo();
 96  
 
 97  
                 // Do not attempt to instrument interfaces or classes that
 98  
                 // have already been instrumented
 99  14
                 if (((access & Opcodes.ACC_INTERFACE) != 0)
 100  
                                 || arrayContains(interfaces, hasBeenInstrumented))
 101  
                 {
 102  1
                         super.visit(version, access, name, signature, superName,
 103  
                                                         interfaces);
 104  1
                 }
 105  
                 else
 106  
                 {
 107  13
                         instrument = true;
 108  
 
 109  
                         // Flag this class as having been instrumented
 110  13
                         String[] newInterfaces = new String[interfaces.length + 1];
 111  13
                         System.arraycopy(interfaces, 0, newInterfaces, 0,
 112  
                                                         interfaces.length);
 113  13
                         newInterfaces[newInterfaces.length - 1] = hasBeenInstrumented;
 114  
 
 115  13
                         super.visit(version, access, name, signature, superName,
 116  
                                         newInterfaces);
 117  
                 }
 118  14
         }
 119  
 
 120  
         /**
 121  
          * @param source In the format "ClassInstrumenter.java"
 122  
          */
 123  
         public void visitSource(String source, String debug)
 124  
         {
 125  11
                 super.visitSource(source, debug);
 126  11
                 classData.setSourceFileName(source);
 127  11
         }
 128  
 
 129  
         public MethodVisitor visitMethod(final int access, final String name,
 130  
                         final String desc, final String signature,
 131  
                         final String[] exceptions)
 132  
         {
 133  38
                 MethodVisitor mv = cv.visitMethod(access, name, desc, signature,
 134  
                                 exceptions);
 135  
 
 136  38
                 if (!instrument)
 137  0
                         return mv;
 138  
 
 139  38
                 return mv == null ? null : new FirstPassMethodInstrumenter(classData, mv,
 140  
                                 this.myName, access, name, desc, signature, exceptions, ignoreRegexs, 
 141  
                                 ignoreBranchesRegexs);
 142  
         }
 143  
 
 144  
         public void visitEnd()
 145  
         {
 146  14
                 if (instrument && classData.getNumberOfValidLines() == 0)
 147  3
                         logger.warn("No line number information found for class "
 148  
                                         + this.myName
 149  
                                         + ".  Perhaps you need to compile with debug=true?");
 150  14
         }
 151  
 
 152  
 }