public static ClassLoader create(Collection<File> bytecodeFilesOrDirectories) { List<File> files = Lists.newArrayList(); for (File file : bytecodeFilesOrDirectories) { if (file.isFile() && file.getPath().endsWith(".class")) { LOG.info("SonarQube Squid ClassLoader was expecting a JAR file instead of CLASS file : '" + file.getAbsolutePath() + "'"); } else { files.add(file); } } if (LOG.isDebugEnabled()) { LOG.debug("----- Classpath analyzed by Squid:"); for (File file : files) { LOG.debug(file.getAbsolutePath()); } LOG.debug("-----"); } try { return new SquidClassLoader(files); } catch (Exception e) { throw new IllegalStateException("Can not create ClassLoader", e); } }
public void endOfAnalysis() { if(!classesNotFound.isEmpty()) { String message = ""; if(classesNotFound.size() > 50) { message = ", ..."; } LOG.warn("Classes not found during the analysis : [{}{}]", classesNotFound.stream().limit(50).collect(Collectors.joining(", ")), message); } allScanners.stream() .filter(s -> s instanceof EndOfAnalysisCheck) .map(EndOfAnalysisCheck.class::cast) .forEach(EndOfAnalysisCheck::endOfAnalysis); classLoader.close(); }
@Override protected Class findClass(String name) throws ClassNotFoundException { String resourceName = name.replace('.', '/') + ".class"; for (Loader loader : loaders) { byte[] classBytes = loader.loadBytes(resourceName); if (classBytes != null) { // TODO Godin: definePackage ? return defineClass(name, classBytes, 0, classBytes.length); } } throw new ClassNotFoundException(name); }
/** * This method reads constant values in bytecode. It should be called when resolving semantics from source. */ @CheckForNull public Object constantValue(Symbol owner, String constantName) { if (constantValues.containsKey(owner)) { return constantValues.get(owner).get(constantName); } if (owner.isTypeSymbol()) { JavaSymbol.TypeJavaSymbol typeSymbol = (JavaSymbol.TypeJavaSymbol) owner; String bytecodeName = typeSymbol.getFullyQualifiedName(); byte[] bytes = classLoader.getBytesForClass(bytecodeName); if (bytes != null) { Map<String, Object> valuesByFieldName = new HashMap<>(); ClassReader classReader = new ClassReader(bytes); classReader.accept( new ClassVisitor(ASM_API_VERSION) { @Override public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { valuesByFieldName.put(name, value); return super.visitField(access, name, descriptor, signature, value); } }, ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); constantValues.put(typeSymbol, valuesByFieldName); return valuesByFieldName.get(constantName); } } return null; }
@Nullable private InputStream inputStreamFor(String fullname) { return classLoader.getResourceAsStream(Convert.bytecodeName(fullname) + ".class"); }
/** * @param files ordered list of files and directories from which to load classes and resources */ public SquidClassLoader(List<File> files) { super(computeParent()); loaders = new ArrayList<>(); for (File file : files) { if (file.exists()) { try { if (file.isDirectory()) { loaders.add(new FileSystemLoader(file)); } else if (file.getName().endsWith(".jar")) { loaders.add(new JarLoader(file)); } else if (file.getName().endsWith(".aar")) { loaders.add(new AarLoader(file)); } } catch (IllegalStateException e) { LOG.warn("Unable to load classes from '{}'", file.getPath()); LOG.debug("{}: {}", e.getMessage(), e.getCause().getMessage()); } } } }
if (classLoader.getResource(Convert.bytecodeName(flatName) + ".class") != null) { symbol.completer = this; } else {
/** * This method reads constant values in bytecode. It should be called when resolving semantics from source. */ @CheckForNull public Object constantValue(Symbol owner, String constantName) { if (constantValues.containsKey(owner)) { return constantValues.get(owner).get(constantName); } if (owner.isTypeSymbol()) { JavaSymbol.TypeJavaSymbol typeSymbol = (JavaSymbol.TypeJavaSymbol) owner; String bytecodeName = typeSymbol.getFullyQualifiedName(); byte[] bytes = classLoader.getBytesForClass(bytecodeName); if (bytes != null) { Map<String, Object> valuesByFieldName = new HashMap<>(); ClassReader classReader = new ClassReader(bytes); classReader.accept( new ClassVisitor(ASM_API_VERSION) { @Override public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { valuesByFieldName.put(name, value); return super.visitField(access, name, descriptor, signature, value); } }, ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG); constantValues.put(typeSymbol, valuesByFieldName); return valuesByFieldName.get(constantName); } } return null; }
@Nullable private InputStream inputStreamFor(String fullname) { return classLoader.getResourceAsStream(Convert.bytecodeName(fullname) + ".class"); }
/** * @param files ordered list of files and directories from which to load classes and resources */ public SquidClassLoader(List<File> files) { super(computeParent()); loaders = new ArrayList<>(); for (File file : files) { if (file.exists()) { try { if (file.isDirectory()) { loaders.add(new FileSystemLoader(file)); } else if (file.getName().endsWith(".jar")) { loaders.add(new JarLoader(file)); } else if (file.getName().endsWith(".aar")) { loaders.add(new AarLoader(file)); } } catch (IllegalStateException e) { LOG.warn("Unable to load classes from '{}'", file.getPath()); LOG.debug("{}: {}", e.getMessage(), e.getCause().getMessage()); } } } }
if (classLoader.getResource(Convert.bytecodeName(flatName) + ".class") != null) { symbol.completer = this; } else {
@Override protected Class findClass(String name) throws ClassNotFoundException { String resourceName = name.replace('.', '/') + ".class"; for (Loader loader : loaders) { byte[] classBytes = loader.loadBytes(resourceName); if (ArrayUtils.isNotEmpty(classBytes)) { // TODO Godin: definePackage ? return defineClass(name, classBytes, 0, classBytes.length); } } throw new ClassNotFoundException(name); }
public void endOfAnalysis() { if(!classesNotFound.isEmpty()) { String message = ""; if(classesNotFound.size() > 50) { message = ", ..."; } LOG.warn("Classes not found during the analysis : [{}{}]", classesNotFound.stream().limit(50).collect(Collectors.joining(", ")), message); } allScanners.stream() .filter(s -> s instanceof EndOfAnalysisCheck) .map(EndOfAnalysisCheck.class::cast) .forEach(EndOfAnalysisCheck::endOfAnalysis); classLoader.close(); }
public static ClassLoader create(Collection<File> bytecodeFilesOrDirectories) { List<File> files = Lists.newArrayList(); for (File file : bytecodeFilesOrDirectories) { if (file.isFile() && file.getPath().endsWith(".class")) { LOG.info("SonarQube Squid ClassLoader was expecting a JAR file instead of CLASS file : '" + file.getAbsolutePath() + "'"); } else { files.add(file); } } if (LOG.isDebugEnabled()) { LOG.debug("----- Classpath analyzed by Squid:"); for (File file : files) { LOG.debug(file.getAbsolutePath()); } LOG.debug("-----"); } try { return new SquidClassLoader(files); } catch (Exception e) { throw new IllegalStateException("Can not create ClassLoader", e); } }
private static MethodLookup lookup(String className, String signature, SquidClassLoader classLoader, LookupMethodVisitor methodVisitor) { byte[] bytes = classLoader.getBytesForClass(className); if (bytes == null) { return null; } ClassReader cr = new ClassReader(bytes); LookupClassVisitor lookupVisitor = new LookupClassVisitor(methodVisitor, signature); cr.accept(lookupVisitor, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); if (lookupVisitor.methodFound) { return new MethodLookup(lookupVisitor.isStatic, lookupVisitor.isVarArgs, lookupVisitor.declaredExceptions); } // we didn't succeed to find the method in the class, try recursively on superclasses and interfaces if (lookupVisitor.superClassName != null) { MethodLookup result = lookup(lookupVisitor.superClassName, signature, classLoader, methodVisitor); if (result != null) { return result; } } if (lookupVisitor.interfaces != null) { return Arrays.stream(lookupVisitor.interfaces) .map(iface -> lookup(iface, signature, classLoader, methodVisitor)) .filter(Objects::nonNull) .findAny().orElse(null); } return null; }
/** * Read bytes representing class with name passed as an argument. Modify the class version in bytecode so ASM can read * returned array without issues. * * @param className canonical name of the class (e.g. org.acme.Foo ) * @return bytes or null if class is not found */ @CheckForNull public byte[] getBytesForClass(String className) { try (InputStream is = getResourceAsStream(Convert.bytecodeName(className) + ".class")) { if (is == null) { return null; } return ByteStreams.toByteArray(is); } catch (IOException e) { throw new AnalysisException("An IOException occurred in SonarJava classLoader.",e); } }
@Override protected Class findClass(String name) throws ClassNotFoundException { String resourceName = name.replace('.', '/') + ".class"; for (Loader loader : loaders) { byte[] classBytes = loader.loadBytes(resourceName); if (ArrayUtils.isNotEmpty(classBytes)) { // TODO Godin: definePackage ? return defineClass(name, classBytes, 0, classBytes.length); } } throw new ClassNotFoundException(name); }
public BytecodeScanner scan(Collection<File> bytecodeFilesOrDirectories) { ClassLoader classLoader = ClassLoaderBuilder.create(bytecodeFilesOrDirectories); scanClasses(javaResourceLocator.classKeys(), new AsmClassProviderImpl(classLoader)); // TODO unchecked cast ((SquidClassLoader) classLoader).close(); return this; }
public static SquidClassLoader create(Collection<File> bytecodeFilesOrDirectories) { List<File> files = Lists.newArrayList(); for (File file : bytecodeFilesOrDirectories) { if (file.isFile() && file.getPath().endsWith(".class")) { LOG.info("SonarQube Squid ClassLoader was expecting a JAR file instead of CLASS file : '" + file.getAbsolutePath() + "'"); } else { files.add(file); } } if (LOG.isDebugEnabled()) { LOG.debug("----- Classpath analyzed by Squid:"); for (File file : files) { LOG.debug(file.getAbsolutePath()); } LOG.debug("-----"); } try { return new SquidClassLoader(files); } catch (Exception e) { throw new IllegalStateException("Can not create ClassLoader", e); } } }
private static MethodLookup lookup(String className, String signature, SquidClassLoader classLoader, LookupMethodVisitor methodVisitor) { byte[] bytes = classLoader.getBytesForClass(className); if (bytes == null) { return null; } ClassReader cr = new ClassReader(bytes); LookupClassVisitor lookupVisitor = new LookupClassVisitor(methodVisitor, signature); cr.accept(lookupVisitor, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); if (lookupVisitor.methodFound) { return new MethodLookup(lookupVisitor.isStatic, lookupVisitor.isVarArgs, lookupVisitor.declaredExceptions); } // we didn't succeed to find the method in the class, try recursively on superclasses and interfaces if (lookupVisitor.superClassName != null) { MethodLookup result = lookup(lookupVisitor.superClassName, signature, classLoader, methodVisitor); if (result != null) { return result; } } if (lookupVisitor.interfaces != null) { return Arrays.stream(lookupVisitor.interfaces) .map(iface -> lookup(iface, signature, classLoader, methodVisitor)) .filter(Objects::nonNull) .findAny().orElse(null); } return null; }