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 db...@apache.org on 2012/02/26 21:20:10 UTC
svn commit: r1293927 - in /geronimo/xbean/trunk/xbean-finder/src:
main/java/org/apache/xbean/finder/ main/java/org/apache/xbean/finder/archive/
test/java/org/apache/xbean/finder/
Author: dblevins
Date: Sun Feb 26 20:20:10 2012
New Revision: 1293927
URL: http://svn.apache.org/viewvc?rev=1293927&view=rev
Log:
XBEAN-202: AnnotationFinder.select(String... classnames) allows narrowing of finder scope
XBEAN-201: JarArchive and FileArchive cache results so re-iterating is cheap
Added:
geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/FinderSelectTest.java
geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/SelectMetaAnnotatedClassTest.java
- copied, changed from r1291554, geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/MetaAnnotatedClassTest.java
Modified:
geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/AnnotationFinder.java
geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/archive/FileArchive.java
geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/archive/JarArchive.java
Modified: geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/AnnotationFinder.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/AnnotationFinder.java?rev=1293927&r1=1293926&r2=1293927&view=diff
==============================================================================
--- geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/AnnotationFinder.java (original)
+++ geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/AnnotationFinder.java Sun Feb 26 20:20:10 2012
@@ -43,9 +43,11 @@ import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -72,6 +74,80 @@ public class AnnotationFinder implements
private final int ASM_FLAGS = ClassReader.SKIP_CODE + ClassReader.SKIP_DEBUG + ClassReader.SKIP_FRAMES;
private final Archive archive;
+ private AnnotationFinder(AnnotationFinder parent, Iterable<String> classNames) {
+ this.archive = new SubArchive(classNames);
+ this.metaroots.addAll(parent.metaroots);
+ for (Class<? extends Annotation> metaroot : metaroots) {
+ final ClassInfo info = parent.classInfos.get(metaroot.getName());
+ if (info == null) continue;
+ readClassDef(info);
+ }
+ for (String name : classNames) {
+ final ClassInfo info = parent.classInfos.get(name);
+ if (info == null) continue;
+ readClassDef(info);
+ }
+
+ resolveAnnotations(parent, new ArrayList<String>());
+ for (ClassInfo classInfo : classInfos.values()) {
+ if (isMetaRoot(classInfo)) {
+ try {
+ metaroots.add((Class<? extends Annotation>) classInfo.get());
+ } catch (ClassNotFoundException e) {
+ classesNotLoaded.add(classInfo.getName());
+ }
+ }
+ }
+
+ for (Class<? extends Annotation> metaroot : metaroots) {
+ List<Info> infoList = annotated.get(metaroot.getName());
+ for (Info info : infoList) {
+ final String className = info.getName() + "$$";
+ final ClassInfo i = parent.classInfos.get(className);
+ if (i == null) continue;
+ readClassDef(i);
+ }
+ }
+ }
+
+ private void readClassDef(ClassInfo info) {
+ classInfos.put(info.name, info);
+ index(info);
+ index(info.constructors);
+ index(info.methods);
+ index(info.fields);
+ }
+
+ private void resolveAnnotations(AnnotationFinder parent, List<String> scanned) {
+ // Get a list of the annotations that exist before we start
+ final List<String> annotations = new ArrayList<String>(annotated.keySet());
+
+ for (String annotation : annotations) {
+ if (scanned.contains(annotation)) continue;
+ final ClassInfo info = parent.classInfos.get(annotation);
+ if (info == null) continue;
+ readClassDef(info);
+ }
+
+ // If the "annotated" list has grown, then we must scan those
+ if (annotated.keySet().size() != annotations.size()) {
+ resolveAnnotations(parent, annotations);
+ }
+ }
+
+
+ private void index(List<? extends Info> infos) {
+ for (Info i : infos) {
+ index(i);
+ }
+ }
+
+ private void index(Info i) {
+ for (AnnotationInfo annotationInfo : i.getAnnotations()) {
+ index(annotationInfo, i);
+ }
+ }
+
public AnnotationFinder(Archive archive) {
this.archive = archive;
@@ -832,6 +908,12 @@ public class AnnotationFinder implements
}
protected List<Info> getAnnotationInfos(String name) {
+ final List<Info> infos = annotated.get(name);
+ if (infos != null) return infos;
+ return Collections.EMPTY_LIST;
+ }
+
+ protected List<Info> initAnnotationInfos(String name) {
List<Info> infos = annotated.get(name);
if (infos == null) {
infos = new SingleLinkedList<Info>();
@@ -862,7 +944,7 @@ public class AnnotationFinder implements
if (aPackage != null) {
final PackageInfo info = new PackageInfo(aPackage);
for (AnnotationInfo annotation : info.getAnnotations()) {
- List<Info> annotationInfos = getAnnotationInfos(annotation.getName());
+ List<Info> annotationInfos = initAnnotationInfos(annotation.getName());
if (!annotationInfos.contains(info)) {
annotationInfos.add(info);
}
@@ -886,12 +968,56 @@ public class AnnotationFinder implements
for (Info info : infos) {
for (AnnotationInfo annotation : info.getAnnotations()) {
- List<Info> annotationInfos = getAnnotationInfos(annotation.getName());
+ List<Info> annotationInfos = initAnnotationInfos(annotation.getName());
annotationInfos.add(info);
}
}
}
+ public AnnotationFinder select(Class<?>... clazz) {
+ String[] names = new String[clazz.length];
+ int i = 0;
+ for (Class<?> name : clazz) {
+ names[i++] = name.getName();
+ }
+
+ return new AnnotationFinder(this, Arrays.asList(names));
+ }
+
+ public AnnotationFinder select(String... clazz) {
+ return new AnnotationFinder(this, Arrays.asList(clazz));
+ }
+
+ public AnnotationFinder select(Iterable<String> clazz) {
+ return new AnnotationFinder(this, clazz);
+ }
+
+ public class SubArchive implements Archive {
+ private List<String> classes = new ArrayList<String>();
+
+ public SubArchive(String... classes) {
+ Collections.addAll(this.classes, classes);
+ }
+
+ public SubArchive(Iterable<String> classes) {
+ for (String name : classes) {
+ this.classes.add(name);
+ }
+ }
+
+ public InputStream getBytecode(String className) throws IOException, ClassNotFoundException {
+ return archive.getBytecode(className);
+ }
+
+ public Class<?> loadClass(String className) throws ClassNotFoundException {
+ return archive.loadClass(className);
+ }
+
+ public Iterator<String> iterator() {
+ return classes.iterator();
+ }
+ }
+
public class Annotatable {
private final List<AnnotationInfo> annotations = new ArrayList<AnnotationInfo>();
@@ -1305,6 +1431,10 @@ public class AnnotationFinder implements
}
}
+ private void index(AnnotationInfo annotationInfo, Info info) {
+ initAnnotationInfos(annotationInfo.getName()).add(info);
+ }
+
public class InfoBuildingVisitor extends EmptyVisitor {
private Info info;
@@ -1355,7 +1485,7 @@ public class AnnotationFinder implements
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
AnnotationInfo annotationInfo = new AnnotationInfo(desc);
info.getAnnotations().add(annotationInfo);
- getAnnotationInfos(annotationInfo.getName()).add(info);
+ index(annotationInfo, info);
return new InfoBuildingVisitor(annotationInfo);
}
Modified: geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/archive/FileArchive.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/archive/FileArchive.java?rev=1293927&r1=1293926&r2=1293927&view=diff
==============================================================================
--- geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/archive/FileArchive.java (original)
+++ geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/archive/FileArchive.java Sun Feb 26 20:20:10 2012
@@ -33,6 +33,7 @@ public class FileArchive implements Arch
private final ClassLoader loader;
private final File dir;
+ private List<String> list;
public FileArchive(ClassLoader loader, URL url) {
this.loader = loader;
@@ -44,6 +45,10 @@ public class FileArchive implements Arch
this.dir = dir;
}
+ public File getDir() {
+ return dir;
+ }
+
public InputStream getBytecode(String className) throws IOException, ClassNotFoundException {
int pos = className.indexOf("<");
if (pos > -1) {
@@ -69,7 +74,10 @@ public class FileArchive implements Arch
}
public Iterator<String> iterator() {
- return file(dir).iterator();
+ if (list != null) return list.iterator();
+
+ list = file(dir);
+ return list.iterator();
}
private List<String> file(File dir) {
Modified: geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/archive/JarArchive.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/archive/JarArchive.java?rev=1293927&r1=1293926&r2=1293927&view=diff
==============================================================================
--- geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/archive/JarArchive.java (original)
+++ geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/archive/JarArchive.java Sun Feb 26 20:20:10 2012
@@ -35,13 +35,18 @@ public class JarArchive implements Archi
private final ClassLoader loader;
private final URL url;
+ private List<String> list;
public JarArchive(ClassLoader loader, URL url) {
- if (!"jar".equals(url.getProtocol())) throw new IllegalArgumentException("not a file url: " + url);
+ if (!"jar".equals(url.getProtocol())) throw new IllegalArgumentException("not a jar url: " + url);
this.loader = loader;
this.url = url;
}
+ public URL getUrl() {
+ return url;
+ }
+
public InputStream getBytecode(String className) throws IOException, ClassNotFoundException {
int pos = className.indexOf("<");
if (pos > -1) {
@@ -67,8 +72,11 @@ public class JarArchive implements Archi
}
public Iterator<String> iterator() {
+ if (list != null) return list.iterator();
+
try {
- return jar(url).iterator();
+ list = jar(url);
+ return list.iterator();
} catch (IOException e) {
throw new IllegalStateException(e);
}
Added: geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/FinderSelectTest.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/FinderSelectTest.java?rev=1293927&view=auto
==============================================================================
--- geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/FinderSelectTest.java (added)
+++ geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/FinderSelectTest.java Sun Feb 26 20:20:10 2012
@@ -0,0 +1,65 @@
+/*
+ * 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 org.apache.xbean.finder.archive.ClassesArchive;
+import org.junit.Test;
+
+import java.util.List;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class FinderSelectTest {
+
+ @Test
+ public void test() throws Exception {
+
+ final AnnotationFinder all = new AnnotationFinder(new ClassesArchive(Red.class, Green.class, Blue.class));
+
+ final AnnotationFinder finder = all.select(Red.class.getName());
+ final List<Class<?>> classes = finder.findAnnotatedClasses(Color.class);
+
+ for (Class<?> aClass : classes) {
+ System.out.println(aClass);
+ }
+
+ }
+
+
+
+ @java.lang.annotation.Target(value = {java.lang.annotation.ElementType.TYPE})
+ @java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
+ public @interface Color {
+ }
+
+
+ @Color
+ public static class Red {
+
+ }
+
+ @Color
+ public static class Green {
+
+ }
+
+ @Color
+ public static class Blue {
+
+ }
+}
Copied: geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/SelectMetaAnnotatedClassTest.java (from r1291554, geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/MetaAnnotatedClassTest.java)
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/SelectMetaAnnotatedClassTest.java?p2=geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/SelectMetaAnnotatedClassTest.java&p1=geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/MetaAnnotatedClassTest.java&r1=1291554&r2=1293927&rev=1293927&view=diff
==============================================================================
--- geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/MetaAnnotatedClassTest.java (original)
+++ geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/SelectMetaAnnotatedClassTest.java Sun Feb 26 20:20:10 2012
@@ -16,6 +16,7 @@
*/
package org.apache.xbean.finder;
+import com.sun.xml.internal.txw2.IllegalSignatureException;
import junit.framework.TestCase;
import org.apache.xbean.finder.archive.ClassesArchive;
@@ -40,30 +41,23 @@ import static java.lang.annotation.Reten
*
* @version $Rev$ $Date$
*/
-public class MetaAnnotatedClassTest extends TestCase {
+public class SelectMetaAnnotatedClassTest extends TestCase {
- public void test() throws Exception {
- AnnotationFinder finder = new AnnotationFinder(new ClassesArchive(Square.class, Circle.class, Triangle.class, Fake.class, Store.class, Farm.class, None.class)).link();
-
- Map<Class<?>, Annotated<Class<?>>> map = new HashMap<Class<?>, Annotated<Class<?>>>();
+ private AnnotationFinder finder;
+ private Map<Class<?>, Annotated<Class<?>>> map;
- List<Annotated<Class<?>>> metas = finder.findMetaAnnotatedClasses(Color.class);
- for (Annotated<Class<?>> meta : metas) {
- Annotated<Class<?>> oldValue = map.put(meta.get(), meta);
- assertNull("no duplicates allowed", oldValue);
- }
+ public void test() throws Exception {
+ finder = new AnnotationFinder(new ClassesArchive(Square.class, Circle.class, Triangle.class, Fake.class, Store.class, Farm.class, None.class)).link();
// MetaAnnotation classes themselves are not included
- assertNull(map.get(Red.class));
- assertNull(map.get(Crimson.class));
-
- // Check the negative scenario
- assertFalse(map.containsKey(None.class));
+ assertNull(get(Red.class));
+ assertNull(get(Crimson.class));
+ assertNull(get(None.class));
// Check the positive scenarios
{ // Circle
- Annotated<Class<?>> target = map.get(Circle.class);
+ Annotated<Class<?>> target = get(Circle.class);
assertNotNull(target);
assertTrue(target.isAnnotationPresent(Color.class));
@@ -74,7 +68,7 @@ public class MetaAnnotatedClassTest exte
}
{ // Square
- Annotated<Class<?>> target = map.get(Square.class);
+ Annotated<Class<?>> target = get(Square.class);
assertNotNull(target);
assertTrue(target.isAnnotationPresent(Color.class));
@@ -90,7 +84,7 @@ public class MetaAnnotatedClassTest exte
}
{ // Triangle
- Annotated<Class<?>> target = map.get(Triangle.class);
+ Annotated<Class<?>> target = get(Triangle.class);
assertNotNull(target);
assertTrue(target.isAnnotationPresent(Color.class));
@@ -111,7 +105,7 @@ public class MetaAnnotatedClassTest exte
}
{ // Fake -- should not get more than we asked for
- Annotated<Class<?>> target = map.get(Fake.class);
+ Annotated<Class<?>> target = get(Fake.class);
assertNull(target);
List<Annotated<Class<?>>> list = finder.findMetaAnnotatedClasses(NotMeta.class);
@@ -128,7 +122,7 @@ public class MetaAnnotatedClassTest exte
{ // Circular - Egg wins
- Annotated<Class<?>> target = map.get(Store.class);
+ Annotated<Class<?>> target = get(Store.class);
assertNotNull(target);
assertTrue(target.isAnnotationPresent(Color.class));
@@ -149,7 +143,7 @@ public class MetaAnnotatedClassTest exte
}
{ // Circular - Chicken wins
- Annotated<Class<?>> target = map.get(Farm.class);
+ Annotated<Class<?>> target = get(Farm.class);
assertNotNull(target);
assertTrue(target.isAnnotationPresent(Color.class));
@@ -171,6 +165,23 @@ public class MetaAnnotatedClassTest exte
}
+// private Annotated<Class<?>> get(Class<?> key) {
+// return map.get(key);
+// }
+//
+ private Annotated<Class<?>> get(Class<?> key) {
+ final List<Annotated<Class<?>>> all = finder.findMetaAnnotatedClasses(Color.class);
+ final AnnotationFinder select = finder.select(key);
+ final List<Annotated<Class<?>>> metas = select.findMetaAnnotatedClasses(Color.class);
+
+ assertFalse(all.size() == metas.size());
+ for (Annotated<Class<?>> meta : metas) {
+ if (meta.get() == key) return meta;
+ }
+
+ return null;
+ }
+
private boolean contains(Class<? extends Annotation> type, Annotation[] annotations) {
for (Annotation annotation : annotations) {
if (type.isAssignableFrom(annotation.annotationType())) return true;