/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIESOR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.aries.web.converter.impl; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Attribute; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.signature.SignatureReader; import org.objectweb.asm.signature.SignatureVisitor; public class PackageFinder extends ClassVisitor//AnnotationVisitor, SignatureVisitor, ClassVisitor, //FieldVisitor, MethodVisitor { private static int asmVersion = Opcodes.ASM4; private PackageFinderSignatureVisitor pfsv; private PackageFinderAnnotationVisitor pfav; private PackageFinderFieldVisitor pffv; private PackageFinderMethodVisitor pfmv; public PackageFinder() { super(asmVersion); this.pfsv = new PackageFinderSignatureVisitor(); this.pfav = new PackageFinderAnnotationVisitor(); this.pffv = new PackageFinderFieldVisitor(); this.pfmv = new PackageFinderMethodVisitor(); } private Set<String> packages = new HashSet<String>(); private Set<String> exemptPackages = new HashSet<String>(); // stored value of the signature class name private String signatureOuterClass = null; public Set<String> getImportPackages() { // Remove entries that will be imported by default for (Iterator<String> i = packages.iterator(); i.hasNext();) { if (i.next().startsWith("java.")) i.remove(); } return packages; } public Set<String> getExemptPackages() { return exemptPackages; } private String getPackageName(String name) { String packageName = null; if (name != null) { int index = name.lastIndexOf('/'); if (index > 0) packageName = name.substring(0, index); } return packageName; } private String canonizePackage(String rawPackage) { String result = rawPackage.replace('/', '.'); // handle arrays return result.replaceFirst("^\\[+L", ""); } private void addPackage(String packageName) { if (packageName != null) { packages.add(canonizePackage(packageName)); } } private void addExemptPackage(String packageName) { if (packageName != null) exemptPackages.add(canonizePackage(packageName)); } private void addPackages(String[] packageNames) { if (packageNames != null) { for (String s : packageNames) if (s != null) { packages.add(canonizePackage(s)); } } } private String getResolvedPackageName(String name) { String resolvedName = null; if (name != null) resolvedName = getPackageName(name); return resolvedName; } private String[] getResolvedPackageNames(String[] names) { String[] resolvedNames = null; if (names != null) { resolvedNames = new String[names.length]; int i = 0; for (String s : names) resolvedNames[i++] = getResolvedPackageName(s); } return resolvedNames; } private String getDescriptorInfo(String descriptor) { String type = null; if (descriptor != null) type = getType(Type.getType(descriptor)); return type; } private String[] getMethodDescriptorInfo(String descriptor) { String[] descriptors = null; if (descriptor != null) { Type[] types = Type.getArgumentTypes(descriptor); descriptors = new String[types.length + 1]; descriptors[0] = getType(Type.getReturnType(descriptor)); int i = 1; for (Type t : types) descriptors[i++] = getType(t); } return descriptors; } private String getType(Type t) { String type = null; switch (t.getSort()) { case Type.ARRAY: type = getType(t.getElementType()); break; case Type.OBJECT: type = getPackageName(t.getInternalName()); break; } return type; } private void addSignaturePackages(String signature) { if (signature != null) new SignatureReader(signature).accept(pfsv); } private void addResolvedSignaturePackages(String signature) { if (signature != null) new SignatureReader(signature).acceptType(pfsv); } // // ClassVisitor methods // public void visit(int arg0, int arg1, String name, String signature, String parent, String[] interfaces) { // We dont want to import our own packages so we add this classes package name to the // list of exempt packages. addExemptPackage(getPackageName(name)); if (signature == null) { addPackage(getResolvedPackageName(parent)); addPackages(getResolvedPackageNames(interfaces)); } else addSignaturePackages(signature); } public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { addPackage(getDescriptorInfo(descriptor)); return pfav; } public void visitAttribute(Attribute arg0) { // No-op } public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { if (signature == null) addPackage(getDescriptorInfo(descriptor)); else addResolvedSignaturePackages(signature); if (value instanceof Type) addPackage(getType((Type) value)); return pffv; } public void visitInnerClass(String arg0, String arg1, String arg2, int arg3) { // no-op } public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { if (signature == null) addPackages(getMethodDescriptorInfo(descriptor)); else addSignaturePackages(signature); addPackages(getResolvedPackageNames(exceptions)); return pfmv; } public void visitOuterClass(String arg0, String arg1, String arg2) { // no-op } public void visitSource(String arg0, String arg1) { // no-op } public void visitEnd() { // no-op } public class PackageFinderSignatureVisitor extends SignatureVisitor { public PackageFinderSignatureVisitor() { super(asmVersion); } // // SignatureVisitor methods // public SignatureVisitor visitArrayType() { return pfsv; } public void visitBaseType(char arg0) { // no-op } public SignatureVisitor visitClassBound() { return pfsv; } public void visitClassType(String name) { signatureOuterClass = name; addPackage(getResolvedPackageName(name)); } public void visitInnerClassType(String name) { addPackage(getResolvedPackageName(signatureOuterClass + "$" + name)); } public SignatureVisitor visitExceptionType() { return pfsv; } public void visitFormalTypeParameter(String arg0) { // no-op } public SignatureVisitor visitInterface() { return pfsv; } public SignatureVisitor visitParameterType() { return pfsv; } public SignatureVisitor visitReturnType() { return pfsv; } public SignatureVisitor visitSuperclass() { return pfsv; } public void visitTypeArgument() { // no-op } public SignatureVisitor visitTypeArgument(char arg0) { return pfsv; } public void visitTypeVariable(String arg0) { // no-op } public SignatureVisitor visitInterfaceBound() { return pfsv; } } public class PackageFinderAnnotationVisitor extends AnnotationVisitor { public PackageFinderAnnotationVisitor() { super(asmVersion); } // // AnnotationVisitor Methods // public void visit(String arg0, Object value) { if (value instanceof Type) { addPackage(getType((Type) value)); } } public AnnotationVisitor visitAnnotation(String arg0, String descriptor) { addPackage(getDescriptorInfo(descriptor)); return pfav; } public AnnotationVisitor visitArray(String arg0) { return pfav; } public void visitEnum(String name, String desc, String value) { addPackage(getDescriptorInfo(desc)); } } public class PackageFinderFieldVisitor extends FieldVisitor { public PackageFinderFieldVisitor() { super(asmVersion); } } public class PackageFinderMethodVisitor extends MethodVisitor { public PackageFinderMethodVisitor() { super(asmVersion); } // // MethodVisitor methods // public AnnotationVisitor visitAnnotationDefault() { return pfav; } public void visitCode() { // no-op } public void visitFrame(int arg0, int arg1, Object[] arg2, int arg3, Object[] arg4) { // no-op } public void visitIincInsn(int arg0, int arg1) { // no-op } public void visitInsn(int arg0) { // no-op } public void visitIntInsn(int arg0, int arg1) { // no-op } public void visitJumpInsn(int arg0, Label arg1) { // no-op } public void visitLabel(Label arg0) { // no-op } public void visitLdcInsn(Object type) { if (type instanceof Type) addPackage(getType((Type) type)); } public void visitLineNumber(int arg0, Label arg1) { // no-op } public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) { addResolvedSignaturePackages(signature); } public void visitLookupSwitchInsn(Label arg0, int[] arg1, Label[] arg2) { // no-op } public void visitMaxs(int arg0, int arg1) { // no-op } public void visitMethodInsn(int opcode, String owner, String name, String descriptor) { addPackage(getResolvedPackageName(owner)); addPackages(getMethodDescriptorInfo(descriptor)); } public void visitMultiANewArrayInsn(String descriptor, int arg1) { addPackage(getDescriptorInfo(descriptor)); } public AnnotationVisitor visitParameterAnnotation(int arg0, String descriptor, boolean arg2) { addPackage(getDescriptorInfo(descriptor)); return pfav; } public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) { //no-op } public void visitTryCatchBlock(Label arg0, Label arg1, Label arg2, String type) { addPackage(getResolvedPackageName(type)); } public void visitTypeInsn(int arg0, String type) { addPackage(getResolvedPackageName(type)); } public void visitVarInsn(int arg0, int arg1) { // no-op } public void visitFieldInsn(int opcode, String owner, String name, String descriptor) { addPackage(getResolvedPackageName(owner)); addPackage(getDescriptorInfo(descriptor)); } } }