SLING-6764 - Guard against reflection failures when registering Sling Model classes
authorJustin Edelson <justin@apache.org>
Fri, 31 Mar 2017 19:14:48 +0000 (19:14 +0000)
committerJustin Edelson <justin@apache.org>
Fri, 31 Mar 2017 19:14:48 +0000 (19:14 +0000)
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1789734 13f79535-47bb-0310-9956-ffa450edef68

src/main/java/org/apache/sling/models/impl/AdapterImplementations.java
src/main/java/org/apache/sling/models/impl/ModelPackageBundleListener.java
src/test/java/org/apache/sling/models/impl/AdapterImplementationsTest.java

index 6a13f35..65d9210 100644 (file)
@@ -102,38 +102,52 @@ final class AdapterImplementations {
     }
     
     /** Add implementation mapping for the given model class (implementation is the model class itself).
-     * Only used for testing purposes. Use {@link #add(Class, Class)} in case you want to register a different implementation.
+     * Only used for testing purposes. Use {@link #addAll(Class, Class...)} in case you want to register a different implementation.
      * @param modelClasses the model classes to register
      */
     protected void addClassesAsAdapterAndImplementation(Class<?>... modelClasses) {
         for (Class<?> modelClass : modelClasses) {
-            add(modelClass, modelClass);
+            addAll(modelClass, modelClass);
         }
     }
     
     /**
-     * Add implementation mapping for the given adapter type.
-     * @param adapterType Adapter type
+     * Add implementation mapping for the given adapter types.
      * @param implType Implementation type
+     * @param adapterTypes Adapter types
+     * @result true if adapters were successfully added
      */
     @SuppressWarnings("unchecked")
