/*
* 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));
}
}
}