EMMA Coverage Report (generated Mon Nov 29 14:43:38 PST 2010)
[all classes][com.jeantessier.metrics]

COVERAGE SUMMARY FOR SOURCE FILE [MetricsGatherer.java]

nameclass, %method, %block, %line, %
MetricsGatherer.java100% (1/1)96%  (43/45)94%  (1788/1893)96%  (330.4/344)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class MetricsGatherer100% (1/1)96%  (43/45)94%  (1788/1893)96%  (330.4/344)
removeMetricsListener (MetricsListener): void 0%   (0/1)0%   (0/19)0%   (0/4)
visitInterfaceMethodRef_info (InterfaceMethodRef_info): void 0%   (0/1)0%   (0/64)0%   (0/7)
addMetricsListener (MetricsListener): void 100% (1/1)74%  (14/19)93%  (3.7/4)
cloneListeners (): Collection 100% (1/1)75%  (15/20)93%  (3.7/4)
visitClass_info (Class_info): void 100% (1/1)81%  (30/37)83%  (5/6)
processDescriptor (String): Collection 100% (1/1)93%  (65/70)92%  (11/12)
<static initializer> 100% (1/1)100% (5/5)100% (1/1)
MetricsGatherer (MetricsFactory): void 100% (1/1)100% (22/22)100% (7/7)
addClassDependencies (Collection): void 100% (1/1)100% (15/15)100% (3/3)
addClassDependency (String): void 100% (1/1)100% (170/170)100% (22/22)
addMethodDependency (String): void 100% (1/1)100% (108/108)100% (15/15)
computeDepthOfInheritance (Classfile): int 100% (1/1)100% (21/21)100% (5/5)
fireBeginClass (Classfile): void 100% (1/1)100% (22/22)100% (4/4)
fireBeginMethod (Method_info): void 100% (1/1)100% (22/22)100% (4/4)
fireBeginSession (int): void 100% (1/1)100% (22/22)100% (4/4)
fireEndClass (Classfile, Metrics): void 100% (1/1)100% (23/23)100% (4/4)
fireEndMethod (Method_info, Metrics): void 100% (1/1)100% (23/23)100% (4/4)
fireEndSession (): void 100% (1/1)100% (21/21)100% (4/4)
getCurrentClass (): Metrics 100% (1/1)100% (3/3)100% (1/1)
getCurrentGroup (): Metrics 100% (1/1)100% (3/3)100% (1/1)
getCurrentMethod (): Metrics 100% (1/1)100% (3/3)100% (1/1)
getCurrentProject (): Metrics 100% (1/1)100% (3/3)100% (1/1)
getMetricsFactory (): MetricsFactory 100% (1/1)100% (3/3)100% (1/1)
isInFilter (String): boolean 100% (1/1)100% (12/12)100% (4/4)
isInScope (String): boolean 100% (1/1)100% (12/12)100% (4/4)
isInnerClassOfCurrentClass (InnerClass): boolean 100% (1/1)100% (32/32)100% (4/4)
setCurrentClass (Metrics): void 100% (1/1)100% (4/4)100% (2/2)
setCurrentGroup (Metrics): void 100% (1/1)100% (4/4)100% (2/2)
setCurrentMethod (Metrics): void 100% (1/1)100% (4/4)100% (2/2)
setCurrentProject (Metrics): void 100% (1/1)100% (4/4)100% (2/2)
setFilterIncludes (Collection): void 100% (1/1)100% (4/4)100% (2/2)
setScopeIncludes (Collection): void 100% (1/1)100% (4/4)100% (2/2)
visitClassfile (Classfile): void 100% (1/1)100% (252/252)100% (49/49)
visitClassfiles (Collection): void 100% (1/1)100% (10/10)100% (4/4)
visitDeprecated_attribute (Deprecated_attribute): void 100% (1/1)100% (58/58)100% (11/11)
visitExceptionHandler (ExceptionHandler): void 100% (1/1)100% (8/8)100% (3/3)
visitFieldRef_info (FieldRef_info): void 100% (1/1)100% (64/64)100% (7/7)
visitField_info (Field_info): void 100% (1/1)100% (192/192)100% (31/31)
visitInnerClass (InnerClass): void 100% (1/1)100% (149/149)100% (33/33)
visitInstruction (Instruction): void 100% (1/1)100% (12/12)100% (5/5)
visitLineNumber (LineNumber): void 100% (1/1)100% (7/7)100% (2/2)
visitLocalVariable (LocalVariable): void 100% (1/1)100% (13/13)100% (3/3)
visitMethodRef_info (MethodRef_info): void 100% (1/1)100% (64/64)100% (7/7)
visitMethod_info (Method_info): void 100% (1/1)100% (223/223)100% (38/38)
visitSynthetic_attribute (Synthetic_attribute): void 100% (1/1)100% (43/43)100% (8/8)

