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.asm; 021 022 import org.objectweb.asm.ClassReader; 023 import org.objectweb.asm.util.TraceClassVisitor; 024 import org.slf4j.Logger; 025 import org.slf4j.LoggerFactory; 026 027 import java.io.IOException; 028 import java.io.PrintWriter; 029 import java.util.HashMap; 030 import java.util.Map; 031 032 public class AsmClassProviderImpl extends AsmClassProvider { 033 034 private static Logger logger = LoggerFactory.getLogger(AsmClassProviderImpl.class); 035 private final ClassLoader classLoader; 036 private Map<String, AsmClass> asmClassCache = new HashMap<String, AsmClass>(); 037 038 public AsmClassProviderImpl() { 039 this.classLoader = Thread.currentThread().getContextClassLoader(); 040 } 041 042 public AsmClassProviderImpl(ClassLoader classLoader) { 043 this.classLoader = classLoader; 044 } 045 046 public AsmClass getClass(String internalName, DETAIL_LEVEL level) { 047 if (internalName == null) { 048 throw new IllegalStateException("You can try to load a class whose internalName = 'null'"); 049 } 050 AsmClass asmClass = getAsmClassFromCacheOrCreateIt(internalName); 051 if (level.isGreaterThan(asmClass.getDetailLevel())) { 052 decoracteAsmClassFromBytecode(asmClass, level); 053 } 054 return asmClass; 055 } 056 057 private AsmClass getAsmClassFromCacheOrCreateIt(String internalName) { 058 AsmClass asmClass = asmClassCache.get(internalName); 059 if (asmClass == null) { 060 asmClass = new AsmClass(internalName, DETAIL_LEVEL.NOTHING); 061 asmClassCache.put(internalName, asmClass); 062 } 063 return asmClass; 064 } 065 066 private void decoracteAsmClassFromBytecode(AsmClass asmClass, DETAIL_LEVEL level) { 067 try { 068 AsmClassVisitor classVisitor = new AsmClassVisitor(this, asmClass, level); 069 ClassReader asmReader = new ClassReader(classLoader.getResourceAsStream(asmClass.getInternalName() + ".class")); 070 asmReader.accept(classVisitor, 0); 071 } catch (IOException e) { 072 logger.warn("Class '" + asmClass.getInternalName() + "' is not accessible through the ClassLoader."); 073 } 074 } 075 076 public final void printClassBytecode(String internalName) { 077 try { 078 TraceClassVisitor classVisitor = new TraceClassVisitor(new PrintWriter(System.out)); 079 ClassReader asmReader = new ClassReader(classLoader.getResourceAsStream(internalName + ".class")); 080 asmReader.accept(classVisitor, 0); 081 } catch (IOException e) { 082 logger.info("Class '" + internalName + "' is not accessible through the ClassLoader."); 083 } 084 } 085 }