001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2012 SonarSource 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 java.io.IOException; 023 import java.io.InputStream; 024 import java.util.HashMap; 025 import java.util.Map; 026 027 import org.apache.commons.io.IOUtils; 028 import org.objectweb.asm.ClassReader; 029 import org.slf4j.Logger; 030 import org.slf4j.LoggerFactory; 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 InputStream input = null; 068 try { 069 AsmClassVisitor classVisitor = new AsmClassVisitor(this, asmClass, level); 070 input = classLoader.getResourceAsStream(asmClass.getInternalName() + ".class"); 071 ClassReader asmReader = new ClassReader(input); 072 asmReader.accept(classVisitor, 0); 073 074 } catch (IOException e) { 075 logger.warn("Class '" + asmClass.getInternalName() + "' is not accessible through the ClassLoader."); 076 } catch (SecurityException e) { 077 logger.warn("Class '" + asmClass.getInternalName() 078 + "' is not accessible through the ClassLoader. One signed jar seems to be corrupted."); 079 } finally { 080 IOUtils.closeQuietly(input); 081 } 082 } 083 }