1/*
2 *  Copyright (c) 2001-2009, Jean Tessier
3 *  All rights reserved.
4 *  
5 *  Redistribution and use in source and binary forms, with or without
6 *  modification, are permitted provided that the following conditions
7 *  are met:
8 *  
9 *      * Redistributions of source code must retain the above copyright
10 *        notice, this list of conditions and the following disclaimer.
11 *  
12 *      * Redistributions in binary form must reproduce the above copyright
13 *        notice, this list of conditions and the following disclaimer in the
14 *        documentation and/or other materials provided with the distribution.
15 *  
16 *      * Neither the name of Jean Tessier nor the names of his contributors
17 *        may be used to endorse or promote products derived from this software
18 *        without specific prior written permission.
19 *  
20 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 *  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR
24 *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 
33package com.jeantessier.metrics;
34 
35import java.util.*;
36 
37import org.apache.log4j.*;
38import org.apache.oro.text.perl.*;
39 
40import com.jeantessier.classreader.*;
41 
42/**
43 *  Collects metrics from Classfile instances.
44 *  
45 *  This class can only approximate SLOC based on information provided
46 *  by the compiler.
47 */
48public class MetricsGatherer extends VisitorBase {
49    private static final Perl5Util perl = new Perl5Util();
50 
51    private MetricsFactory factory;
52 
53    private Collection<String> scope = null;
54    private Collection<String> filter = null;
55    
56    private Metrics currentProject;
57    private Metrics currentGroup;
58    private Metrics currentClass;
59    private Metrics currentMethod;
60 
61    private int sloc;
62    private boolean isSynthetic;
63    
64    private HashSet<MetricsListener> metricsListeners = new HashSet<MetricsListener>();
65 
66    public MetricsGatherer(MetricsFactory factory) {
67        this.factory = factory;
68 
69        setCurrentProject(getMetricsFactory().createProjectMetrics());
70    }
71 
72    public MetricsFactory getMetricsFactory() {
73        return factory;
74    }
75 
76    public void setScopeIncludes(Collection<String> scope) {
77        this.scope = scope;
78    }
79    
80    public void setFilterIncludes(Collection<String> filter) {
81        this.filter = filter;
82    }
83    
84    private Metrics getCurrentProject() {
85        return currentProject;
86    }
87 
88    void setCurrentProject(Metrics currentProject) {
89        this.currentProject = currentProject;
90    }
91 
92    private Metrics getCurrentGroup() {
93        return currentGroup;
94    }
95 
96    void setCurrentGroup(Metrics currentGroup) {
97        this.currentGroup = currentGroup;
98    }
99 
100    private Metrics getCurrentClass() {
101        return currentClass;
102    }
103 
104    void setCurrentClass(Metrics currentClass) {
105        this.currentClass = currentClass;
106    }
107 
108    private Metrics getCurrentMethod() {
109        return currentMethod;
110    }
111 
112    void setCurrentMethod(Metrics currentMethod) {
113        this.currentMethod = currentMethod;
114    }
115 
116    public void visitClassfiles(Collection<Classfile> classfiles) {
117        fireBeginSession(classfiles.size());
118 
119        super.visitClassfiles(classfiles);
120        
121        fireEndSession();
122    }
123    
124    // Classfile
125    public void visitClassfile(Classfile classfile) {
126        String className = classfile.getClassName();
127        Logger.getLogger(getClass()).debug("VisitClassfile():");
128        Logger.getLogger(getClass()).debug("    class = \"" + className + "\"");
129 
130        fireBeginClass(classfile);
131        
132        setCurrentMethod(null);
133        setCurrentClass(getMetricsFactory().createClassMetrics(className));
134        setCurrentGroup(getCurrentClass().getParent());
135        setCurrentProject(getCurrentGroup().getParent());
136 
137        getMetricsFactory().includeClassMetrics(getCurrentClass());
138 
139        getCurrentProject().addToMeasurement(BasicMeasurements.PACKAGES, getCurrentGroup().getName());
140 
141        if (classfile.isPublic()) {
142            getCurrentProject().addToMeasurement(BasicMeasurements.PUBLIC_CLASSES, className);
143            getCurrentGroup().addToMeasurement(BasicMeasurements.PUBLIC_CLASSES, className);
144        } else {
145            getCurrentProject().addToMeasurement(BasicMeasurements.PACKAGE_CLASSES, className);
146            getCurrentGroup().addToMeasurement(BasicMeasurements.PACKAGE_CLASSES, className);
147        }
148 
149        if (classfile.isFinal()) {
150            getCurrentProject().addToMeasurement(BasicMeasurements.FINAL_CLASSES, className);
151            getCurrentGroup().addToMeasurement(BasicMeasurements.FINAL_CLASSES, className);
152        }
153 
154        if (classfile.isSuper()) {
155            getCurrentProject().addToMeasurement(BasicMeasurements.SUPER_CLASSES, className);
156            getCurrentGroup().addToMeasurement(BasicMeasurements.SUPER_CLASSES, className);
157        }
158 
159        if (classfile.isInterface()) {
160            getCurrentProject().addToMeasurement(BasicMeasurements.INTERFACES, className);
161            getCurrentGroup().addToMeasurement(BasicMeasurements.INTERFACES, className);
162        }
163 
164        if (classfile.isAbstract()) {
165            getCurrentProject().addToMeasurement(BasicMeasurements.ABSTRACT_CLASSES, className);
166            getCurrentGroup().addToMeasurement(BasicMeasurements.ABSTRACT_CLASSES, className);
167        }
168 
169        if (classfile.isSynthetic()) {
170            getCurrentProject().addToMeasurement(BasicMeasurements.SYNTHETIC_CLASSES, className);
171            getCurrentGroup().addToMeasurement(BasicMeasurements.SYNTHETIC_CLASSES, className);
172        }
173 
174        if (classfile.getSuperclassIndex() != 0) {
175            classfile.getRawSuperclass().accept(this);
176 
177            getMetricsFactory().createClassMetrics(classfile.getSuperclassName()).addToMeasurement(BasicMeasurements.SUBCLASSES);
178 
179            Classfile superclass = classfile.getLoader().getClassfile(classfile.getSuperclassName());
180            if (superclass != null) {
181                getCurrentClass().addToMeasurement(BasicMeasurements.DEPTH_OF_INHERITANCE, computeDepthOfInheritance(superclass));
182            }
183        }
184 
185        for (Class_info class_info : classfile.getAllInterfaces()) {
186            class_info.accept(this);
187        }
188 
189        for (Field_info field : classfile.getAllFields()) {
190            field.accept(this);
191        }
192 
193        for (Method_info method : classfile.getAllMethods()) {
194            method.accept(this);
195        }
196 
197        sloc = 1;
198 
199        for (Attribute_info attribute : classfile.getAttributes()) {
200            attribute.accept(this);
201        }
202        
203        if (!classfile.isSynthetic()) {
204            getCurrentClass().addToMeasurement(BasicMeasurements.CLASS_SLOC, sloc);
205        }
206 
207        fireEndClass(classfile, getCurrentClass());
208    }
209    
210    // ConstantPool entries
211    public void visitClass_info(Class_info entry) {
212        Logger.getLogger(getClass()).debug("VisitClass_info():");
213        Logger.getLogger(getClass()).debug("    name = \"" + entry.getName() + "\"");
214        if (entry.getName().startsWith("[")) {
215            addClassDependencies(processDescriptor(entry.getName()));
216        } else {
217            addClassDependency(entry.getName());
218        }
219    }
220    
221    public void visitFieldRef_info(FieldRef_info entry) {
222        Logger.getLogger(getClass()).debug("VisitFieldRef_info():");
223        Logger.getLogger(getClass()).debug("    class = \"" + entry.getClassName() + "\"");
224        Logger.getLogger(getClass()).debug("    name = \"" + entry.getRawNameAndType().getName() + "\"");
225        Logger.getLogger(getClass()).debug("    type = \"" + entry.getRawNameAndType().getType() + "\"");
226 
227        // Dependencies on attributes are accounted as dependencies on their class
228        entry.getRawClass().accept(this);
229        addClassDependencies(processDescriptor(entry.getRawNameAndType().getType()));
230    }
231 
232    public void visitMethodRef_info(MethodRef_info entry) {
233        Logger.getLogger(getClass()).debug("VisitMethodRef_info():");
234        Logger.getLogger(getClass()).debug("    class = \"" + entry.getClassName() + "\"");
235        Logger.getLogger(getClass()).debug("    name = \"" + entry.getRawNameAndType().getName() + "\"");
236        Logger.getLogger(getClass()).debug("    type = \"" + entry.getRawNameAndType().getType() + "\"");
237        addMethodDependency(entry.getFullSignature());
238        addClassDependencies(processDescriptor(entry.getRawNameAndType().getType()));
239    }
240 
241    public void visitInterfaceMethodRef_info(InterfaceMethodRef_info entry) {
242        Logger.getLogger(getClass()).debug("VisitInterfaceMethodRef_info():");
243        Logger.getLogger(getClass()).debug("    class = \"" + entry.getClassName() + "\"");
244        Logger.getLogger(getClass()).debug("    name = \"" + entry.getRawNameAndType().getName() + "\"");
245        Logger.getLogger(getClass()).debug("    type = \"" + entry.getRawNameAndType().getType() + "\"");
246        addMethodDependency(entry.getFullSignature());
247        addClassDependencies(processDescriptor(entry.getRawNameAndType().getType()));
248    }
249 
250    public void visitField_info(Field_info entry) {
251        String fullName = entry.getFullName();
252        getCurrentClass().addToMeasurement(BasicMeasurements.ATTRIBUTES, fullName);
253 
254        Logger.getLogger(getClass()).debug("VisitField_info(" + entry.getFullSignature() + ")");
255        Logger.getLogger(getClass()).debug("Current class: " + getCurrentClass().getName());
256        Logger.getLogger(getClass()).debug("Access flag: " + entry.getAccessFlag());
257        Logger.getLogger(getClass()).debug("Public: " + entry.isPublic());
258        Logger.getLogger(getClass()).debug("Private: " + entry.isPrivate());
259        Logger.getLogger(getClass()).debug("Protected: " + entry.isProtected());
260        Logger.getLogger(getClass()).debug("Static: " + entry.isStatic());
261        
262        if (entry.isPublic()) {
263            getCurrentClass().addToMeasurement(BasicMeasurements.PUBLIC_ATTRIBUTES, fullName);
264        } else if (entry.isPrivate()) {
265            getCurrentClass().addToMeasurement(BasicMeasurements.PRIVATE_ATTRIBUTES, fullName);
266        } else if (entry.isProtected()) {
267            getCurrentClass().addToMeasurement(BasicMeasurements.PROTECTED_ATTRIBUTES, fullName);
268        } else {
269            getCurrentClass().addToMeasurement(BasicMeasurements.PACKAGE_ATTRIBUTES, fullName);
270        }
271 
272        if (entry.isStatic()) {
273            getCurrentClass().addToMeasurement(BasicMeasurements.STATIC_ATTRIBUTES, fullName);
274        }
275 
276        if (entry.isFinal()) {
277            getCurrentClass().addToMeasurement(BasicMeasurements.FINAL_ATTRIBUTES, fullName);
278        }
279 
280        if (entry.isVolatile()) {
281            getCurrentClass().addToMeasurement(BasicMeasurements.VOLATILE_ATTRIBUTES, fullName);
282        }
283 
284        if (entry.isTransient()) {
285            getCurrentClass().addToMeasurement(BasicMeasurements.TRANSIENT_ATTRIBUTES, fullName);
286        }
287 
288        sloc = 1;
289        isSynthetic = entry.isSynthetic();
290        
291        super.visitField_info(entry);
292        
293        if (!isSynthetic) {
294            getCurrentClass().addToMeasurement(BasicMeasurements.CLASS_SLOC, sloc);
295        }
296 
297        addClassDependencies(processDescriptor(entry.getDescriptor()));
298    }
299 
300    public void visitMethod_info(Method_info entry) {
301        fireBeginMethod(entry);
302 
303        String fullSignature = entry.getFullSignature();
304        setCurrentMethod(getMetricsFactory().createMethodMetrics(fullSignature));
305        getMetricsFactory().includeMethodMetrics(getCurrentMethod());
306        
307        Logger.getLogger(getClass()).debug("VisitMethod_info(" + fullSignature + ")");
308        Logger.getLogger(getClass()).debug("Current class: " + getCurrentClass().getName());
309        Logger.getLogger(getClass()).debug("Access flag: " + entry.getAccessFlag());
310        Logger.getLogger(getClass()).debug("Public: " + entry.isPublic());
311        Logger.getLogger(getClass()).debug("Private: " + entry.isPrivate());
312        Logger.getLogger(getClass()).debug("Protected: " + entry.isProtected());
313        Logger.getLogger(getClass()).debug("Static: " + entry.isStatic());
314 
315        sloc = 0;
316        isSynthetic = entry.isSynthetic();
317        
318        if (entry.isPublic()) {
319            getCurrentClass().addToMeasurement(BasicMeasurements.PUBLIC_METHODS, fullSignature);
320        } else if (entry.isPrivate()) {
321            getCurrentClass().addToMeasurement(BasicMeasurements.PRIVATE_METHODS, fullSignature);
322        } else if (entry.isProtected()) {
323            getCurrentClass().addToMeasurement(BasicMeasurements.PROTECTED_METHODS, fullSignature);
324        } else {
325            getCurrentClass().addToMeasurement(BasicMeasurements.PACKAGE_METHODS, fullSignature);
326        }
327 
328        if (entry.isStatic()) {
329            getCurrentClass().addToMeasurement(BasicMeasurements.STATIC_METHODS, fullSignature);
330        }
331 
332        if (entry.isFinal()) {
333            getCurrentClass().addToMeasurement(BasicMeasurements.FINAL_METHODS, fullSignature);
334        }
335 
336        if (entry.isSynchronized()) {
337            getCurrentClass().addToMeasurement(BasicMeasurements.SYNCHRONIZED_METHODS, fullSignature);
338        }
339 
340        if (entry.isNative()) {
341            getCurrentClass().addToMeasurement(BasicMeasurements.NATIVE_METHODS, fullSignature);
342        }
343 
344        if (entry.isAbstract()) {
345            getCurrentClass().addToMeasurement(BasicMeasurements.ABSTRACT_METHODS, fullSignature);
346            sloc = 1;
347        }
348 
349        getCurrentMethod().addToMeasurement(BasicMeasurements.PARAMETERS, DescriptorHelper.getParameterCount(entry.getDescriptor()));
350        
351        super.visitMethod_info(entry);
352        
353        if (!isSynthetic) {
354            getCurrentMethod().addToMeasurement(BasicMeasurements.SLOC, sloc);
355        }
356 
357        addClassDependencies(processDescriptor(entry.getDescriptor()));
358 
359        fireEndMethod(entry, getCurrentMethod());
360    }
361 
362    // 
363    // Attributes
364    //
365 
366    public void visitSynthetic_attribute(Synthetic_attribute attribute) {
367        Object owner = attribute.getOwner();
368 
369        isSynthetic = true;
370        
371        if (owner instanceof Field_info) {
372            getCurrentClass().addToMeasurement(BasicMeasurements.SYNTHETIC_ATTRIBUTES, ((Field_info) owner).getFullName());
373        } else if (owner instanceof Method_info) {
374            getCurrentClass().addToMeasurement(BasicMeasurements.SYNTHETIC_METHODS, ((Method_info) owner).getFullSignature());
375        } else {
376            Logger.getLogger(getClass()).warn("Synthetic attribute on unknown Visitable: " + owner.getClass().getName());
377        }
378    }
379 
380    public void visitDeprecated_attribute(Deprecated_attribute attribute) {
381        Object owner = attribute.getOwner();
382    
383        if (owner instanceof Classfile) {
384            String className = ((Classfile) owner).getClassName();
385            getCurrentProject().addToMeasurement(BasicMeasurements.DEPRECATED_CLASSES, className);
386            getCurrentGroup().addToMeasurement(BasicMeasurements.DEPRECATED_CLASSES, className);
387        } else if (owner instanceof Field_info) {
388            getCurrentClass().addToMeasurement(BasicMeasurements.DEPRECATED_ATTRIBUTES, ((Field_info) owner).getFullName());
389        } else if (owner instanceof Method_info) {
390            getCurrentClass().addToMeasurement(BasicMeasurements.DEPRECATED_METHODS, ((Method_info) owner).getFullSignature());
391        } else {
392            Logger.getLogger(getClass()).warn("Deprecated attribute on unknown Visitable: " + owner.getClass().getName());
393        }
394    }
395 
396    // 
397    // Attribute helpers
398    //
399 
400    public void visitInstruction(Instruction helper) {
401        super.visitInstruction(helper);
402 
403        /*
404         *  We can skip the "new" (0xbb) instruction as it is always
405         *  followed by a call to the constructor method.
406         */
407 
408        switch (helper.getOpcode()) {
409            case 0x12: // ldc
410            case 0x13: // ldc_w
411            case 0xb2: // getstatic
412            case 0xb3: // putstatic
413            case 0xb4: // getfield
414            case 0xb5: // putfield
415            case 0xb6: // invokevirtual
416            case 0xb7: // invokespecial
417            case 0xb8: // invokestatic
418            case 0xb9: // invokeinterface
419            // case 0xbb: // new
420            case 0xbd: // anewarray
421            case 0xc0: // checkcast
422            case 0xc1: // instanceof
423            case 0xc5: // multianewarray
424                helper.getIndexedConstantPoolEntry().accept(this);
425                break;
426            default:
427                // Do nothing
428                break;
429        }
430    }
431 
432    public void visitExceptionHandler(ExceptionHandler helper) {
433        if (helper.getCatchTypeIndex() != 0) {
434            helper.getRawCatchType().accept(this);
435        }
436    }
437 
438    public void visitInnerClass(InnerClass helper) {
439        if (isInnerClassOfCurrentClass(helper)) {
440            String innerClassName = helper.getInnerClassInfo();
441 
442            getCurrentProject().addToMeasurement(BasicMeasurements.INNER_CLASSES, innerClassName);
443            getCurrentGroup().addToMeasurement(BasicMeasurements.INNER_CLASSES, innerClassName);
444            getCurrentClass().addToMeasurement(BasicMeasurements.INNER_CLASSES, innerClassName);
445        
446            if (helper.isPublic()) {
447                getCurrentProject().addToMeasurement(BasicMeasurements.PUBLIC_INNER_CLASSES, innerClassName);
448                getCurrentGroup().addToMeasurement(BasicMeasurements.PUBLIC_INNER_CLASSES, innerClassName);
449                getCurrentClass().addToMeasurement(BasicMeasurements.PUBLIC_INNER_CLASSES, innerClassName);
450            } else if (helper.isPrivate()) {
451                getCurrentProject().addToMeasurement(BasicMeasurements.PRIVATE_INNER_CLASSES, innerClassName);
452                getCurrentGroup().addToMeasurement(BasicMeasurements.PRIVATE_INNER_CLASSES, innerClassName);
453                getCurrentClass().addToMeasurement(BasicMeasurements.PRIVATE_INNER_CLASSES, innerClassName);
454            } else if (helper.isProtected()) {
455                getCurrentProject().addToMeasurement(BasicMeasurements.PROTECTED_INNER_CLASSES, innerClassName);
456                getCurrentGroup().addToMeasurement(BasicMeasurements.PROTECTED_INNER_CLASSES, innerClassName);
457                getCurrentClass().addToMeasurement(BasicMeasurements.PROTECTED_INNER_CLASSES, innerClassName);
458            } else {
459                getCurrentProject().addToMeasurement(BasicMeasurements.PACKAGE_INNER_CLASSES, innerClassName);
460                getCurrentGroup().addToMeasurement(BasicMeasurements.PACKAGE_INNER_CLASSES, innerClassName);
461                getCurrentClass().addToMeasurement(BasicMeasurements.PACKAGE_INNER_CLASSES, innerClassName);
462            }
463 
464            if (helper.isStatic()) {
465                getCurrentProject().addToMeasurement(BasicMeasurements.STATIC_INNER_CLASSES, innerClassName);
466                getCurrentGroup().addToMeasurement(BasicMeasurements.STATIC_INNER_CLASSES, innerClassName);
467                getCurrentClass().addToMeasurement(BasicMeasurements.STATIC_INNER_CLASSES, innerClassName);
468            }
469 
470            if (helper.isFinal()) {
471                getCurrentProject().addToMeasurement(BasicMeasurements.FINAL_INNER_CLASSES, innerClassName);
472                getCurrentGroup().addToMeasurement(BasicMeasurements.FINAL_INNER_CLASSES, innerClassName);
473                getCurrentClass().addToMeasurement(BasicMeasurements.FINAL_INNER_CLASSES, innerClassName);
474            }
475 
476            if (helper.isAbstract()) {
477                getCurrentProject().addToMeasurement(BasicMeasurements.ABSTRACT_INNER_CLASSES, innerClassName);
478                getCurrentGroup().addToMeasurement(BasicMeasurements.ABSTRACT_INNER_CLASSES, innerClassName);
479                getCurrentClass().addToMeasurement(BasicMeasurements.ABSTRACT_INNER_CLASSES, innerClassName);
480            }
481        }
482    }
483 
484    // Package-level for testing
485    boolean isInnerClassOfCurrentClass(InnerClass helper) {
486        boolean result;
487 
488        if (helper.getOuterClassInfo().equals("")) {
489            result = perl.match("/^" + getCurrentClass().getName() + "\\$\\d+$/", helper.getInnerClassInfo());
490        } else {
491            result = helper.getOuterClassInfo().equals(getCurrentClass().getName());
492        }
493 
494        return result;
495    }
496 
497    public void visitLineNumber(LineNumber helper) {
498        sloc++;
499    }
500 
501    public void visitLocalVariable(LocalVariable helper) {
502        getCurrentMethod().addToMeasurement(BasicMeasurements.LOCAL_VARIABLES, helper.getName());
503 
504        addClassDependencies(processDescriptor(helper.getDescriptor()));
505    }
506 
507    private int computeDepthOfInheritance(Classfile classfile) {
508        int result = 1;
509        
510        if (classfile != null && classfile.getSuperclassIndex() != 0) {
511            Classfile superclass = classfile.getLoader().getClassfile(classfile.getSuperclassName());
512            result += computeDepthOfInheritance(superclass);
513        }
514 
515        return result;
516    }
517    
518    private Collection<String> processDescriptor(String str) {
519        Collection<String> result = new LinkedList<String>();
520        
521        Logger.getLogger(getClass()).debug("ProcessDescriptor: " + str);
522 
523        int currentPos = 0;
524        int startPos;
525        int endPos;
526 
527        while ((startPos = str.indexOf('L', currentPos)) != -1) {
528            if ((endPos = str.indexOf(';', startPos)) != -1) {
529                String classname = ClassNameHelper.path2ClassName(str.substring(startPos + 1, endPos));
530                result.add(classname);
531                currentPos = endPos + 1;
532            } else {
533                currentPos = startPos + 1;
534            }
535        }
536 
537        Logger.getLogger(getClass()).debug("ProcessDescriptor: " + result);
538        
539        return result;
540    }
541 
542    private void addClassDependencies(Collection<String> classnames) {
543        for (String classname : classnames) {
544            addClassDependency(classname);
545        }
546    }
547    
548    private void addClassDependency(String name) {
549        Logger.getLogger(getClass()).debug("AddClassDependency(\"" + name + "\") ...");
550 
551        if (!getCurrentClass().getName().equals(name) && isInFilter(name)) {
552            Metrics other = getMetricsFactory().createClassMetrics(name);
553                
554            if (getCurrentMethod() != null && isInScope(getCurrentMethod().getName())) {
555                Logger.getLogger(getClass()).debug("AddClassDependency " + getCurrentMethod().getName() + " -> " + name + " ...");
556                
557                if (getCurrentClass().getParent().equals(other.getParent())) {
558                    Logger.getLogger(getClass()).debug("Intra-Package ...");
559                    getCurrentMethod().addToMeasurement(BasicMeasurements.OUTBOUND_INTRA_PACKAGE_CLASS_DEPENDENCIES, other.getName());
560                    other.addToMeasurement(BasicMeasurements.INBOUND_INTRA_PACKAGE_METHOD_DEPENDENCIES, getCurrentMethod().getName());
561                } else {
562                    Logger.getLogger(getClass()).debug("Extra-Package ...");
563                    getCurrentMethod().addToMeasurement(BasicMeasurements.OUTBOUND_EXTRA_PACKAGE_CLASS_DEPENDENCIES, other.getName());
564                    other.addToMeasurement(BasicMeasurements.INBOUND_EXTRA_PACKAGE_METHOD_DEPENDENCIES, getCurrentMethod().getName());
565                }
566            } else if (isInScope(getCurrentClass().getName())) {
567                Logger.getLogger(getClass()).debug("AddClassDependency " + getCurrentClass().getName() + " -> " + name + " ...");
568                
569                if (getCurrentClass().getParent().equals(other.getParent())) {
570                    Logger.getLogger(getClass()).debug("Intra-Package ...");
571                    getCurrentClass().addToMeasurement(BasicMeasurements.OUTBOUND_INTRA_PACKAGE_DEPENDENCIES, other.getName());
572                    other.addToMeasurement(BasicMeasurements.INBOUND_INTRA_PACKAGE_DEPENDENCIES, getCurrentClass().getName());
573                } else {
574                    Logger.getLogger(getClass()).debug("Extra-Package ...");
575                    getCurrentClass().addToMeasurement(BasicMeasurements.OUTBOUND_EXTRA_PACKAGE_DEPENDENCIES, other.getName());
576                    other.addToMeasurement(BasicMeasurements.INBOUND_EXTRA_PACKAGE_DEPENDENCIES, getCurrentClass().getName());
577                }
578            }
579        }
580    }
581    
582    private void addMethodDependency(String name) {
583        Logger.getLogger(getClass()).debug("AddMethodDependency " + getCurrentMethod().getName() + " -> " + name + " ...");
584 
585        if (!getCurrentMethod().getName().equals(name) && isInScope(getCurrentMethod().getName()) && isInFilter(name)) {
586            Metrics other = getMetricsFactory().createMethodMetrics(name);
587            
588            if (getCurrentClass().equals(other.getParent())) {
589                Logger.getLogger(getClass()).debug("Intra-Class ...");
590                getCurrentMethod().addToMeasurement(BasicMeasurements.OUTBOUND_INTRA_CLASS_FEATURE_DEPENDENCIES, other.getName());
591                other.addToMeasurement(BasicMeasurements.INBOUND_INTRA_CLASS_METHOD_DEPENDENCIES, getCurrentMethod().getName());
592            } else if (getCurrentGroup().equals(other.getParent().getParent())) {
593                Logger.getLogger(getClass()).debug("Intra-Package ...");
594                getCurrentMethod().addToMeasurement(BasicMeasurements.OUTBOUND_INTRA_PACKAGE_FEATURE_DEPENDENCIES, other.getName());
595                other.addToMeasurement(BasicMeasurements.INBOUND_INTRA_PACKAGE_METHOD_DEPENDENCIES, getCurrentMethod().getName());
596            } else {
597                Logger.getLogger(getClass()).debug("Extra-Package ...");
598                getCurrentMethod().addToMeasurement(BasicMeasurements.OUTBOUND_EXTRA_PACKAGE_FEATURE_DEPENDENCIES, other.getName());
599                other.addToMeasurement(BasicMeasurements.INBOUND_EXTRA_PACKAGE_METHOD_DEPENDENCIES, getCurrentMethod().getName());
600            }
601        }
602    }
603    
604    private boolean isInScope(String name) {
605        boolean result = true;
606 
607        if (scope != null) {
608            result = scope.contains(name);
609        }
610 
611        return result;
612    }
613    
614    private boolean isInFilter(String name) {
615        boolean result = true;
616 
617        if (filter != null) {
618            result = filter.contains(name);
619        }
620 
621        return result;
622    }
623 
624    public void addMetricsListener(MetricsListener listener) {
625        synchronized(metricsListeners) {
626            metricsListeners.add(listener);
627        }
628    }
629 
630    public void removeMetricsListener(MetricsListener listener) {
631        synchronized(metricsListeners) {
632            metricsListeners.remove(listener);
633        }
634    }
635 
636    protected void fireBeginSession(int size) {
637        MetricsEvent event = new MetricsEvent(this, size);
638        for (MetricsListener listener : cloneListeners()) {
639            listener.beginSession(event);
640        }
641    }
642 
643    protected void fireBeginClass(Classfile classfile) {
644        MetricsEvent event = new MetricsEvent(this, classfile);
645        for (MetricsListener listener : cloneListeners()) {
646            listener.beginClass(event);
647        }
648    }
649 
650    protected void fireBeginMethod(Method_info method) {
651        MetricsEvent event = new MetricsEvent(this, method);
652        for (MetricsListener listener : cloneListeners()) {
653            listener.beginMethod(event);
654        }
655    }
656 
657    protected void fireEndMethod(Method_info method, Metrics metrics) {
658        MetricsEvent event = new MetricsEvent(this, method, metrics);
659        for (MetricsListener listener : cloneListeners()) {
660            listener.endMethod(event);
661        }
662    }
663 
664    protected void fireEndClass(Classfile classfile, Metrics metrics) {
665        MetricsEvent event = new MetricsEvent(this, classfile, metrics);
666        for (MetricsListener listener : cloneListeners()) {
667            listener.endClass(event);
668        }
669    }
670 
671    protected void fireEndSession() {
672        MetricsEvent event = new MetricsEvent(this);
673        for (MetricsListener listener : cloneListeners()) {
674            listener.endSession(event);
675        }
676    }
677 
678    private Collection<MetricsListener> cloneListeners() {
679        Collection<MetricsListener> result;
680        synchronized(metricsListeners) {
681            result = (Collection<MetricsListener>) metricsListeners.clone();
682        }
683        return result;
684    }
685}

[all classes][com.jeantessier.metrics]
EMMA 2.0.5312 (C) Vladimir Roubtsov