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 */ 020package org.sonar.java.bytecode.asm; 021 022import java.io.IOException; 023import java.io.InputStream; 024import java.util.HashMap; 025import java.util.Map; 026 027import org.apache.commons.io.IOUtils; 028import org.objectweb.asm.ClassReader; 029import org.slf4j.Logger; 030import org.slf4j.LoggerFactory; 031 032public 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 @Override 047 public AsmClass getClass(String internalName, DETAIL_LEVEL level) { 048 if (internalName == null) { 049 throw new IllegalStateException("You can try to load a class whose internalName = 'null'"); 050 } 051 AsmClass asmClass = getAsmClassFromCacheOrCreateIt(internalName); 052 if (level.isGreaterThan(asmClass.getDetailLevel())) { 053 decoracteAsmClassFromBytecode(asmClass, level); 054 } 055 return asmClass; 056 } 057 058 private AsmClass getAsmClassFromCacheOrCreateIt(String internalName) { 059 AsmClass asmClass = asmClassCache.get(internalName); 060 if (asmClass == null) { 061 asmClass = new AsmClass(internalName, DETAIL_LEVEL.NOTHING); 062 asmClassCache.put(internalName, asmClass); 063 } 064 return asmClass; 065 } 066 067 private void decoracteAsmClassFromBytecode(AsmClass asmClass, DETAIL_LEVEL level) { 068 InputStream input = null; 069 try { 070 AsmClassVisitor classVisitor = new AsmClassVisitor(this, asmClass, level); 071 input = classLoader.getResourceAsStream(asmClass.getInternalName() + ".class"); 072 ClassReader asmReader = new ClassReader(input); 073 asmReader.accept(classVisitor, 0); 074 075 } catch (IOException e) { 076 logger.warn("Class '" + asmClass.getInternalName() + "' is not accessible through the ClassLoader."); 077 } catch (SecurityException e) { 078 logger.warn("Class '" + asmClass.getInternalName() 079 + "' is not accessible through the ClassLoader. One signed jar seems to be corrupted."); 080 } finally { 081 IOUtils.closeQuietly(input); 082 } 083 } 084}