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 rm...@apache.org on 2015/03/17 12:23:04 UTC

svn commit: r1667269 - in /geronimo/xbean/trunk/xbean-finder/src: main/java/org/apache/xbean/finder/AnnotationFinder.java test/java/org/apache/xbean/finder/ClassFinderDepthTest.java

Author: rmannibucau
Date: Tue Mar 17 11:23:04 2015
New Revision: 1667269

URL: http://svn.apache.org/r1667269
Log:
XBEAN-280 parent classes can't be loaded through linkParent in some cases

Modified:
    geronimo/xbean/trunk/xbean-finder/src/main/java/org/apache/xbean/finder/AnnotationFinder.java
    geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/ClassFinderDepthTest.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=1667269&r1=1667268&r2=1667269&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 Tue Mar 17 11:23:04 2015
@@ -68,6 +68,13 @@ import java.util.Set;
 public class AnnotationFinder implements IAnnotationFinder {
     private static final int ASM_FLAGS = ClassReader.SKIP_CODE + ClassReader.SKIP_DEBUG + ClassReader.SKIP_FRAMES;
 
+    // this flag is just a backdoor to allow workaround in case we impact an application, if we aresafe for 2-3 versions
+    // let remove it
+    //
+    // main issue which can happen is a parent class we dont want to scan appears,
+    // xbean.finder.prevent-lazy-linking= true will prevent it, see readClassDef(Class)
+    private static final boolean ALLOW_LAZY_LINKING = !Boolean.getBoolean("xbean.finder.prevent-lazy-linking");
+
     private final Set<Class<? extends Annotation>> metaroots = new HashSet<Class<? extends Annotation>>();
 
     protected final Map<String, List<Info>> annotated = newAnnotatedMap();
@@ -77,6 +84,7 @@ public class AnnotationFinder implements
     private final List<String> classesNotLoaded = new LinkedList<String>();
     private final Archive archive;
     private final boolean checkRuntimeAnnotation;
+    private volatile boolean linking;
 
     private AnnotationFinder(AnnotationFinder parent, Iterable<String> classNames) {
         this.archive = new SubArchive(classNames);
@@ -245,6 +253,7 @@ public class AnnotationFinder implements
     }
 
     public AnnotationFinder enableFindSubclasses() {
+        linking = ALLOW_LAZY_LINKING;
         for (ClassInfo classInfo : classInfos.values().toArray(new ClassInfo[classInfos.size()])) {
 
             linkParent(classInfo);
@@ -356,15 +365,27 @@ public class AnnotationFinder implements
             parentInfo = classInfos.get(classInfo.superType);
 
             if (parentInfo == null) {
-
-                if (classInfo.clazz != null) {
-                    readClassDef(((Class<?>) classInfo.clazz).getSuperclass());
-                } else {
-                    readClassDef(classInfo.superType);
-                }
+                // best scanning we can do, try it first
+                readClassDef(classInfo.superType);
 
                 parentInfo = classInfos.get(classInfo.superType);
 
+                if (parentInfo == null) {
+                    // parentInfo == null means readClassDef fails so clean up error and retry
+                    classesNotLoaded.remove(classInfo.superType);
+
+                    try {
+                        if (classInfo.get() != null) { // call get() to ensure clazz got a change to be loaded
+                            readClassDef(((Class<?>) classInfo.clazz).getSuperclass());
+                            parentInfo = classInfos.get(classInfo.superType);
+                        }
+                    } catch (final ClassNotFoundException e) {
+                        // no-op
+                    } catch (final Throwable e) {
+                        // no-op
+                    }
+                }
+
                 if (parentInfo == null) return;
 
                 linkParent(parentInfo);
@@ -1170,6 +1191,9 @@ public class AnnotationFinder implements
         infos.add(classInfo);
         for (Method method : clazz.getDeclaredMethods()) {
             MethodInfo methodInfo = new MethodInfo(classInfo, method);
+            if (linking) {
+                classInfo.methods.add(methodInfo);
+            }
             infos.add(methodInfo);
             for (Annotation[] annotations : method.getParameterAnnotations()) {
                 for (int i = 0; i < annotations.length; i++) {
@@ -1180,6 +1204,9 @@ public class AnnotationFinder implements
 
         for (Constructor<?> constructor : clazz.getConstructors()) {
             MethodInfo methodInfo = new MethodInfo(classInfo, constructor);
+            if (linking) {
+                classInfo.methods.add(methodInfo);
+            }
             infos.add(methodInfo);
             for (Annotation[] annotations : constructor.getParameterAnnotations()) {
                 for (int i = 0; i < annotations.length; i++) {
@@ -1189,7 +1216,11 @@ public class AnnotationFinder implements
         }
 
         for (Field field : clazz.getDeclaredFields()) {
-            infos.add(new FieldInfo(classInfo, field));
+            final FieldInfo fieldInfo = new FieldInfo(classInfo, field);
+            if (linking) {
+                classInfo.fields.add(fieldInfo);
+            }
+            infos.add(fieldInfo);
         }
 
         for (Info info : infos) {
@@ -1198,6 +1229,10 @@ public class AnnotationFinder implements
                 annotationInfos.add(info);
             }
         }
+
+        if (linking) {
+            classInfos.put(classInfo.name, classInfo);
+        }
     }
 
     public AnnotationFinder select(Class<?>... clazz) {

Modified: geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/ClassFinderDepthTest.java
URL: http://svn.apache.org/viewvc/geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/ClassFinderDepthTest.java?rev=1667269&r1=1667268&r2=1667269&view=diff
==============================================================================
--- geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/ClassFinderDepthTest.java (original)
+++ geronimo/xbean/trunk/xbean-finder/src/test/java/org/apache/xbean/finder/ClassFinderDepthTest.java Tue Mar 17 11:23:04 2015
@@ -90,20 +90,18 @@ public class ClassFinderDepthTest extend
     }
 
     public void testFindImplementations() throws Exception {
-        for (int i = 0; i < 10; i++) { 
-            for (final AnnotationFinder finder : new AnnotationFinder[] {
-                new AnnotationFinder(new ClassesArchive(Crimson.class, Square.class)).link()
-            }) {
+        for (int i = 0; i < 10; i++) {
+            final AnnotationFinder finder =
+                    new AnnotationFinder(new ClassesArchive(Crimson.class, Square.class)).link();
 
-                assertImplementations(finder, HSB.class, Color.class, Red.class, Crimson.class);
-                assertImplementations(finder, Hue.class, HSB.class, Color.class, Red.class, Crimson.class);
-                assertImplementations(finder, Saturation.class, HSB.class, Color.class, Red.class, Crimson.class);
-            }
+            assertImplementations(finder, HSB.class, Color.class, Red.class, Crimson.class);
+            assertImplementations(finder, Hue.class, HSB.class, Color.class, Red.class, Crimson.class);
+            assertImplementations(finder, Saturation.class, HSB.class, Color.class, Red.class, Crimson.class);
         }
     }
 
     private void assertSubclasses(AnnotationFinder finder, Class<?> clazz, Class... subclasses) {
-        final List<Class<?>> classes = new ArrayList(finder.findSubclasses(clazz));
+        final List<Class<?>> classes = new ArrayList<Class<?>>(finder.findSubclasses(clazz));
 
         for (Class subclass : subclasses) {
             assertContains(classes, subclass);