001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2009 SonarSource SA 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020 package org.sonar.java.bytecode; 021 022 import java.io.File; 023 import java.util.ArrayList; 024 import java.util.Arrays; 025 import java.util.Collection; 026 import java.util.List; 027 028 import org.sonar.java.bytecode.asm.AsmClass; 029 import org.sonar.java.bytecode.asm.AsmClassProvider; 030 import org.sonar.java.bytecode.asm.AsmClassProviderImpl; 031 import org.sonar.java.bytecode.asm.AsmClassProvider.DETAIL_LEVEL; 032 import org.sonar.java.bytecode.visitor.AccessorVisitor; 033 import org.sonar.java.bytecode.visitor.BytecodeVisitor; 034 import org.sonar.java.bytecode.visitor.DITVisitor; 035 import org.sonar.java.bytecode.visitor.DeadCodeDetectionVisitor; 036 import org.sonar.java.bytecode.visitor.DependenciesVisitor; 037 import org.sonar.java.bytecode.visitor.LCOM4Visitor; 038 import org.sonar.java.bytecode.visitor.NOCVisitor; 039 import org.sonar.java.bytecode.visitor.RFCVisitor; 040 import org.sonar.squid.api.CodeScanner; 041 import org.sonar.squid.api.SourceClass; 042 import org.sonar.squid.api.SourceCode; 043 import org.sonar.squid.indexer.QueryByType; 044 import org.sonar.squid.indexer.SquidIndex; 045 046 public class BytecodeScanner extends CodeScanner<BytecodeVisitor> { 047 048 private SquidIndex indexer; 049 050 public BytecodeScanner(SquidIndex indexer) { 051 this.indexer = indexer; 052 } 053 054 public BytecodeScanner scan(Collection<File> bytecodeFilesOrDirectories) { 055 Collection<SourceCode> classes = indexer.search(new QueryByType(SourceClass.class)); 056 return scan(classes, new AsmClassProviderImpl(ClassworldsClassLoader.create(bytecodeFilesOrDirectories))); 057 } 058 059 public BytecodeScanner scanDirectory(File bytecodeDirectory) { 060 return scan(Arrays.asList(bytecodeDirectory)); 061 } 062 063 protected BytecodeScanner scan(Collection<SourceCode> classes, AsmClassProvider classProvider) { 064 loadByteCodeInformation(classes, classProvider); 065 notifyBytecodeVisitors(classes, classProvider); 066 return this; 067 } 068 069 private void notifyBytecodeVisitors(Collection<SourceCode> classes, AsmClassProvider classProvider) { 070 BytecodeVisitor[] visitorArray = getVisitors().toArray(new BytecodeVisitor[getVisitors().size()]); 071 for (SourceCode sourceCode : classes) { 072 AsmClass asmClass = classProvider.getClass(sourceCode.getKey(), DETAIL_LEVEL.STRUCTURE_AND_CALLS); 073 BytecodeVisitorNotifier visitorNotifier = new BytecodeVisitorNotifier(asmClass, visitorArray); 074 visitorNotifier.notifyVisitors(); 075 } 076 } 077 078 private void loadByteCodeInformation(Collection<SourceCode> classes, AsmClassProvider classProvider) { 079 for (SourceCode sourceCode : classes) { 080 classProvider.getClass(sourceCode.getKey(), DETAIL_LEVEL.STRUCTURE_AND_CALLS); 081 } 082 } 083 084 @Override 085 public Collection<Class<? extends BytecodeVisitor>> getVisitorClasses() { 086 List<Class<? extends BytecodeVisitor>> visitorClasses = new ArrayList<Class<? extends BytecodeVisitor>>(); 087 visitorClasses.add(AccessorVisitor.class); 088 visitorClasses.add(DITVisitor.class); 089 visitorClasses.add(RFCVisitor.class); 090 visitorClasses.add(NOCVisitor.class); 091 visitorClasses.add(LCOM4Visitor.class); 092 visitorClasses.add(DependenciesVisitor.class); 093 visitorClasses.add(DeadCodeDetectionVisitor.class); 094 return visitorClasses; 095 } 096 }