You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xbean-scm@geronimo.apache.org by dj...@apache.org on 2010/03/17 20:06:14 UTC
svn commit: r924423 - in
/geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder:
AbstractFinder.java ClassFinder.java
Author: djencks
Date: Wed Mar 17 19:06:14 2010
New Revision: 924423
URL: http://svn.apache.org/viewvc?rev=924423&view=rev
Log:
XBEAN-145 put the classfile scanning code in an abstract superclass so it can be used by osgi-aware code more easily
Added:
geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/AbstractFinder.java (with props)
Modified:
geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/ClassFinder.java
Added: geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/AbstractFinder.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/AbstractFinder.java?rev=924423&view=auto
==============================================================================
--- geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/AbstractFinder.java (added)
+++ geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/AbstractFinder.java Wed Mar 17 19:06:14 2010
@@ -0,0 +1,759 @@
+/*
+ * 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 WARRANTIES OR 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.xbean.finder;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.commons.EmptyVisitor;
+import org.objectweb.asm.signature.SignatureReader;
+import org.objectweb.asm.signature.SignatureVisitor;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractFinder {
+ private final Map<String, List<Info>> annotated = new HashMap<String, List<Info>>();
+ protected final List<ClassInfo> classInfos = new ArrayList<ClassInfo>();
+ private final List<String> classesNotLoaded = new ArrayList<String>();
+ private final int ASM_FLAGS = ClassReader.SKIP_CODE + ClassReader.SKIP_DEBUG + ClassReader.SKIP_FRAMES;
+
+ protected abstract URL getResource(String className);
+
+ protected abstract Class<?> loadClass(String fixedName) throws ClassNotFoundException;
+
+ public boolean isAnnotationPresent(Class<? extends Annotation> annotation) {
+ List<Info> infos = annotated.get(annotation.getName());
+ return infos != null && !infos.isEmpty();
+ }
+
+ /**
+ * Returns a list of classes that could not be loaded in last invoked findAnnotated* method.
+ * <p/>
+ * The list will only contain entries of classes whose byte code matched the requirements
+ * of last invoked find* method, but were unable to be loaded and included in the results.
+ * <p/>
+ * The list returned is unmodifiable. Once obtained, the returned list will be a live view of the
+ * results from the last findAnnotated* method call.
+ * <p/>
+ * This method is not thread safe.
+ * @return an unmodifiable live view of classes that could not be loaded in previous findAnnotated* call.
+ */
+ public List<String> getClassesNotLoaded() {
+ return Collections.unmodifiableList(classesNotLoaded);
+ }
+
+ public List<Package> findAnnotatedPackages(Class<? extends Annotation> annotation) {
+ classesNotLoaded.clear();
+ List<Package> packages = new ArrayList<Package>();
+ List<Info> infos = getAnnotationInfos(annotation.getName());
+ for (Info info : infos) {
+ if (info instanceof PackageInfo) {
+ PackageInfo packageInfo = (PackageInfo) info;
+ try {
+ Package pkg = packageInfo.get();
+ // double check via proper reflection
+ if (pkg.isAnnotationPresent(annotation)) {
+ packages.add(pkg);
+ }
+ } catch (ClassNotFoundException e) {
+ classesNotLoaded.add(packageInfo.getName());
+ }
+ }
+ }
+ return packages;
+ }
+
+ public List<Class> findAnnotatedClasses(Class<? extends Annotation> annotation) {
+ classesNotLoaded.clear();
+ List<Class> classes = new ArrayList<Class>();
+ List<Info> infos = getAnnotationInfos(annotation.getName());
+ for (Info info : infos) {
+ if (info instanceof ClassInfo) {
+ ClassInfo classInfo = (ClassInfo) info;
+ try {
+ Class clazz = classInfo.get();
+ // double check via proper reflection
+ if (clazz.isAnnotationPresent(annotation)) {
+ classes.add(clazz);
+ }
+ } catch (ClassNotFoundException e) {
+ classesNotLoaded.add(classInfo.getName());
+ }
+ }
+ }
+ return classes;
+ }
+
+ /**
+ * Naive implementation - works extremelly slow O(n^3)
+ *
+ * @param annotation
+ * @return list of directly or indirectly (inherited) annotated classes
+ */
+ public List<Class> findInheritedAnnotatedClasses(Class<? extends Annotation> annotation) {
+ classesNotLoaded.clear();
+ List<Class> classes = new ArrayList<Class>();
+ List<Info> infos = getAnnotationInfos(annotation.getName());
+ for (Info info : infos) {
+ try {
+ if(info instanceof ClassInfo){
+ classes.add(((ClassInfo) info).get());
+ }
+ } catch (ClassNotFoundException cnfe) {
+ // TODO: ignored, but a log message would be appropriate
+ }
+ }
+ boolean annClassFound;
+ List<ClassInfo> tempClassInfos = new ArrayList<ClassInfo>(classInfos);
+ do {
+ annClassFound = false;
+ for (int pos = 0; pos < tempClassInfos.size(); pos++) {
+ ClassInfo classInfo = tempClassInfos.get(pos);
+ try {
+ // check whether any superclass is annotated
+ String superType = classInfo.getSuperType();
+ for (Class clazz : classes) {
+ if (superType.equals(clazz.getName())) {
+ classes.add(classInfo.get());
+ tempClassInfos.remove(pos);
+ annClassFound = true;
+ break;
+ }
+ }
+ // check whether any interface is annotated
+ List<String> interfces = classInfo.getInterfaces();
+ for (String interfce: interfces) {
+ for (Class clazz : classes) {
+ if (interfce.replaceFirst("<.*>","").equals(clazz.getName())) {
+ classes.add(classInfo.get());
+ tempClassInfos.remove(pos);
+ annClassFound = true;
+ break;
+ }
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ classesNotLoaded.add(classInfo.getName());
+ } catch (NoClassDefFoundError e) {
+ classesNotLoaded.add(classInfo.getName());
+ }
+ }
+ } while (annClassFound);
+ return classes;
+ }
+
+ public List<Method> findAnnotatedMethods(Class<? extends Annotation> annotation) {
+ classesNotLoaded.clear();
+ List<ClassInfo> seen = new ArrayList<ClassInfo>();
+ List<Method> methods = new ArrayList<Method>();
+ List<Info> infos = getAnnotationInfos(annotation.getName());
+ for (Info info : infos) {
+ if (info instanceof MethodInfo && !info.getName().equals("<init>")) {
+ MethodInfo methodInfo = (MethodInfo) info;
+ ClassInfo classInfo = methodInfo.getDeclaringClass();
+
+ if (seen.contains(classInfo)) continue;
+
+ seen.add(classInfo);
+
+ try {
+ Class clazz = classInfo.get();
+ for (Method method : clazz.getDeclaredMethods()) {
+ if (method.isAnnotationPresent(annotation)) {
+ methods.add(method);
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ classesNotLoaded.add(classInfo.getName());
+ }
+ }
+ }
+ return methods;
+ }
+
+ public List<Constructor> findAnnotatedConstructors(Class<? extends Annotation> annotation) {
+ classesNotLoaded.clear();
+ List<ClassInfo> seen = new ArrayList<ClassInfo>();
+ List<Constructor> constructors = new ArrayList<Constructor>();
+ List<Info> infos = getAnnotationInfos(annotation.getName());
+ for (Info info : infos) {
+ if (info instanceof MethodInfo && info.getName().equals("<init>")) {
+ MethodInfo methodInfo = (MethodInfo) info;
+ ClassInfo classInfo = methodInfo.getDeclaringClass();
+
+ if (seen.contains(classInfo)) continue;
+
+ seen.add(classInfo);
+
+ try {
+ Class clazz = classInfo.get();
+ for (Constructor constructor : clazz.getConstructors()) {
+ if (constructor.isAnnotationPresent(annotation)) {
+ constructors.add(constructor);
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ classesNotLoaded.add(classInfo.getName());
+ }
+ }
+ }
+ return constructors;
+ }
+
+ public List<Field> findAnnotatedFields(Class<? extends Annotation> annotation) {
+ classesNotLoaded.clear();
+ List<ClassInfo> seen = new ArrayList<ClassInfo>();
+ List<Field> fields = new ArrayList<Field>();
+ List<Info> infos = getAnnotationInfos(annotation.getName());
+ for (Info info : infos) {
+ if (info instanceof FieldInfo) {
+ FieldInfo fieldInfo = (FieldInfo) info;
+ ClassInfo classInfo = fieldInfo.getDeclaringClass();
+
+ if (seen.contains(classInfo)) continue;
+
+ seen.add(classInfo);
+
+ try {
+ Class clazz = classInfo.get();
+ for (Field field : clazz.getDeclaredFields()) {
+ if (field.isAnnotationPresent(annotation)) {
+ fields.add(field);
+ }
+ }
+ } catch (ClassNotFoundException e) {
+ classesNotLoaded.add(classInfo.getName());
+ }
+ }
+ }
+ return fields;
+ }
+
+ public List<Class> findClassesInPackage(String packageName, boolean recursive) {
+ classesNotLoaded.clear();
+ List<Class> classes = new ArrayList<Class>();
+ for (ClassInfo classInfo : classInfos) {
+ try {
+ if (recursive && classInfo.getPackageName().startsWith(packageName)){
+ classes.add(classInfo.get());
+ } else if (classInfo.getPackageName().equals(packageName)){
+ classes.add(classInfo.get());
+ }
+ } catch (ClassNotFoundException e) {
+ classesNotLoaded.add(classInfo.getName());
+ }
+ }
+ return classes;
+ }
+
+ protected List<Info> getAnnotationInfos(String name) {
+ List<Info> infos = annotated.get(name);
+ if (infos == null) {
+ infos = new ArrayList<Info>();
+ annotated.put(name, infos);
+ }
+ return infos;
+ }
+
+ protected void readClassDef(InputStream in) throws IOException {
+ ClassReader classReader = new ClassReader(in);
+ classReader.accept(new InfoBuildingVisitor(), ASM_FLAGS);
+ }
+
+ public class Annotatable {
+ private final List<ClassFinder.AnnotationInfo> annotations = new ArrayList<ClassFinder.AnnotationInfo>();
+
+ public Annotatable(AnnotatedElement element) {
+ for (Annotation annotation : element.getAnnotations()) {
+ annotations.add(new ClassFinder.AnnotationInfo(annotation.annotationType().getName()));
+ }
+ }
+
+ public Annotatable() {
+ }
+
+ public List<ClassFinder.AnnotationInfo> getAnnotations() {
+ return annotations;
+ }
+
+ }
+
+ public static interface Info {
+ String getName();
+
+ List<ClassFinder.AnnotationInfo> getAnnotations();
+ }
+
+ public class PackageInfo extends Annotatable implements Info {
+ private final String name;
+ private final ClassFinder.ClassInfo info;
+ private final Package pkg;
+
+ public PackageInfo(Package pkg){
+ super(pkg);
+ this.pkg = pkg;
+ this.name = pkg.getName();
+ this.info = null;
+ }
+
+ public PackageInfo(String name) {
+ info = new ClassFinder.ClassInfo(name, null);
+ this.name = name;
+ this.pkg = null;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Package get() throws ClassNotFoundException {
+ return (pkg != null)?pkg:info.get().getPackage();
+ }
+ }
+
+ public class ClassInfo extends Annotatable implements Info {
+ private String name;
+ private final List<ClassFinder.MethodInfo> methods = new ArrayList<ClassFinder.MethodInfo>();
+ private final List<ClassFinder.MethodInfo> constructors = new ArrayList<ClassFinder.MethodInfo>();
+ private String superType;
+ private final List<String> interfaces = new ArrayList<String>();
+ private final List<ClassFinder.FieldInfo> fields = new ArrayList<ClassFinder.FieldInfo>();
+ private Class<?> clazz;
+ private ClassNotFoundException notFound;
+
+ public ClassInfo(Class clazz) {
+ super(clazz);
+ this.clazz = clazz;
+ this.name = clazz.getName();
+ Class superclass = clazz.getSuperclass();
+ this.superType = superclass != null ? superclass.getName(): null;
+ }
+
+ public ClassInfo(String name, String superType) {
+ this.name = name;
+ this.superType = superType;
+ }
+
+ public String getPackageName(){
+ return name.substring(0,name.lastIndexOf("."));
+ }
+
+ public List<ClassFinder.MethodInfo> getConstructors() {
+ return constructors;
+ }
+
+ public List<String> getInterfaces() {
+ return interfaces;
+ }
+
+ public List<ClassFinder.FieldInfo> getFields() {
+ return fields;
+ }
+
+ public List<ClassFinder.MethodInfo> getMethods() {
+ return methods;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getSuperType() {
+ return superType;
+ }
+
+ public Class get() throws ClassNotFoundException {
+ if (clazz != null) return clazz;
+ if (notFound != null) throw notFound;
+ try {
+ String fixedName = name.replaceFirst("<.*>", "");
+ this.clazz = loadClass(fixedName);
+ return clazz;
+ } catch (ClassNotFoundException notFound) {
+ classesNotLoaded.add(name);
+ this.notFound = notFound;
+ throw notFound;
+ }
+ }
+
+
+ public String toString() {
+ return name;
+ }
+ }
+
+ public class MethodInfo extends Annotatable implements Info {
+ private final ClassInfo declaringClass;
+ private final String returnType;
+ private final String name;
+ private final List<List<ClassFinder.AnnotationInfo>> parameterAnnotations = new ArrayList<List<ClassFinder.AnnotationInfo>>();
+
+ public MethodInfo(ClassInfo info, Constructor constructor){
+ super(constructor);
+ this.declaringClass = info;
+ this.name = "<init>";
+ this.returnType = Void.TYPE.getName();
+ }
+
+ public MethodInfo(ClassInfo info, Method method){
+ super(method);
+ this.declaringClass = info;
+ this.name = method.getName();
+ this.returnType = method.getReturnType().getName();
+ }
+
+ public MethodInfo(ClassInfo declarignClass, String name, String returnType) {
+ this.declaringClass = declarignClass;
+ this.name = name;
+ this.returnType = returnType;
+ }
+
+ public List<List<ClassFinder.AnnotationInfo>> getParameterAnnotations() {
+ return parameterAnnotations;
+ }
+
+ public List<ClassFinder.AnnotationInfo> getParameterAnnotations(int index) {
+ if (index >= parameterAnnotations.size()) {
+ for (int i = parameterAnnotations.size(); i <= index; i++) {
+ List<ClassFinder.AnnotationInfo> annotationInfos = new ArrayList<ClassFinder.AnnotationInfo>();
+ parameterAnnotations.add(i, annotationInfos);
+ }
+ }
+ return parameterAnnotations.get(index);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public ClassInfo getDeclaringClass() {
+ return declaringClass;
+ }
+
+ public String getReturnType() {
+ return returnType;
+ }
+
+ public String toString() {
+ return declaringClass + "@" + name;
+ }
+ }
+
+ public class FieldInfo extends Annotatable implements Info {
+ private final String name;
+ private final String type;
+ private final ClassInfo declaringClass;
+
+ public FieldInfo(ClassInfo info, Field field){
+ super(field);
+ this.declaringClass = info;
+ this.name = field.getName();
+ this.type = field.getType().getName();
+ }
+
+ public FieldInfo(ClassInfo declaringClass, String name, String type) {
+ this.declaringClass = declaringClass;
+ this.name = name;
+ this.type = type;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public ClassInfo getDeclaringClass() {
+ return declaringClass;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String toString() {
+ return declaringClass + "#" + name;
+ }
+ }
+
+ public class AnnotationInfo extends Annotatable implements Info {
+ private final String name;
+
+ public AnnotationInfo(Annotation annotation){
+ this(annotation.getClass().getName());
+ }
+
+ public AnnotationInfo(Class<? extends Annotation> annotation) {
+ this.name = annotation.getName().intern();
+ }
+
+ public AnnotationInfo(String name) {
+ name = name.replaceAll("^L|;$", "");
+ name = name.replace('/', '.');
+ this.name = name.intern();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String toString() {
+ return name;
+ }
+ }
+
+ public class InfoBuildingVisitor extends EmptyVisitor {
+ private Info info;
+
+ public InfoBuildingVisitor() {
+ }
+
+ public InfoBuildingVisitor(Info info) {
+ this.info = info;
+ }
+
+ public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+ if (name.endsWith("package-info")) {
+ info = new PackageInfo(javaName(name));
+ } else {
+ ClassInfo classInfo = new ClassInfo(javaName(name), javaName(superName));
+
+ if (signature == null) {
+ for (String interfce : interfaces) {
+ classInfo.getInterfaces().add(javaName(interfce));
+ }
+ } else {
+ // the class uses generics
+ new SignatureReader(signature).accept(new ClassFinder.GenericAwareInfoBuildingVisitor(ClassFinder.GenericAwareInfoBuildingVisitor.TYPE.CLASS, classInfo));
+ }
+ info = classInfo;
+ classInfos.add(classInfo);
+ }
+ }
+
+ private String javaName(String name) {
+ return (name == null)? null:name.replace('/', '.');
+ }
+
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ AnnotationInfo annotationInfo = new AnnotationInfo(desc);
+ info.getAnnotations().add(annotationInfo);
+ getAnnotationInfos(annotationInfo.getName()).add(info);
+ return new ClassFinder.InfoBuildingVisitor(annotationInfo);
+ }
+
+ public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
+ ClassInfo classInfo = ((ClassInfo) info);
+ FieldInfo fieldInfo = new FieldInfo(classInfo, name, desc);
+ classInfo.getFields().add(fieldInfo);
+ return new ClassFinder.InfoBuildingVisitor(fieldInfo);
+ }
+
+ public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
+ ClassInfo classInfo = ((ClassInfo) info);
+ MethodInfo methodInfo = new MethodInfo(classInfo, name, desc);
+ classInfo.getMethods().add(methodInfo);
+ return new ClassFinder.InfoBuildingVisitor(methodInfo);
+ }
+
+ public AnnotationVisitor visitParameterAnnotation(int param, String desc, boolean visible) {
+ MethodInfo methodInfo = ((MethodInfo) info);
+ List<AnnotationInfo> annotationInfos = methodInfo.getParameterAnnotations(param);
+ AnnotationInfo annotationInfo = new AnnotationInfo(desc);
+ annotationInfos.add(annotationInfo);
+ return new ClassFinder.InfoBuildingVisitor(annotationInfo);
+ }
+ }
+
+ public static class GenericAwareInfoBuildingVisitor implements SignatureVisitor {
+
+ public enum TYPE {
+ CLASS
+ }
+
+ public enum STATE {
+ BEGIN, END, SUPERCLASS, INTERFACE, FORMAL_TYPE_PARAM
+ }
+
+ private Info info;
+ private ClassFinder.GenericAwareInfoBuildingVisitor.TYPE type;
+ private ClassFinder.GenericAwareInfoBuildingVisitor.STATE state;
+
+ private static boolean debug = false;
+
+ public GenericAwareInfoBuildingVisitor() {
+ }
+
+ public GenericAwareInfoBuildingVisitor(ClassFinder.GenericAwareInfoBuildingVisitor.TYPE type, Info info) {
+ this.type = type;
+ this.info = info;
+ this.state = ClassFinder.GenericAwareInfoBuildingVisitor.STATE.BEGIN;
+ }
+
+ public void visitFormalTypeParameter(String s) {
+ if (debug) System.out.println(" s=" + s);
+ switch (state) {
+ case BEGIN:
+ ((ClassInfo) info).name += "<" + s;
+ }
+ state = ClassFinder.GenericAwareInfoBuildingVisitor.STATE.FORMAL_TYPE_PARAM;
+ }
+
+ public SignatureVisitor visitClassBound() {
+ if (debug) System.out.println(" visitClassBound()");
+ return this;
+ }
+
+ public SignatureVisitor visitInterfaceBound() {
+ if (debug) System.out.println(" visitInterfaceBound()");
+ return this;
+ }
+
+ public SignatureVisitor visitSuperclass() {
+ if (debug) System.out.println(" visitSuperclass()");
+ state = ClassFinder.GenericAwareInfoBuildingVisitor.STATE.SUPERCLASS;
+ return this;
+ }
+
+ public SignatureVisitor visitInterface() {
+ if (debug) System.out.println(" visitInterface()");
+ ((ClassInfo) info).getInterfaces().add("");
+ state = ClassFinder.GenericAwareInfoBuildingVisitor.STATE.INTERFACE;
+ return this;
+ }
+
+ public SignatureVisitor visitParameterType() {
+ if (debug) System.out.println(" visitParameterType()");
+ return this;
+ }
+
+ public SignatureVisitor visitReturnType() {
+ if (debug) System.out.println(" visitReturnType()");
+ return this;
+ }
+
+ public SignatureVisitor visitExceptionType() {
+ if (debug) System.out.println(" visitExceptionType()");
+ return this;
+ }
+
+ public void visitBaseType(char c) {
+ if (debug) System.out.println(" visitBaseType(" + c + ")");
+ }
+
+ public void visitTypeVariable(String s) {
+ if (debug) System.out.println(" visitTypeVariable(" + s + ")");
+ }
+
+ public SignatureVisitor visitArrayType() {
+ if (debug) System.out.println(" visitArrayType()");
+ return this;
+ }
+
+ public void visitClassType(String s) {
+ if (debug) System.out.println(" visitClassType(" + s + ")");
+ switch (state) {
+ case INTERFACE:
+ List<String> interfces = ((ClassInfo) info).getInterfaces();
+ int idx = interfces.size() - 1;
+ String interfce = interfces.get(idx);
+ if (interfce.length() == 0) {
+ interfce = javaName(s);
+ } else {
+ interfce += javaName(s);
+ }
+ interfces.set(idx, interfce);
+ break;
+ case SUPERCLASS:
+ if (!s.equals("java/lang/Object")) {
+ ((ClassInfo) info).superType = javaName(s);
+ }
+ }
+ }
+
+ public void visitInnerClassType(String s) {
+ if (debug) System.out.println(" visitInnerClassType(" + s + ")");
+ }
+
+ public void visitTypeArgument() {
+ if (debug) System.out.println(" visitTypeArgument()");
+ switch (state) {
+ case INTERFACE:
+ List<String> interfces = ((ClassInfo) info).getInterfaces();
+ int idx = interfces.size() - 1;
+ String interfce = interfces.get(idx);
+ interfce += "<";
+ interfces.set(idx, interfce);
+ }
+ }
+
+ public SignatureVisitor visitTypeArgument(char c) {
+ if (debug) System.out.println(" visitTypeArgument(" + c + ")");
+ switch (state) {
+ case INTERFACE:
+ List<String> interfces = ((ClassInfo) info).getInterfaces();
+ int idx = interfces.size() - 1;
+ String interfce = interfces.get(idx);
+ interfce += "<";
+ interfces.set(idx, interfce);
+ }
+ return this;
+ }
+
+ public void visitEnd() {
+ if (debug) System.out.println(" visitEnd()");
+ switch (state) {
+ case INTERFACE:
+ List<String> interfces = ((ClassInfo) info).getInterfaces();
+ int idx = interfces.size() - 1;
+ String interfce = interfces.get(idx);
+ interfce += ">";
+ interfces.set(idx, interfce);
+ break;
+ case FORMAL_TYPE_PARAM:
+ String name = ((ClassInfo) info).name;
+ if (name.contains("<")) {
+ ((ClassInfo) info).name += ">";
+ }
+ }
+ state = ClassFinder.GenericAwareInfoBuildingVisitor.STATE.END;
+ }
+
+ private String javaName(String name) {
+ return (name == null)? null:name.replace('/', '.');
+ }
+
+ }
+}
Propchange: geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/AbstractFinder.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/AbstractFinder.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/AbstractFinder.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/ClassFinder.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/ClassFinder.java?rev=924423&r1=924422&r2=924423&view=diff
==============================================================================
--- geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/ClassFinder.java (original)
+++ geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/ClassFinder.java Wed Mar 17 19:06:14 2010
@@ -16,33 +16,19 @@
*/
package org.apache.xbean.finder;
-import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.FieldVisitor;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.commons.EmptyVisitor;
-import org.objectweb.asm.signature.SignatureReader;
-import org.objectweb.asm.signature.SignatureVisitor;
-
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
-import java.lang.reflect.AnnotatedElement;
-import java.net.URL;
import java.net.JarURLConnection;
+import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
@@ -61,13 +47,9 @@ import java.util.jar.JarInputStream;
* @author David Blevins
* @version $Rev$ $Date$
*/
-public class ClassFinder {
- private final Map<String, List<Info>> annotated = new HashMap<String, List<Info>>();
- private final List<ClassInfo> classInfos = new ArrayList<ClassInfo>();
+public class ClassFinder extends AbstractFinder {
private final ClassLoader classLoader;
- private final List<String> classesNotLoaded = new ArrayList<String>();
- private final int ASM_FLAGS = ClassReader.SKIP_CODE + ClassReader.SKIP_DEBUG + ClassReader.SKIP_FRAMES;
/**
* Creates a ClassFinder that will search the urls in the specified classloader
@@ -188,231 +170,6 @@ public class ClassFinder {
}
}
- public boolean isAnnotationPresent(Class<? extends Annotation> annotation) {
- List<Info> infos = annotated.get(annotation.getName());
- return infos != null && !infos.isEmpty();
- }
-
- /**
- * Returns a list of classes that could not be loaded in last invoked findAnnotated* method.
- * <p/>
- * The list will only contain entries of classes whose byte code matched the requirements
- * of last invoked find* method, but were unable to be loaded and included in the results.
- * <p/>
- * The list returned is unmodifiable. Once obtained, the returned list will be a live view of the
- * results from the last findAnnotated* method call.
- * <p/>
- * This method is not thread safe.
- * @return an unmodifiable live view of classes that could not be loaded in previous findAnnotated* call.
- */
- public List<String> getClassesNotLoaded() {
- return Collections.unmodifiableList(classesNotLoaded);
- }
-
- public List<Package> findAnnotatedPackages(Class<? extends Annotation> annotation) {
- classesNotLoaded.clear();
- List<Package> packages = new ArrayList<Package>();
- List<Info> infos = getAnnotationInfos(annotation.getName());
- for (Info info : infos) {
- if (info instanceof PackageInfo) {
- PackageInfo packageInfo = (PackageInfo) info;
- try {
- Package pkg = packageInfo.get();
- // double check via proper reflection
- if (pkg.isAnnotationPresent(annotation)) {
- packages.add(pkg);
- }
- } catch (ClassNotFoundException e) {
- classesNotLoaded.add(packageInfo.getName());
- }
- }
- }
- return packages;
- }
-
- public List<Class> findAnnotatedClasses(Class<? extends Annotation> annotation) {
- classesNotLoaded.clear();
- List<Class> classes = new ArrayList<Class>();
- List<Info> infos = getAnnotationInfos(annotation.getName());
- for (Info info : infos) {
- if (info instanceof ClassInfo) {
- ClassInfo classInfo = (ClassInfo) info;
- try {
- Class clazz = classInfo.get();
- // double check via proper reflection
- if (clazz.isAnnotationPresent(annotation)) {
- classes.add(clazz);
- }
- } catch (ClassNotFoundException e) {
- classesNotLoaded.add(classInfo.getName());
- }
- }
- }
- return classes;
- }
-
- /**
- * Naive implementation - works extremelly slow O(n^3)
- *
- * @param annotation
- * @return list of directly or indirectly (inherited) annotated classes
- */
- public List<Class> findInheritedAnnotatedClasses(Class<? extends Annotation> annotation) {
- classesNotLoaded.clear();
- List<Class> classes = new ArrayList<Class>();
- List<Info> infos = getAnnotationInfos(annotation.getName());
- for (Info info : infos) {
- try {
- if(info instanceof ClassInfo){
- classes.add(((ClassInfo) info).get());
- }
- } catch (ClassNotFoundException cnfe) {
- // TODO: ignored, but a log message would be appropriate
- }
- }
- boolean annClassFound;
- List<ClassInfo> tempClassInfos = new ArrayList<ClassInfo>(classInfos);
- do {
- annClassFound = false;
- for (int pos = 0; pos < tempClassInfos.size(); pos++) {
- ClassInfo classInfo = tempClassInfos.get(pos);
- try {
- // check whether any superclass is annotated
- String superType = classInfo.getSuperType();
- for (Class clazz : classes) {
- if (superType.equals(clazz.getName())) {
- classes.add(classInfo.get());
- tempClassInfos.remove(pos);
- annClassFound = true;
- break;
- }
- }
- // check whether any interface is annotated
- List<String> interfces = classInfo.getInterfaces();
- for (String interfce: interfces) {
- for (Class clazz : classes) {
- if (interfce.replaceFirst("<.*>","").equals(clazz.getName())) {
- classes.add(classInfo.get());
- tempClassInfos.remove(pos);
- annClassFound = true;
- break;
- }
- }
- }
- } catch (ClassNotFoundException e) {
- classesNotLoaded.add(classInfo.getName());
- } catch (NoClassDefFoundError e) {
- classesNotLoaded.add(classInfo.getName());
- }
- }
- } while (annClassFound);
- return classes;
- }
-
- public List<Method> findAnnotatedMethods(Class<? extends Annotation> annotation) {
- classesNotLoaded.clear();
- List<ClassInfo> seen = new ArrayList<ClassInfo>();
- List<Method> methods = new ArrayList<Method>();
- List<Info> infos = getAnnotationInfos(annotation.getName());
- for (Info info : infos) {
- if (info instanceof MethodInfo && !info.getName().equals("<init>")) {
- MethodInfo methodInfo = (MethodInfo) info;
- ClassInfo classInfo = methodInfo.getDeclaringClass();
-
- if (seen.contains(classInfo)) continue;
-
- seen.add(classInfo);
-
- try {
- Class clazz = classInfo.get();
- for (Method method : clazz.getDeclaredMethods()) {
- if (method.isAnnotationPresent(annotation)) {
- methods.add(method);
- }
- }
- } catch (ClassNotFoundException e) {
- classesNotLoaded.add(classInfo.getName());
- }
- }
- }
- return methods;
- }
-
- public List<Constructor> findAnnotatedConstructors(Class<? extends Annotation> annotation) {
- classesNotLoaded.clear();
- List<ClassInfo> seen = new ArrayList<ClassInfo>();
- List<Constructor> constructors = new ArrayList<Constructor>();
- List<Info> infos = getAnnotationInfos(annotation.getName());
- for (Info info : infos) {
- if (info instanceof MethodInfo && info.getName().equals("<init>")) {
- MethodInfo methodInfo = (MethodInfo) info;
- ClassInfo classInfo = methodInfo.getDeclaringClass();
-
- if (seen.contains(classInfo)) continue;
-
- seen.add(classInfo);
-
- try {
- Class clazz = classInfo.get();
- for (Constructor constructor : clazz.getConstructors()) {
- if (constructor.isAnnotationPresent(annotation)) {
- constructors.add(constructor);
- }
- }
- } catch (ClassNotFoundException e) {
- classesNotLoaded.add(classInfo.getName());
- }
- }
- }
- return constructors;
- }
-
- public List<Field> findAnnotatedFields(Class<? extends Annotation> annotation) {
- classesNotLoaded.clear();
- List<ClassInfo> seen = new ArrayList<ClassInfo>();
- List<Field> fields = new ArrayList<Field>();
- List<Info> infos = getAnnotationInfos(annotation.getName());
- for (Info info : infos) {
- if (info instanceof FieldInfo) {
- FieldInfo fieldInfo = (FieldInfo) info;
- ClassInfo classInfo = fieldInfo.getDeclaringClass();
-
- if (seen.contains(classInfo)) continue;
-
- seen.add(classInfo);
-
- try {
- Class clazz = classInfo.get();
- for (Field field : clazz.getDeclaredFields()) {
- if (field.isAnnotationPresent(annotation)) {
- fields.add(field);
- }
- }
- } catch (ClassNotFoundException e) {
- classesNotLoaded.add(classInfo.getName());
- }
- }
- }
- return fields;
- }
-
- public List<Class> findClassesInPackage(String packageName, boolean recursive) {
- classesNotLoaded.clear();
- List<Class> classes = new ArrayList<Class>();
- for (ClassInfo classInfo : classInfos) {
- try {
- if (recursive && classInfo.getPackageName().startsWith(packageName)){
- classes.add(classInfo.get());
- } else if (classInfo.getPackageName().equals(packageName)){
- classes.add(classInfo.get());
- }
- } catch (ClassNotFoundException e) {
- classesNotLoaded.add(classInfo.getName());
- }
- }
- return classes;
- }
-
private static Collection<URL> getUrls(ClassLoader classLoader, boolean excludeParent) throws IOException {
return getUrls(classLoader, excludeParent? classLoader.getParent() : null);
}
@@ -425,6 +182,18 @@ public class ClassFinder {
return urlSet.getUrls();
}
+ @Override
+ protected URL getResource(String className) {
+ return classLoader.getResource(className);
+ }
+
+ @Override
+ protected Class<?> loadClass(String fixedName) throws ClassNotFoundException {
+ return classLoader.loadClass(fixedName);
+ }
+
+
+
private List<String> file(URL location) {
List<String> classNames = new ArrayList<String>();
File dir = new File(URLDecoder.decode(location.getPath()));
@@ -484,264 +253,16 @@ public class ClassFinder {
return classNames;
}
- public class Annotatable {
- private final List<AnnotationInfo> annotations = new ArrayList<AnnotationInfo>();
-
- public Annotatable(AnnotatedElement element) {
- for (Annotation annotation : element.getAnnotations()) {
- annotations.add(new AnnotationInfo(annotation.annotationType().getName()));
- }
- }
-
- public Annotatable() {
- }
-
- public List<AnnotationInfo> getAnnotations() {
- return annotations;
- }
-
- }
-
- public static interface Info {
- String getName();
-
- List<AnnotationInfo> getAnnotations();
- }
-
- public class PackageInfo extends Annotatable implements Info {
- private final String name;
- private final ClassInfo info;
- private final Package pkg;
-
- public PackageInfo(Package pkg){
- super(pkg);
- this.pkg = pkg;
- this.name = pkg.getName();
- this.info = null;
- }
-
- public PackageInfo(String name) {
- info = new ClassInfo(name, null);
- this.name = name;
- this.pkg = null;
- }
-
- public String getName() {
- return name;
- }
-
- public Package get() throws ClassNotFoundException {
- return (pkg != null)?pkg:info.get().getPackage();
- }
- }
-
- public class ClassInfo extends Annotatable implements Info {
- private String name;
- private final List<MethodInfo> methods = new ArrayList<MethodInfo>();
- private final List<MethodInfo> constructors = new ArrayList<MethodInfo>();
- private String superType;
- private final List<String> interfaces = new ArrayList<String>();
- private final List<FieldInfo> fields = new ArrayList<FieldInfo>();
- private Class<?> clazz;
- private ClassNotFoundException notFound;
-
- public ClassInfo(Class clazz) {
- super(clazz);
- this.clazz = clazz;
- this.name = clazz.getName();
- Class superclass = clazz.getSuperclass();
- this.superType = superclass != null ? superclass.getName(): null;
- }
-
- public ClassInfo(String name, String superType) {
- this.name = name;
- this.superType = superType;
- }
-
- public String getPackageName(){
- return name.substring(0,name.lastIndexOf("."));
- }
-
- public List<MethodInfo> getConstructors() {
- return constructors;
- }
-
- public List<String> getInterfaces() {
- return interfaces;
- }
-
- public List<FieldInfo> getFields() {
- return fields;
- }
-
- public List<MethodInfo> getMethods() {
- return methods;
- }
-
- public String getName() {
- return name;
- }
-
- public String getSuperType() {
- return superType;
- }
-
- public Class get() throws ClassNotFoundException {
- if (clazz != null) return clazz;
- if (notFound != null) throw notFound;
- try {
- this.clazz = classLoader.loadClass(name.replaceFirst("<.*>",""));
- return clazz;
- } catch (ClassNotFoundException notFound) {
- classesNotLoaded.add(name);
- this.notFound = notFound;
- throw notFound;
- }
- }
-
- public String toString() {
- return name;
- }
- }
-
- public class MethodInfo extends Annotatable implements Info {
- private final ClassInfo declaringClass;
- private final String returnType;
- private final String name;
- private final List<List<AnnotationInfo>> parameterAnnotations = new ArrayList<List<AnnotationInfo>>();
-
- public MethodInfo(ClassInfo info, Constructor constructor){
- super(constructor);
- this.declaringClass = info;
- this.name = "<init>";
- this.returnType = Void.TYPE.getName();
- }
-
- public MethodInfo(ClassInfo info, Method method){
- super(method);
- this.declaringClass = info;
- this.name = method.getName();
- this.returnType = method.getReturnType().getName();
- }
-
- public MethodInfo(ClassInfo declarignClass, String name, String returnType) {
- this.declaringClass = declarignClass;
- this.name = name;
- this.returnType = returnType;
- }
-
- public List<List<AnnotationInfo>> getParameterAnnotations() {
- return parameterAnnotations;
- }
-
- public List<AnnotationInfo> getParameterAnnotations(int index) {
- if (index >= parameterAnnotations.size()) {
- for (int i = parameterAnnotations.size(); i <= index; i++) {
- List<AnnotationInfo> annotationInfos = new ArrayList<AnnotationInfo>();
- parameterAnnotations.add(i, annotationInfos);
- }
- }
- return parameterAnnotations.get(index);
- }
-
- public String getName() {
- return name;
- }
-
- public ClassInfo getDeclaringClass() {
- return declaringClass;
- }
-
- public String getReturnType() {
- return returnType;
- }
-
- public String toString() {
- return declaringClass + "@" + name;
- }
- }
-
- public class FieldInfo extends Annotatable implements Info {
- private final String name;
- private final String type;
- private final ClassInfo declaringClass;
-
- public FieldInfo(ClassInfo info, Field field){
- super(field);
- this.declaringClass = info;
- this.name = field.getName();
- this.type = field.getType().getName();
- }
-
- public FieldInfo(ClassInfo declaringClass, String name, String type) {
- this.declaringClass = declaringClass;
- this.name = name;
- this.type = type;
- }
-
- public String getName() {
- return name;
- }
-
- public ClassInfo getDeclaringClass() {
- return declaringClass;
- }
-
- public String getType() {
- return type;
- }
-
- public String toString() {
- return declaringClass + "#" + name;
- }
- }
-
- public class AnnotationInfo extends Annotatable implements Info {
- private final String name;
-
- public AnnotationInfo(Annotation annotation){
- this(annotation.getClass().getName());
- }
-
- public AnnotationInfo(Class<? extends Annotation> annotation) {
- this.name = annotation.getName().intern();
- }
-
- public AnnotationInfo(String name) {
- name = name.replaceAll("^L|;$", "");
- name = name.replace('/', '.');
- this.name = name.intern();
- }
-
- public String getName() {
- return name;
- }
-
- public String toString() {
- return name;
- }
- }
-
- private List<Info> getAnnotationInfos(String name) {
- List<Info> infos = annotated.get(name);
- if (infos == null) {
- infos = new ArrayList<Info>();
- annotated.put(name, infos);
- }
- return infos;
- }
-
- private void readClassDef(String className) {
+ protected void readClassDef(String className) {
if (!className.endsWith(".class")) {
className = className.replace('.', '/') + ".class";
}
try {
- URL resource = classLoader.getResource(className);
+ URL resource = getResource(className);
if (resource != null) {
InputStream in = resource.openStream();
try {
- ClassReader classReader = new ClassReader(in);
- classReader.accept(new InfoBuildingVisitor(), ASM_FLAGS);
+ readClassDef(in);
} finally {
in.close();
}
@@ -753,227 +274,4 @@ public class ClassFinder {
}
}
-
- public class InfoBuildingVisitor extends EmptyVisitor {
- private Info info;
-
- public InfoBuildingVisitor() {
- }
-
- public InfoBuildingVisitor(Info info) {
- this.info = info;
- }
-
- public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
- if (name.endsWith("package-info")) {
- info = new PackageInfo(javaName(name));
- } else {
- ClassInfo classInfo = new ClassInfo(javaName(name), javaName(superName));
-
- if (signature == null) {
- for (String interfce : interfaces) {
- classInfo.getInterfaces().add(javaName(interfce));
- }
- } else {
- // the class uses generics
- new SignatureReader(signature).accept(new GenericAwareInfoBuildingVisitor(GenericAwareInfoBuildingVisitor.TYPE.CLASS, classInfo));
- }
- info = classInfo;
- classInfos.add(classInfo);
- }
- }
-
- private String javaName(String name) {
- return (name == null)? null:name.replace('/', '.');
- }
-
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- AnnotationInfo annotationInfo = new AnnotationInfo(desc);
- info.getAnnotations().add(annotationInfo);
- getAnnotationInfos(annotationInfo.getName()).add(info);
- return new InfoBuildingVisitor(annotationInfo);
- }
-
- public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
- ClassInfo classInfo = ((ClassInfo) info);
- FieldInfo fieldInfo = new FieldInfo(classInfo, name, desc);
- classInfo.getFields().add(fieldInfo);
- return new InfoBuildingVisitor(fieldInfo);
- }
-
- public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
- ClassInfo classInfo = ((ClassInfo) info);
- MethodInfo methodInfo = new MethodInfo(classInfo, name, desc);
- classInfo.getMethods().add(methodInfo);
- return new InfoBuildingVisitor(methodInfo);
- }
-
- public AnnotationVisitor visitParameterAnnotation(int param, String desc, boolean visible) {
- MethodInfo methodInfo = ((MethodInfo) info);
- List<AnnotationInfo> annotationInfos = methodInfo.getParameterAnnotations(param);
- AnnotationInfo annotationInfo = new AnnotationInfo(desc);
- annotationInfos.add(annotationInfo);
- return new InfoBuildingVisitor(annotationInfo);
- }
- }
-
- public static class GenericAwareInfoBuildingVisitor implements SignatureVisitor {
-
- public enum TYPE {
- CLASS
- }
-
- public enum STATE {
- BEGIN, END, SUPERCLASS, INTERFACE, FORMAL_TYPE_PARAM
- }
-
- private Info info;
- private TYPE type;
- private STATE state;
-
- private static boolean debug = false;
-
- public GenericAwareInfoBuildingVisitor() {
- }
-
- public GenericAwareInfoBuildingVisitor(TYPE type, Info info) {
- this.type = type;
- this.info = info;
- this.state = STATE.BEGIN;
- }
-
- public void visitFormalTypeParameter(String s) {
- if (debug) System.out.println(" s=" + s);
- switch (state) {
- case BEGIN:
- ((ClassInfo) info).name += "<" + s;
- }
- state = STATE.FORMAL_TYPE_PARAM;
- }
-
- public SignatureVisitor visitClassBound() {
- if (debug) System.out.println(" visitClassBound()");
- return this;
- }
-
- public SignatureVisitor visitInterfaceBound() {
- if (debug) System.out.println(" visitInterfaceBound()");
- return this;
- }
-
- public SignatureVisitor visitSuperclass() {
- if (debug) System.out.println(" visitSuperclass()");
- state = STATE.SUPERCLASS;
- return this;
- }
-
- public SignatureVisitor visitInterface() {
- if (debug) System.out.println(" visitInterface()");
- ((ClassInfo) info).getInterfaces().add("");
- state = STATE.INTERFACE;
- return this;
- }
-
- public SignatureVisitor visitParameterType() {
- if (debug) System.out.println(" visitParameterType()");
- return this;
- }
-
- public SignatureVisitor visitReturnType() {
- if (debug) System.out.println(" visitReturnType()");
- return this;
- }
-
- public SignatureVisitor visitExceptionType() {
- if (debug) System.out.println(" visitExceptionType()");
- return this;
- }
-
- public void visitBaseType(char c) {
- if (debug) System.out.println(" visitBaseType(" + c + ")");
- }
-
- public void visitTypeVariable(String s) {
- if (debug) System.out.println(" visitTypeVariable(" + s + ")");
- }
-
- public SignatureVisitor visitArrayType() {
- if (debug) System.out.println(" visitArrayType()");
- return this;
- }
-
- public void visitClassType(String s) {
- if (debug) System.out.println(" visitClassType(" + s + ")");
- switch (state) {
- case INTERFACE:
- List<String> interfces = ((ClassInfo) info).getInterfaces();
- int idx = interfces.size() - 1;
- String interfce = interfces.get(idx);
- if (interfce.length() == 0) {
- interfce = javaName(s);
- } else {
- interfce += javaName(s);
- }
- interfces.set(idx, interfce);
- break;
- case SUPERCLASS:
- if (!s.equals("java/lang/Object")) {
- ((ClassInfo) info).superType = javaName(s);
- }
- }
- }
-
- public void visitInnerClassType(String s) {
- if (debug) System.out.println(" visitInnerClassType(" + s + ")");
- }
-
- public void visitTypeArgument() {
- if (debug) System.out.println(" visitTypeArgument()");
- switch (state) {
- case INTERFACE:
- List<String> interfces = ((ClassInfo) info).getInterfaces();
- int idx = interfces.size() - 1;
- String interfce = interfces.get(idx);
- interfce += "<";
- interfces.set(idx, interfce);
- }
- }
-
- public SignatureVisitor visitTypeArgument(char c) {
- if (debug) System.out.println(" visitTypeArgument(" + c + ")");
- switch (state) {
- case INTERFACE:
- List<String> interfces = ((ClassInfo) info).getInterfaces();
- int idx = interfces.size() - 1;
- String interfce = interfces.get(idx);
- interfce += "<";
- interfces.set(idx, interfce);
- }
- return this;
- }
-
- public void visitEnd() {
- if (debug) System.out.println(" visitEnd()");
- switch (state) {
- case INTERFACE:
- List<String> interfces = ((ClassInfo) info).getInterfaces();
- int idx = interfces.size() - 1;
- String interfce = interfces.get(idx);
- interfce += ">";
- interfces.set(idx, interfce);
- break;
- case FORMAL_TYPE_PARAM:
- String name = ((ClassInfo) info).name;
- if (name.contains("<")) {
- ((ClassInfo) info).name += ">";
- }
- }
- state = STATE.END;
- }
-
- private String javaName(String name) {
- return (name == null)? null:name.replace('/', '.');
- }
-
- }
}