Author: dblevins Date: Wed Jun 6 03:52:11 2012 New Revision: 1346728 URL: http://svn.apache.org/viewvc?rev=1346728&view=rev Log: Abstracted ASM out of the AnnotationFinder behind a Parser interface that uses the InfoHandler "Listener" interface. Went for the SAX Handler lingo on the "listener" as it seemed more appropriate.
Added: commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/parse/ commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/parse/AsmParser.java commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/parse/Parser.java Modified: commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/AnnotationFinder.java commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/model/InfoHandler.java Modified: commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/AnnotationFinder.java URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/AnnotationFinder.java?rev=1346728&r1=1346727&r2=1346728&view=diff ============================================================================== --- commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/AnnotationFinder.java (original) +++ commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/AnnotationFinder.java Wed Jun 6 03:52:11 2012 @@ -32,14 +32,9 @@ import org.apache.commons.classscan.find import org.apache.commons.classscan.finder.model.InfoHandler; import org.apache.commons.classscan.finder.model.MethodInfo; import org.apache.commons.classscan.finder.model.PackageInfo; +import org.apache.commons.classscan.finder.parse.AsmParser; +import org.apache.commons.classscan.finder.parse.Parser; import org.apache.commons.classscan.finder.util.SingleLinkedList; -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.Attribute; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Type; -import org.objectweb.asm.commons.EmptyVisitor; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -80,9 +75,11 @@ public class AnnotationFinder implements protected final Map<String, ClassInfo> originalInfos = new HashMap<String, ClassInfo>(); private final List<String> classesNotLoaded = new ArrayList<String>(); private final Archive archive; + private Parser parser; private AnnotationFinder(AnnotationFinder parent, Iterable<String> classNames) { this.archive = new SubArchive(classNames); + this.parser = new AsmParser(this, archive); this.metaroots.addAll(parent.metaroots); for (Class<? extends Annotation> metaroot : metaroots) { final ClassInfo info = parent.classInfos.get(metaroot.getName()); @@ -120,16 +117,8 @@ public class AnnotationFinder implements public AnnotationFinder(Archive archive) { this.archive = archive; - for (Archive.Entry entry : archive) { - final String className = entry.getName(); - try { - readClassDef(entry.getBytecode()); - } catch (NoClassDefFoundError e) { - throw new NoClassDefFoundError("Could not fully load class: " + className + "\n due to:" + e.getMessage()); - } catch (IOException e) { - e.printStackTrace(); - } - } + parser = new AsmParser(this, archive); + parser.parse(); // keep track of what was originally from the archives originalInfos.putAll(classInfos); @@ -1059,6 +1048,11 @@ public class AnnotationFinder implements index(annotationInfo, info); } + @Override + public void error(String className, Throwable throwable) { + classesNotLoaded.add(className); + } + protected void readClassDef(String className) { if (classInfos.containsKey(className)) return; try { @@ -1106,128 +1100,7 @@ public class AnnotationFinder implements } } - //---------------------------------------------------------------------------- - // - // From here below are the ASM specific parts. - // - // With a cleaned up model, this could easily be abstracted - // - //---------------------------------------------------------------------------- - public static class AsmParser { - - private final InfoHandler handler; - - public AsmParser(InfoHandler handler) { - this.handler = handler; - } - - } - protected void readClassDef(InputStream in) throws IOException { - try { - final ClassReader classReader = new ClassReader(in); - final int flags = ClassReader.SKIP_CODE + ClassReader.SKIP_DEBUG + ClassReader.SKIP_FRAMES; - classReader.accept(new InfoBuildingVisitor(), flags); - } finally { - in.close(); - } - } - - private final InfoHandler handler = this; - - public class InfoBuildingVisitor extends EmptyVisitor { - - private Info info; - - public InfoBuildingVisitor() { - } - - public InfoBuildingVisitor(Info info) { - this.info = info; - } - - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - if (name.endsWith("package-info")) { - info = new PackageInfo(archive, javaName(name)); - handler.visit((PackageInfo) info); - } else { - - ClassInfo classInfo = new ClassInfo(archive, javaName(name), javaName(superName)); - - for (String interfce : interfaces) { - classInfo.getInterfaces().add(javaName(interfce)); - } - - info = classInfo; - - handler.visit((ClassInfo) info); - } - } - - private String javaName(String name) { - return (name == null) ? null : name.replace('/', '.'); - } - - @Override - public void visitInnerClass(String name, String outerName, String innerName, int access) { - super.visitInnerClass(name, outerName, innerName, access); - } - - @Override - public void visitAttribute(Attribute attribute) { - super.visitAttribute(attribute); - } - - @Override - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - final String name = Type.getType(desc).getClassName(); - AnnotationInfo annotationInfo = new AnnotationInfo(name); - info.getAnnotations().add(annotationInfo); - - handler.visit(annotationInfo, info); - - return new InfoBuildingVisitor(annotationInfo); - } - - @Override - 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); - - handler.visit(fieldInfo); - - return new InfoBuildingVisitor(fieldInfo); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - final ClassInfo classInfo = ((ClassInfo) info); - final List<String> params = new ArrayList<String>(); - org.objectweb.asm.commons.Method method = new org.objectweb.asm.commons.Method(name, desc); - for (Type type : method.getArgumentTypes()) { - params.add(type.getClassName()); - } - - MethodInfo methodInfo = new MethodInfo(classInfo, name, params); - classInfo.getMethods().add(methodInfo); - - handler.visit(methodInfo); - - return new InfoBuildingVisitor(methodInfo); - } - - - @Override - public AnnotationVisitor visitParameterAnnotation(int param, String desc, boolean visible) { - final MethodInfo methodInfo = ((MethodInfo) info); - final List<AnnotationInfo> annotationInfos = methodInfo.getParameterAnnotations(param); - final String name = Type.getType(desc).getClassName(); - final AnnotationInfo annotationInfo = new AnnotationInfo(name); - annotationInfos.add(annotationInfo); - return new InfoBuildingVisitor(annotationInfo); - } + parser.parse(in); } } \ No newline at end of file Modified: commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/model/InfoHandler.java URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/model/InfoHandler.java?rev=1346728&r1=1346727&r2=1346728&view=diff ============================================================================== --- commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/model/InfoHandler.java (original) +++ commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/model/InfoHandler.java Wed Jun 6 03:52:11 2012 @@ -16,6 +16,8 @@ */ package org.apache.commons.classscan.finder.model; +import java.io.IOException; + /** * @version $Rev$ $Date$ */ @@ -26,4 +28,6 @@ public interface InfoHandler { public void visit(FieldInfo info); public void visit(PackageInfo info); public void visit(AnnotationInfo annotationInfo, Info info); + + public void error(String className, Throwable throwable); } Added: commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/parse/AsmParser.java URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/parse/AsmParser.java?rev=1346728&view=auto ============================================================================== --- commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/parse/AsmParser.java (added) +++ commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/parse/AsmParser.java Wed Jun 6 03:52:11 2012 @@ -0,0 +1,173 @@ +/* + * 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.commons.classscan.finder.parse; + +import org.apache.commons.classscan.finder.archive.Archive; +import org.apache.commons.classscan.finder.model.AnnotationInfo; +import org.apache.commons.classscan.finder.model.ClassInfo; +import org.apache.commons.classscan.finder.model.FieldInfo; +import org.apache.commons.classscan.finder.model.Info; +import org.apache.commons.classscan.finder.model.InfoHandler; +import org.apache.commons.classscan.finder.model.MethodInfo; +import org.apache.commons.classscan.finder.model.PackageInfo; +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.Attribute; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Type; +import org.objectweb.asm.commons.EmptyVisitor; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +/** +* @version $Rev$ $Date$ +*/ +public class AsmParser implements Parser { + private final InfoHandler handler; + private final Archive archive; + + public AsmParser(InfoHandler handler, Archive archive) { + this.handler = handler; + this.archive = archive; + } + + @Override + public void parse() { + for (Archive.Entry entry : archive) { + final String className = entry.getName(); + try { + parse(entry.getBytecode()); + } catch (NoClassDefFoundError e) { + throw new NoClassDefFoundError("Could not fully load class: " + className + "\n due to:" + e.getMessage()); + } catch (IOException e) { + handler.error(entry.getName(), e); + } + } + } + + @Override + public void parse(InputStream in) throws IOException { + try { + final ClassReader classReader = new ClassReader(in); + final int flags = ClassReader.SKIP_CODE + ClassReader.SKIP_DEBUG + ClassReader.SKIP_FRAMES; + classReader.accept(new InfoBuildingVisitor(), flags); + } finally { + in.close(); + } + } + + public class InfoBuildingVisitor extends EmptyVisitor { + + private Info info; + + public InfoBuildingVisitor() { + } + + public InfoBuildingVisitor(Info info) { + this.info = info; + } + + + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + if (name.endsWith("package-info")) { + info = new PackageInfo(archive, javaName(name)); + handler.visit((PackageInfo) info); + } else { + + ClassInfo classInfo = new ClassInfo(archive, javaName(name), javaName(superName)); + + for (String interfce : interfaces) { + classInfo.getInterfaces().add(javaName(interfce)); + } + + info = classInfo; + + handler.visit((ClassInfo) info); + } + } + + private String javaName(String name) { + return (name == null) ? null : name.replace('/', '.'); + } + + @Override + public void visitInnerClass(String name, String outerName, String innerName, int access) { + super.visitInnerClass(name, outerName, innerName, access); + } + + @Override + public void visitAttribute(Attribute attribute) { + super.visitAttribute(attribute); + } + + @Override + public AnnotationVisitor visitAnnotation(String desc, boolean visible) { + final String name = Type.getType(desc).getClassName(); + AnnotationInfo annotationInfo = new AnnotationInfo(name); + info.getAnnotations().add(annotationInfo); + + handler.visit(annotationInfo, info); + + return new InfoBuildingVisitor(annotationInfo); + } + + @Override + 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); + + handler.visit(fieldInfo); + + return new InfoBuildingVisitor(fieldInfo); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + final ClassInfo classInfo = ((ClassInfo) info); + final List<String> params = new ArrayList<String>(); + org.objectweb.asm.commons.Method method = new org.objectweb.asm.commons.Method(name, desc); + for (Type type : method.getArgumentTypes()) { + params.add(type.getClassName()); + } + + MethodInfo methodInfo = new MethodInfo(classInfo, name, params); + classInfo.getMethods().add(methodInfo); + + handler.visit(methodInfo); + + return new InfoBuildingVisitor(methodInfo); + } + + + @Override + public AnnotationVisitor visitParameterAnnotation(int param, String desc, boolean visible) { + final MethodInfo methodInfo = ((MethodInfo) info); + final List<AnnotationInfo> annotationInfos = methodInfo.getParameterAnnotations(param); + final String name = Type.getType(desc).getClassName(); + final AnnotationInfo annotationInfo = new AnnotationInfo(name); + annotationInfos.add(annotationInfo); + return new InfoBuildingVisitor(annotationInfo); + } + } + +} Added: commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/parse/Parser.java URL: http://svn.apache.org/viewvc/commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/parse/Parser.java?rev=1346728&view=auto ============================================================================== --- commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/parse/Parser.java (added) +++ commons/sandbox/classscan/branches/commons-finder/src/main/java/org/apache/commons/classscan/finder/parse/Parser.java Wed Jun 6 03:52:11 2012 @@ -0,0 +1,29 @@ +/* + * 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.commons.classscan.finder.parse; + +import java.io.IOException; +import java.io.InputStream; + +/** + * @version $Rev$ $Date$ + */ +public interface Parser { + void parse(); + + void parse(InputStream in) throws IOException; +}