Author: sergeyb
Date: Wed May 23 14:54:39 2012
New Revision: 1341886

URL: http://svn.apache.org/viewvc?rev=1341886&view=rev
Log:
[ARIES-855] Initial support for loading nested classes

Added:
    
aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/BeanLoadingTest.java
   (with props)
    
aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/pojos/SimpleBean.java
   (with props)
    
aries/trunk/blueprint/blueprint-core/src/test/resources/test-bean-classes.xml   
(with props)
Modified:
    
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/di/AbstractRecipe.java

Modified: 
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/di/AbstractRecipe.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/di/AbstractRecipe.java?rev=1341886&r1=1341885&r2=1341886&view=diff
==============================================================================
--- 
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/di/AbstractRecipe.java
 (original)
+++ 
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/di/AbstractRecipe.java
 Wed May 23 14:54:39 2012
@@ -26,16 +26,21 @@ import java.util.concurrent.Future;
 import java.util.concurrent.FutureTask;
 
 import org.apache.aries.blueprint.container.GenericType;
-import org.osgi.service.blueprint.container.ReifiedType;
 import org.osgi.service.blueprint.container.ComponentDefinitionException;
+import org.osgi.service.blueprint.container.ReifiedType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public abstract class AbstractRecipe implements Recipe {
+    private static final Logger LOGGER = LoggerFactory
+            .getLogger(AbstractRecipe.class);
 
     protected final String name;
     protected boolean prototype = true;
 
     protected AbstractRecipe(String name) {
-        if (name == null) throw new NullPointerException("name is null");
+        if (name == null)
+            throw new NullPointerException("name is null");
         this.name = name;
     }
 
@@ -55,7 +60,8 @@ public abstract class AbstractRecipe imp
         // Ensure a container has been set
         ExecutionContext context = ExecutionContext.Holder.getContext();
 
-        // if this recipe has already been executed in this context, return 
the currently registered value
+        // if this recipe has already been executed in this context, return the
+        // currently registered value
         Object result = context.getPartialObject(name);
         if (result != null) {
             return result;
@@ -66,12 +72,15 @@ public abstract class AbstractRecipe imp
         boolean didCreate = false;
         try {
             if (!prototype) {
-                FutureTask<Object> objectCreation = new FutureTask<Object>(new 
Callable<Object>() {
-                    public Object call() throws ComponentDefinitionException {
-                        return internalCreate();
-                    }                
-                });
-                Future<Object> resultFuture = context.addFullObject(name, 
objectCreation);
+                FutureTask<Object> objectCreation = new FutureTask<Object>(
+                        new Callable<Object>() {
+                            public Object call()
+                                    throws ComponentDefinitionException {
+                                return internalCreate();
+                            }
+                        });
+                Future<Object> resultFuture = context.addFullObject(name,
+                        objectCreation);
 
                 // are we the first to try to create it
                 if (resultFuture == null) {
@@ -79,8 +88,7 @@ public abstract class AbstractRecipe imp
                     objectCreation.run();
                     resultFuture = objectCreation;
                 }
-                
-                
+
                 try {
                     result = resultFuture.get();
                 } catch (InterruptedException ie) {
@@ -90,45 +98,51 @@ public abstract class AbstractRecipe imp
                         throw (ComponentDefinitionException) ee.getCause();
                     else if (ee.getCause() instanceof RuntimeException)
                         throw (RuntimeException) ee.getCause();
-                    else 
+                    else
                         throw (Error) ee.getCause();
                 }
-                
+
             } else {
                 result = internalCreate();
             }
         } finally {
-            if (didCreate) context.removePartialObject(name);
-            
+            if (didCreate)
+                context.removePartialObject(name);
+
             Recipe popped = context.pop();
             if (popped != this) {
-                //noinspection ThrowFromFinallyBlock
-                throw new IllegalStateException("Internal Error: recipe stack 
is corrupt:" +
-                        " Expected " + this + " to be popped of the stack but 
was " + popped);
+                // noinspection ThrowFromFinallyBlock
+                throw new IllegalStateException(
+                        "Internal Error: recipe stack is corrupt:"
+                                + " Expected " + this
+                                + " to be popped of the stack but was "
+                                + popped);
             }
         }
-        
+
         return result;
     }
 
-    protected abstract Object internalCreate() throws 
ComponentDefinitionException;
-    
+    protected abstract Object internalCreate()
+            throws ComponentDefinitionException;
+
     protected void addPartialObject(Object obj) {
-        if (!prototype) {                 
+        if (!prototype) {
             ExecutionContext.Holder.getContext().addPartialObject(name, obj);
         }
     }
-    
+
     protected boolean canConvert(Object obj, ReifiedType type) {
-       return ExecutionContext.Holder.getContext().canConvert(obj, type);
+        return ExecutionContext.Holder.getContext().canConvert(obj, type);
     }
-    
+
     protected Object convert(Object obj, ReifiedType type) throws Exception {
         return ExecutionContext.Holder.getContext().convert(obj, type);
     }
 
     protected Object convert(Object obj, Type type) throws Exception {
-        return ExecutionContext.Holder.getContext().convert(obj, new 
GenericType(type));
+        return ExecutionContext.Holder.getContext().convert(obj,
+                new GenericType(type));
     }
 
     protected Class loadClass(String className) {
@@ -144,10 +158,41 @@ public abstract class AbstractRecipe imp
         if (typeName == null) {
             return null;
         }
+        return doLoadType(typeName, fromClassLoader, true, false);
+    }
+
+    private ReifiedType doLoadType(String typeName,
+            ClassLoader fromClassLoader, boolean checkNestedIfFailed,
+            boolean retry) {
         try {
-            return GenericType.parse(typeName, fromClassLoader != null ? 
fromClassLoader : ExecutionContext.Holder.getContext());
+            return GenericType.parse(typeName,
+                    fromClassLoader != null ? fromClassLoader
+                            : ExecutionContext.Holder.getContext());
         } catch (ClassNotFoundException e) {
-            throw new ComponentDefinitionException("Unable to load class " + 
typeName + " from recipe " + this, e);
+            String errorMessage = "Unable to load class " + typeName
+                    + " from recipe " + this;
+            if (checkNestedIfFailed) {
+                int lastDot = typeName.lastIndexOf('.');
+                if (lastDot > 0 && lastDot < typeName.length()) {
+                    String nestedTypeName = typeName.substring(0, lastDot)
+                            + "$" + typeName.substring(lastDot + 1);
+                    LOGGER.debug(errorMessage
+                            + ", trying to load a nested class "
+                            + nestedTypeName);
+                    try {
+                        return doLoadType(nestedTypeName, fromClassLoader,
+                                false, true);
+                    } catch (ComponentDefinitionException e2) {
+                        // ignore, the recursive call will throw this 
exception,
+                        // but ultimately the exception referencing the 
original
+                        // typeName has to be thrown
+                    }
+                }
+            }
+            if (!retry) {
+                LOGGER.error(errorMessage);
+            }
+            throw new ComponentDefinitionException(errorMessage, e);
         }
     }
 
@@ -157,11 +202,9 @@ public abstract class AbstractRecipe imp
     public List<Recipe> getConstructorDependencies() {
         return Collections.emptyList();
     }
-    
+
     public String toString() {
-        return getClass().getSimpleName() + "[" +
-                "name='" + name + '\'' +
-                ']';
+        return getClass().getSimpleName() + "[" + "name='" + name + '\'' + ']';
 
     }
 

Added: 
aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/BeanLoadingTest.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/BeanLoadingTest.java?rev=1341886&view=auto
==============================================================================
--- 
aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/BeanLoadingTest.java
 (added)
+++ 
aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/BeanLoadingTest.java
 Wed May 23 14:54:39 2012
@@ -0,0 +1,46 @@
+/*
+ * 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.aries.blueprint;
+
+import org.apache.aries.blueprint.di.Repository;
+import org.apache.aries.blueprint.parser.ComponentDefinitionRegistryImpl;
+import org.apache.aries.blueprint.pojos.SimpleBean;
+
+public class BeanLoadingTest extends AbstractBlueprintTest {
+
+    public void testLoadSimpleBean() throws Exception {
+        ComponentDefinitionRegistryImpl registry = 
parse("/test-bean-classes.xml");
+        Repository repository = new TestBlueprintContainer(registry)
+                .getRepository();
+
+        Object obj = repository.create("simpleBean");
+        assertNotNull(obj);
+        assertTrue(obj instanceof SimpleBean);
+    }
+
+    public void testLoadSimpleBeanNested() throws Exception {
+        ComponentDefinitionRegistryImpl registry = 
parse("/test-bean-classes.xml");
+        Repository repository = new TestBlueprintContainer(registry)
+                .getRepository();
+
+        Object obj = repository.create("simpleBeanNested");
+        assertNotNull(obj);
+        assertTrue(obj instanceof SimpleBean.Nested);
+    }
+}

Propchange: 
aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/BeanLoadingTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/BeanLoadingTest.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: 
aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/pojos/SimpleBean.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/pojos/SimpleBean.java?rev=1341886&view=auto
==============================================================================
--- 
aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/pojos/SimpleBean.java
 (added)
+++ 
aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/pojos/SimpleBean.java
 Wed May 23 14:54:39 2012
@@ -0,0 +1,25 @@
+/*
+ * 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.aries.blueprint.pojos;
+
+public class SimpleBean {
+    public static class Nested {
+
+    }
+}

Propchange: 
aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/pojos/SimpleBean.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/pojos/SimpleBean.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: 
aries/trunk/blueprint/blueprint-core/src/test/resources/test-bean-classes.xml
URL: 
http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/test/resources/test-bean-classes.xml?rev=1341886&view=auto
==============================================================================
--- 
aries/trunk/blueprint/blueprint-core/src/test/resources/test-bean-classes.xml 
(added)
+++ 
aries/trunk/blueprint/blueprint-core/src/test/resources/test-bean-classes.xml 
Wed May 23 14:54:39 2012
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0";
+            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+            xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0";
+            default-availability="mandatory" >
+
+    <bean id="simpleBean" class="org.apache.aries.blueprint.pojos.SimpleBean"/>
+    <bean id="simpleBeanNested" 
class="org.apache.aries.blueprint.pojos.SimpleBean.Nested"/>
+    
+
+</blueprint>

Propchange: 
aries/trunk/blueprint/blueprint-core/src/test/resources/test-bean-classes.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: 
aries/trunk/blueprint/blueprint-core/src/test/resources/test-bean-classes.xml
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Propchange: 
aries/trunk/blueprint/blueprint-core/src/test/resources/test-bean-classes.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml


Reply via email to