-    public void add(Class<?> adapterType, Class<?> implType) {
-        String key = adapterType.getName();
-        if (adapterType == implType) {
-            modelClasses.put(key, new ModelClass(implType, sortedStaticInjectAnnotationProcessorFactories));
+    boolean addAll(Class<?> implType, Class<?>... adapterTypes) {
+        ModelClass<?> modelClass = null;
+        try {
+            modelClass = new ModelClass(implType, sortedStaticInjectAnnotationProcessorFactories);
+        } catch (Exception e) {
+            log.warn("Unable to reflect on " + implType.getName(), e);
+            return false;
+        } catch (NoClassDefFoundError e) {
+            log.warn("Unable to reflect on " + implType.getName(), e);
+            return false;
         }
-        else {
-            // although we already use a ConcurrentMap synchronize explicitly because we apply non-atomic operations on it
-            synchronized (adapterImplementations) {
-                ConcurrentNavigableMap<String,ModelClass<?>> implementations = adapterImplementations.get(key);
-                if (implementations == null) {
-                    // to have a consistent ordering independent of bundle loading use a ConcurrentSkipListMap that sorts by class name
-                    implementations = new ConcurrentSkipListMap<String,ModelClass<?>>();
-                    adapterImplementations.put(key, implementations);
+
+        for (Class<?> adapterType : adapterTypes) {
+            String key = adapterType.getName();
+            if (adapterType == implType) {
+                modelClasses.put(key, modelClass);
+            } else {
+                // although we already use a ConcurrentMap synchronize explicitly because we apply non-atomic operations on it
+                synchronized (adapterImplementations) {
+                    ConcurrentNavigableMap<String, ModelClass<?>> implementations = adapterImplementations.get(key);
+                    if (implementations == null) {
+                        // to have a consistent ordering independent of bundle loading use a ConcurrentSkipListMap that sorts by class name
+                        implementations = new ConcurrentSkipListMap<String, ModelClass<?>>();
+                        adapterImplementations.put(key, implementations);
+                    }
+                    implementations.put(implType.getName(), modelClass);
                 }
-                implementations.put(implType.getName(), new ModelClass(implType, sortedStaticInjectAnnotationProcessorFactories));
             }
         }
+        return true;
     }
     
     /**
index ac6ef47..1401d6b 100644 (file)
@@ -149,34 +149,33 @@ public class ModelPackageBundleListener implements BundleTrackerCustomizer {
                 }
                 // register adapter only if given adapters are valid
                 if (validateAdapterClasses(implType, adapterTypes)) {
-                    for (Class<?> adapterType : adapterTypes) {
-                        adapterImplementations.add(adapterType, implType);
-                    }
-                    ServiceRegistration reg = registerAdapterFactory(adapterTypes, annotation.adaptables(), implType, annotation.condition());
-                    regs.add(reg);
-
-                    String[] resourceTypes = annotation.resourceType();
-                    for (String resourceType : resourceTypes) {
-                        if (StringUtils.isNotEmpty(resourceType)) {
-                            for (Class<?> adaptable : annotation.adaptables()) {
-                                adapterImplementations.registerModelToResourceType(bundle, resourceType, adaptable, implType);
-                                ExportServlet.ExportedObjectAccessor accessor = null;
-                                if (adaptable == Resource.class) {
-                                    accessor = new ExportServlet.ResourceAccessor(implType);
-                                } else if (adaptable == SlingHttpServletRequest.class) {
-                                    accessor = new ExportServlet.RequestAccessor(implType);
-                                }
-                                Exporter exporterAnnotation = implType.getAnnotation(Exporter.class);
-                                if (exporterAnnotation != null) {
-                                    registerExporter(bundle, implType, resourceType, exporterAnnotation, regs, accessor);
-                                }
-                                Exporters exportersAnnotation = implType.getAnnotation(Exporters.class);
-                                if (exportersAnnotation != null) {
-                                    for (Exporter ann : exportersAnnotation.value()) {
-                                        registerExporter(bundle, implType, resourceType, ann, regs, accessor);
+                    if (adapterImplementations.addAll(implType, adapterTypes)) {
+                        ServiceRegistration reg = registerAdapterFactory(adapterTypes, annotation.adaptables(), implType, annotation.condition());
+                        regs.add(reg);
+
+                        String[] resourceTypes = annotation.resourceType();
+                        for (String resourceType : resourceTypes) {
+                            if (StringUtils.isNotEmpty(resourceType)) {
+                                for (Class<?> adaptable : annotation.adaptables()) {
+                                    adapterImplementations.registerModelToResourceType(bundle, resourceType, adaptable, implType);
+                                    ExportServlet.ExportedObjectAccessor accessor = null;
+                                    if (adaptable == Resource.class) {
+                                        accessor = new ExportServlet.ResourceAccessor(implType);
+                                    } else if (adaptable == SlingHttpServletRequest.class) {
+                                        accessor = new ExportServlet.RequestAccessor(implType);
+                                    }
+                                    Exporter exporterAnnotation = implType.getAnnotation(Exporter.class);
+                                    if (exporterAnnotation != null) {
+                                        registerExporter(bundle, implType, resourceType, exporterAnnotation, regs, accessor);
+                                    }
+                                    Exporters exportersAnnotation = implType.getAnnotation(Exporters.class);
+                                    if (exportersAnnotation != null) {
+                                        for (Exporter ann : exportersAnnotation.value()) {
+                                            registerExporter(bundle, implType, resourceType, ann, regs, accessor);
+                                        }
                                     }
-                                }
 
+                                }
                             }
                         }
                     }
index 0dc9702..434316f 100644 (file)
@@ -74,7 +74,7 @@ public class AdapterImplementationsTest {
     
     @Test
     public void testSingleMapping() {
-        underTest.add(SAMPLE_ADAPTER, String.class);
+        underTest.addAll(String.class, SAMPLE_ADAPTER);
         
         assertEquals(String.class, underTest.lookup(SAMPLE_ADAPTER, SAMPLE_ADAPTABLE).getType());
         
@@ -85,9 +85,9 @@ public class AdapterImplementationsTest {
 
     @Test
     public void testMultipleMappings() {
-        underTest.add(SAMPLE_ADAPTER, String.class);
-        underTest.add(SAMPLE_ADAPTER, Integer.class);
-        underTest.add(SAMPLE_ADAPTER, Long.class);
+        underTest.addAll(String.class, SAMPLE_ADAPTER);
+        underTest.addAll(Integer.class, SAMPLE_ADAPTER);
+        underTest.addAll(Long.class, SAMPLE_ADAPTER);
         
         assertEquals(Integer.class, underTest.lookup(SAMPLE_ADAPTER, SAMPLE_ADAPTABLE).getType());
         
@@ -103,9 +103,9 @@ public class AdapterImplementationsTest {
     
     @Test
     public void testRemoveAll() {
-        underTest.add(SAMPLE_ADAPTER, String.class);
-        underTest.add(SAMPLE_ADAPTER, Integer.class);
-        underTest.add(SAMPLE_ADAPTER, Long.class);
+        underTest.addAll(String.class, SAMPLE_ADAPTER);
+        underTest.addAll(Integer.class, SAMPLE_ADAPTER);
+        underTest.addAll(Long.class, SAMPLE_ADAPTER);
         
         underTest.removeAll();
         
@@ -120,16 +120,16 @@ public class AdapterImplementationsTest {
             new FirstImplementationPicker()
         ));
 
-        underTest.add(SAMPLE_ADAPTER, String.class);
-        underTest.add(SAMPLE_ADAPTER, Integer.class);
-        underTest.add(SAMPLE_ADAPTER, Long.class);
+        underTest.addAll(String.class, SAMPLE_ADAPTER);
+        underTest.addAll(Integer.class, SAMPLE_ADAPTER);
+        underTest.addAll(Long.class, SAMPLE_ADAPTER);
         
         assertEquals(String.class, underTest.lookup(SAMPLE_ADAPTER, SAMPLE_ADAPTABLE).getType());
     }
     
     @Test
     public void testSimpleModel() {
-        underTest.add(SAMPLE_ADAPTER, SAMPLE_ADAPTER);
+        underTest.addAll(SAMPLE_ADAPTER, SAMPLE_ADAPTER);
         
         assertEquals(SAMPLE_ADAPTER, underTest.lookup(SAMPLE_ADAPTER, SAMPLE_ADAPTABLE).getType());
     }