You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by zo...@apache.org on 2011/02/27 22:21:22 UTC

svn commit: r1075149 [18/23] - in /aries/tags/blueprint-0.3.1: ./ blueprint-annotation-api/ blueprint-annotation-api/src/ blueprint-annotation-api/src/main/ blueprint-annotation-api/src/main/java/ blueprint-annotation-api/src/main/java/org/ blueprint-a...

Added: aries/tags/blueprint-0.3.1/blueprint-core/src/main/java/org/apache/aries/blueprint/utils/ReflectionUtils.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3.1/blueprint-core/src/main/java/org/apache/aries/blueprint/utils/ReflectionUtils.java?rev=1075149&view=auto
==============================================================================
--- aries/tags/blueprint-0.3.1/blueprint-core/src/main/java/org/apache/aries/blueprint/utils/ReflectionUtils.java (added)
+++ aries/tags/blueprint-0.3.1/blueprint-core/src/main/java/org/apache/aries/blueprint/utils/ReflectionUtils.java Sun Feb 27 21:21:05 2011
@@ -0,0 +1,580 @@
+/**
+ * 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.utils;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Collection;
+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;
+import java.util.WeakHashMap;
+
+import org.apache.aries.blueprint.ExtendedBlueprintContainer;
+import org.apache.aries.blueprint.container.GenericType;
+import org.apache.aries.blueprint.di.ExecutionContext;
+import org.osgi.framework.BundleReference;
+import org.osgi.service.blueprint.container.ComponentDefinitionException;
+
+/**
+ * TODO: javadoc
+ *
+ * @version $Rev: 1055827 $, $Date: 2011-01-06 11:03:36 +0000 (Thu, 06 Jan 2011) $
+ */
+public class ReflectionUtils {
+
+    // TODO: MLK: PropertyDescriptor holds a reference to Method which holds a reference to the Class itself
+    private static Map<Class<?>, PropertyDescriptor[][]> beanInfos = Collections.synchronizedMap(new WeakHashMap<Class<?>, PropertyDescriptor[][]>());
+
+    public static boolean hasDefaultConstructor(Class type) {
+        if (!Modifier.isPublic(type.getModifiers())) {
+            return false;
+        }
+        if (Modifier.isAbstract(type.getModifiers())) {
+            return false;
+        }
+        Constructor[] constructors = type.getConstructors();
+        for (Constructor constructor : constructors) {
+            if (Modifier.isPublic(constructor.getModifiers()) &&
+                    constructor.getParameterTypes().length == 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    public static Set<String> getImplementedInterfaces(Set<String> classes, Class clazz) {
+        if (clazz != null && clazz != Object.class) {
+            for (Class itf : clazz.getInterfaces()) {
+                if (Modifier.isPublic(itf.getModifiers())) {
+                    classes.add(itf.getName());
+                }
+                getImplementedInterfaces(classes, itf);
+            }
+            getImplementedInterfaces(classes, clazz.getSuperclass());
+        }
+        return classes;
+    }
+
+    public static Set<String> getSuperClasses(Set<String> classes, Class clazz) {
+        if (clazz != null && clazz != Object.class) {
+            if (Modifier.isPublic(clazz.getModifiers())) {
+                classes.add(clazz.getName());
+            }
+            getSuperClasses(classes, clazz.getSuperclass());
+        }
+        return classes;
+    }
+
+    public static Method getLifecycleMethod(Class clazz, String name) {
+        if (name != null) {
+            try {
+                Method method = clazz.getMethod(name);
+                if (Void.TYPE.equals(method.getReturnType())) {
+                    return method;
+                }
+            } catch (NoSuchMethodException e) {
+                // fall thru
+            }
+        }
+        return null;
+    }
+    
+    public static List<Method> findCompatibleMethods(Class clazz, String name, Class[] paramTypes) {
+        List<Method> methods = new ArrayList<Method>();
+        for (Method method : clazz.getMethods()) {
+            Class[] methodParams = method.getParameterTypes();
+            if (name.equals(method.getName()) && Void.TYPE.equals(method.getReturnType()) && methodParams.length == paramTypes.length && !method.isBridge()) {
+                boolean assignable = true;
+                for (int i = 0; i < paramTypes.length && assignable; i++) {
+                    assignable &= paramTypes[i] == null || methodParams[i].isAssignableFrom(paramTypes[i]);
+                }
+                if (assignable) {
+                    methods.add(method);
+                }
+            }
+        }
+        return methods;
+    }
+
+    public static PropertyDescriptor[] getPropertyDescriptors(Class clazz, boolean allowFieldInjection) {
+        PropertyDescriptor[][] properties = beanInfos.get(clazz);
+        int index = allowFieldInjection ? 0 : 1;
+        
+        if (properties == null) {
+            properties = new PropertyDescriptor[2][];
+            beanInfos.put(clazz, properties);
+        }
+        
+        if (properties[index] == null) {
+            Set<String> propertyNames = new HashSet<String>();
+            Map<String,Method> getters = new HashMap<String, Method>();
+            Map<String,List<Method>> setters = new HashMap<String, List<Method>>();
+            Set<String> illegalProperties = new HashSet<String>();
+            
+            for (Method method : clazz.getMethods()) {
+                if (Modifier.isStatic(method.getModifiers()) || method.isBridge()) continue;
+                
+                String name = method.getName();
+                Class<?> argTypes[] = method.getParameterTypes();
+                Class<?> resultType = method.getReturnType();
+                
+                if (name.length() > 3 && name.startsWith("set") && resultType == Void.TYPE && argTypes.length == 1) {
+                    name = decapitalize(name.substring(3));
+                    if (!!!setters.containsKey(name)) setters.put(name, new ArrayList<Method>());
+                    setters.get(name).add(method);
+                    propertyNames.add(name);
+                } else if (name.length() > 3 && name.startsWith("get") && resultType != Void.TYPE && argTypes.length == 0) {
+                    name = decapitalize(name.substring(3));
+
+                    if (getters.containsKey(name)) illegalProperties.add(name);
+                    else propertyNames.add(name);
+                    
+                    getters.put(name, method);                    
+                } else if (name.length() > 2 && name.startsWith("is") && argTypes.length == 0 && resultType == boolean.class) {
+                    name = decapitalize(name.substring(2));
+
+                    if (getters.containsKey(name)) illegalProperties.add(name);
+                    else propertyNames.add(name);
+                    
+                    getters.put(name, method);                    
+                }
+                
+            }
+
+            Map<String, PropertyDescriptor> props = new HashMap<String, PropertyDescriptor>();
+            for (String propName : propertyNames) {
+                props.put(propName,
+                        new MethodPropertyDescriptor(propName, getters.get(propName), setters.get(propName)));
+            }            
+            
+            if (allowFieldInjection) {
+                for (Class cl = clazz; cl != null && cl != Object.class; cl = cl.getSuperclass()) {
+                    for (Field field : cl.getDeclaredFields()) {
+                        if (!!!Modifier.isStatic(field.getModifiers())) {
+                            String name = decapitalize(field.getName());
+                            PropertyDescriptor desc = props.get(name);
+                            if (desc == null) {
+                                props.put(name, new FieldPropertyDescriptor(name, field));
+                            } else if (desc instanceof MethodPropertyDescriptor) {
+                                props.put(name,
+                                        new JointPropertyDescriptor((MethodPropertyDescriptor) desc,
+                                                new FieldPropertyDescriptor(name, field)));
+                            } else {
+                                illegalProperties.add(name);
+                            }
+                        }
+                    }
+                }
+            }
+            
+            List<PropertyDescriptor> result = new ArrayList<PropertyDescriptor>();
+            for (PropertyDescriptor prop : props.values()) {
+                if (!!!illegalProperties.contains(prop.getName())) result.add(prop);
+            }
+            
+            properties[index] = result.toArray(new PropertyDescriptor[result.size()]); 
+        }
+        return properties[index];
+    }
+
+    private static String decapitalize(String name) {
+        if (name == null || name.length() == 0) {
+            return name;
+        }
+        if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
+                Character.isUpperCase(name.charAt(0))) {
+            return name;
+        }
+        char chars[] = name.toCharArray();
+        chars[0] = Character.toLowerCase(chars[0]);
+        return new String(chars);
+    }
+
+    public static Object invoke(AccessControlContext acc, final Method method, final Object instance, final Object... args) throws Exception {
+        if (acc == null) {
+            return method.invoke(instance, args);
+        } else {
+            try {
+                return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+                    public Object run() throws Exception {
+                        return method.invoke(instance, args);
+                    }            
+                }, acc);
+            } catch (PrivilegedActionException e) {
+                throw e.getException();
+            }
+        }
+    }
+    
+    public static Object newInstance(AccessControlContext acc, final Class clazz) throws Exception {
+        if (acc == null) {
+            return clazz.newInstance();
+        } else {
+            try {
+                return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+                    public Object run() throws Exception {
+                        return clazz.newInstance();
+                    }            
+                }, acc);
+            } catch (PrivilegedActionException e) {
+                throw e.getException();
+            }
+        }
+    }
+    
+    public static Object newInstance(AccessControlContext acc, final Constructor constructor, final Object... args) throws Exception {
+        if (acc == null) {
+            return constructor.newInstance(args);
+        } else {
+            try {
+                return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+                    public Object run() throws Exception {
+                        return constructor.newInstance(args);
+                    }            
+                }, acc);
+            } catch (PrivilegedActionException e) {
+                throw e.getException();
+            }
+        }
+    }
+    
+    public static abstract class PropertyDescriptor {
+        private final String name;
+        
+        public PropertyDescriptor(String name) {
+            this.name = name;
+        }
+        
+        public String getName() {
+            return name;
+        }
+        
+        public abstract boolean allowsGet();
+        public abstract boolean allowsSet();
+        
+        protected abstract Object internalGet(ExtendedBlueprintContainer container, Object instance) throws Exception;
+        protected abstract void internalSet(ExtendedBlueprintContainer container, Object instance, Object value) throws Exception;        
+        
+        public Object get(final Object instance, final ExtendedBlueprintContainer container) throws Exception {            
+            if (container.getAccessControlContext() == null) {
+                return internalGet(container, instance);
+            } else {
+                try {
+                    return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+                        public Object run() throws Exception {
+                            return internalGet(container, instance);
+                        }            
+                    }, container.getAccessControlContext());
+                } catch (PrivilegedActionException e) {
+                    throw e.getException();
+                }
+            }
+        }
+
+        public void set(final Object instance, final Object value, final ExtendedBlueprintContainer container) throws Exception {
+            if (container.getAccessControlContext() == null) {
+                internalSet(container, instance, value);
+            } else {
+                try {
+                    AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+                        public Object run() throws Exception {
+                            internalSet(container, instance, value);
+                            return null;
+                        }            
+                    }, container.getAccessControlContext());
+                } catch (PrivilegedActionException e) {
+                    throw e.getException();
+                }
+            }            
+        }
+        
+        protected Object convert(Object obj, Type type) throws Exception {
+            return ExecutionContext.Holder.getContext().convert(obj, new GenericType(type));
+        }
+    }
+    
+    private static class JointPropertyDescriptor extends PropertyDescriptor {
+        private final MethodPropertyDescriptor mpd;
+        private final FieldPropertyDescriptor fpd;
+        
+        public JointPropertyDescriptor(MethodPropertyDescriptor mpd, FieldPropertyDescriptor fpd) {
+            super(mpd.getName());
+            this.mpd = mpd;
+            this.fpd = fpd;
+        }
+
+        @Override
+        public boolean allowsGet() {
+            return mpd.allowsGet() || fpd.allowsGet();
+        }
+
+        @Override
+        public boolean allowsSet() {
+            return mpd.allowsSet() || fpd.allowsSet();
+        }
+
+        @Override
+        protected Object internalGet(ExtendedBlueprintContainer container, Object instance) throws Exception {
+            if (mpd.allowsGet()) return mpd.internalGet(container, instance);
+            else if (fpd.allowsGet()) return fpd.internalGet(container, instance);
+            else throw new UnsupportedOperationException();
+        }
+
+        @Override
+        protected void internalSet(ExtendedBlueprintContainer container, Object instance, Object value) throws Exception {
+            if (mpd.allowsSet()) mpd.internalSet(container, instance, value);
+            else if (fpd.allowsSet()) fpd.internalSet(container, instance, value);
+            else throw new UnsupportedOperationException();
+        }
+    }
+    
+    private static class FieldPropertyDescriptor extends PropertyDescriptor {
+        private final Field field;
+        
+        public FieldPropertyDescriptor(String name, Field field) {
+            super(name);
+            this.field = field;
+        }
+
+        public boolean allowsGet() {
+            return true;
+        }
+
+        public boolean allowsSet() {
+            return true;
+        }
+
+        protected Object internalGet(ExtendedBlueprintContainer container, final Object instance) throws IllegalArgumentException, IllegalAccessException {
+            if (useContainersPermission(container)) {
+                try {
+                    return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+                        public Object run() throws Exception {
+                            field.setAccessible(true);
+                            return field.get(instance);
+                        }                        
+                    });
+                } catch (PrivilegedActionException pae) {
+                    Exception e = pae.getException();
+                    if (e instanceof IllegalAccessException) throw (IllegalAccessException) e;
+                    else throw (RuntimeException) e;
+                }
+            } else {
+                field.setAccessible(true);
+                return field.get(instance);
+            }
+        }
+
+        protected void internalSet(ExtendedBlueprintContainer container, final Object instance, Object value) throws Exception {
+            final Object convertedValue = convert(value, field.getGenericType());
+            if (useContainersPermission(container)) {
+                try {
+                    AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+                        public Object run() throws Exception {
+                            field.setAccessible(true);
+                            field.set(instance, convertedValue);
+                            return null;
+                        }                        
+                    });
+                } catch (PrivilegedActionException pae) {
+                    throw pae.getException();
+                }
+            } else {
+                field.setAccessible(true);
+                field.set(instance, convertedValue);
+            }
+        }
+        
+        /**
+         * Determine whether the field access (in particular the call to {@link Field#setAccessible(boolean)} should be done with the Blueprint extender's
+         * permissions, rather than the joint (more restrictive) permissions of the extender plus the Blueprint bundle.
+         * 
+         * We currently only allow this for classes that originate from inside the Blueprint bundle. Otherwise this would open a potential security hole.
+         * @param container
+         * @return
+         */
+        private boolean useContainersPermission(ExtendedBlueprintContainer container) {
+            ClassLoader loader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+                public ClassLoader run() {
+                    return field.getDeclaringClass().getClassLoader();
+                }
+            });            
+            
+            if (loader == null) return false;
+            
+            if (loader instanceof BundleReference) {
+                BundleReference ref = (BundleReference) loader;
+                return ref.getBundle().equals(container.getBundleContext().getBundle());                
+            }
+            
+            return false;
+        }
+    }
+    
+    private static class MethodPropertyDescriptor extends PropertyDescriptor {
+        private final Method getter;
+        private final Collection<Method> setters;
+
+        private MethodPropertyDescriptor(String name, Method getter, Collection<Method> setters) {
+            super(name);
+            this.getter = getter;
+            this.setters = (setters != null) ? setters : Collections.<Method>emptyList();
+        }
+        
+        public boolean allowsGet() {
+            return getter != null;
+        }
+        
+        public boolean allowsSet() {
+            return !!!setters.isEmpty();
+        }
+        
+        protected Object internalGet(ExtendedBlueprintContainer container, Object instance) 
+                throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
+            if (getter != null) {
+                return getter.invoke(instance);
+            } else {
+                throw new UnsupportedOperationException();
+            }
+        }
+        
+        protected void internalSet(ExtendedBlueprintContainer container, Object instance, Object value) throws Exception {
+            
+            Method setterMethod = findSetter(value);
+
+            if (setterMethod != null) {
+                setterMethod.invoke(instance, convert(value, setterMethod.getGenericParameterTypes()[0]));
+            } else {
+                throw new ComponentDefinitionException(
+                        "No converter available to convert value "+value+" into a form applicable for the " + 
+                        "setters of property "+getName());
+            }
+        }
+        
+        private Method findSetter(Object value) {
+            Class<?> valueType = (value == null) ? null : value.getClass();
+            
+            Method result = findMethodByClass(valueType);
+            
+            if (result == null) result = findMethodWithConversion(value);
+                        
+            return result;
+        }
+        
+        private Method findMethodByClass(Class<?> arg)
+                throws ComponentDefinitionException {
+            Method result = null;
+
+            if (!hasSameTypeSetter()) {
+                throw new ComponentDefinitionException(
+                        "At least one Setter method has to match the type of the Getter method for property "
+                                + getName());
+            }
+
+            if (setters.size() == 1) {
+                return setters.iterator().next();
+            }
+            
+            for (Method m : setters) {
+                Class<?> paramType = m.getParameterTypes()[0];
+
+                if ((arg == null && Object.class.isAssignableFrom(paramType))
+                        || (arg != null && paramType.isAssignableFrom(arg))) {
+
+                    // pick the method that has the more specific parameter if
+                    // any
+                    if (result != null) {
+                        Class<?> oldParamType = result.getParameterTypes()[0];
+                        if (paramType.isAssignableFrom(oldParamType)) {
+                            // do nothing, result is correct
+                        } else if (oldParamType.isAssignableFrom(paramType)) {
+                            result = m;
+                        } else {
+                            throw new ComponentDefinitionException(
+                                    "Ambiguous setter method for property "
+                                            + getName()
+                                            + ". More than one method matches the  parameter type "
+                                            + arg);
+                        }
+                    } else {
+                        result = m;
+                    }
+                }
+            }
+
+            return result;
+        }
+        
+        // ensure there is a setter that matches the type of the getter
+        private boolean hasSameTypeSetter() {
+            if (getter == null) {
+                return true;
+            }
+            Iterator<Method> it = setters.iterator();
+            while (it.hasNext()) {
+                Method m = it.next();
+                if (m.getParameterTypes()[0].equals(getter.getReturnType())) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        private Method findMethodWithConversion(Object value) throws ComponentDefinitionException {
+            ExecutionContext ctx = ExecutionContext.Holder.getContext();
+            List<Method> matchingMethods = new ArrayList<Method>();
+            for (Method m : setters) {
+                Type paramType = m.getGenericParameterTypes()[0];
+                if (ctx.canConvert(value, new GenericType(paramType))) matchingMethods.add(m);
+            }
+            
+            if (matchingMethods.isEmpty()) return null;
+            else if (matchingMethods.size() == 1) return matchingMethods.get(0);
+            else throw new ComponentDefinitionException(
+                    "Ambiguous setter method for property "+ getName() + 
+                    ". More than one method matches the parameter "+value+" after applying conversion.");
+        }
+        
+        public String toString() {
+            return "PropertyDescriptor <name: "+getName()+", getter: "+getter+", setter: "+setters;
+        }
+    }
+
+    public static Throwable getRealCause(Throwable t) {
+        if (t instanceof InvocationTargetException && t.getCause() != null) {
+            return t.getCause();
+        }
+        return t;
+    }
+
+}

Added: aries/tags/blueprint-0.3.1/blueprint-core/src/main/resources/OSGI-INF/blueprint/blueprint-ext.xml
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3.1/blueprint-core/src/main/resources/OSGI-INF/blueprint/blueprint-ext.xml?rev=1075149&view=auto
==============================================================================
--- aries/tags/blueprint-0.3.1/blueprint-core/src/main/resources/OSGI-INF/blueprint/blueprint-ext.xml (added)
+++ aries/tags/blueprint-0.3.1/blueprint-core/src/main/resources/OSGI-INF/blueprint/blueprint-ext.xml Sun Feb 27 21:21:05 2011
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+
+    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" default-activation="lazy">
+
+    <service interface="org.apache.aries.blueprint.NamespaceHandler">
+        <service-properties>
+            <entry key="osgi.service.blueprint.namespace" value="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"/>
+        </service-properties>
+        <bean class="org.apache.aries.blueprint.ext.ExtNamespaceHandler"/>
+    </service>
+
+</blueprint>

Added: aries/tags/blueprint-0.3.1/blueprint-core/src/main/resources/OSGI-INF/permissions.perm
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3.1/blueprint-core/src/main/resources/OSGI-INF/permissions.perm?rev=1075149&view=auto
==============================================================================
--- aries/tags/blueprint-0.3.1/blueprint-core/src/main/resources/OSGI-INF/permissions.perm (added)
+++ aries/tags/blueprint-0.3.1/blueprint-core/src/main/resources/OSGI-INF/permissions.perm Sun Feb 27 21:21:05 2011
@@ -0,0 +1,26 @@
+################################################################################
+#
+#    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.
+#
+################################################################################
+# Lines beginning with '#' or '//' are comments
+#
+# This file contains the permissions to be granted.
+# The permissions are listed one per
+# line in PermissionInfo encoded format.
+# See org.osgi.service.permissionadmin.PermissionInfo
+
+(java.security.AllPermission "" "")

Added: aries/tags/blueprint-0.3.1/blueprint-core/src/main/resources/org/apache/aries/blueprint/ext/blueprint-ext.xsd
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3.1/blueprint-core/src/main/resources/org/apache/aries/blueprint/ext/blueprint-ext.xsd?rev=1075149&view=auto
==============================================================================
--- aries/tags/blueprint-0.3.1/blueprint-core/src/main/resources/org/apache/aries/blueprint/ext/blueprint-ext.xsd (added)
+++ aries/tags/blueprint-0.3.1/blueprint-core/src/main/resources/org/apache/aries/blueprint/ext/blueprint-ext.xsd Sun Feb 27 21:21:05 2011
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+
+    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.
+
+-->
+<xsd:schema xmlns="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
+            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+            xmlns:bp="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+            targetNamespace="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
+            elementFormDefault="qualified"
+            attributeFormDefault="unqualified"
+            version="1.0.0">
+
+    <xsd:import namespace="http://www.osgi.org/xmlns/blueprint/v1.0.0"/>
+
+    <!-- property placeholder -->
+
+    <xsd:element name="property-placeholder" type="TpropertyPlaceholder"/>
+
+    <xsd:complexType name="TpropertyPlaceholder">
+        <xsd:complexContent>
+            <xsd:extension base="bp:Tcomponent">
+                <xsd:sequence>
+                    <!-- nested properties declaration -->
+                    <xsd:element name="default-properties" type="TdefaultProperties" minOccurs="0" maxOccurs="1"/>
+                    <xsd:element name="location" minOccurs="0" maxOccurs="unbounded" type="xsd:string"/>
+                </xsd:sequence>
+                <xsd:attribute name="placeholder-prefix" type="xsd:string" use="optional" default="${"/>
+                <xsd:attribute name="placeholder-suffix" type="xsd:string" use="optional" default="}"/>
+                <xsd:attribute name="defaults-ref" type="bp:Tidref" use="optional"/>
+                <xsd:attribute name="ignore-missing-locations" type="xsd:boolean" use="optional" default="false"/>
+                <xsd:attribute name="system-properties" use="optional" default="fallback">
+                    <xsd:simpleType>
+                        <xsd:restriction base="xsd:NMTOKEN">
+                            <xsd:enumeration value="never"/>
+                            <xsd:enumeration value="fallback"/>
+                            <xsd:enumeration value="override"/>
+                        </xsd:restriction>
+                    </xsd:simpleType>
+                </xsd:attribute>
+            </xsd:extension>
+        </xsd:complexContent>
+    </xsd:complexType>
+
+    <xsd:complexType name="TdefaultProperties">
+        <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+            <xsd:element name="property" type="bp:Tproperty"/>
+        </xsd:sequence>
+    </xsd:complexType>
+
+    <!-- proxy method -->
+
+    <xsd:attribute name="proxy-method" default="default">
+        <xsd:simpleType>
+            <xsd:restriction>
+                <xsd:simpleType>
+                    <xsd:list>
+                        <xsd:simpleType>
+                            <xsd:restriction base="xsd:NMTOKEN">
+                                <xsd:enumeration value="default"/>
+                                <xsd:enumeration value="classes"/>
+                                <xsd:enumeration value="greedy"/>
+                            </xsd:restriction>
+                        </xsd:simpleType>
+                    </xsd:list>
+                </xsd:simpleType>
+                <xsd:minLength value="1"/>
+            </xsd:restriction>
+        </xsd:simpleType>
+    </xsd:attribute>
+
+    <!-- role -->
+
+    <xsd:attribute name="role">
+        <xsd:simpleType>
+            <xsd:restriction>
+                <xsd:simpleType>
+                    <xsd:list>
+                        <xsd:simpleType>
+                            <xsd:restriction base="xsd:NMTOKEN">
+                                <xsd:enumeration value="processor"/>
+                            </xsd:restriction>
+                        </xsd:simpleType>
+                    </xsd:list>
+                </xsd:simpleType>
+            </xsd:restriction>
+        </xsd:simpleType>
+    </xsd:attribute>
+
+    <!-- CM property placeholder extenstion -->
+
+    <xsd:element name="location" type="xsd:string"/>
+    <xsd:attribute name="ignore-missing-locations" type="xsd:boolean" default="false"/>
+    <xsd:attribute name="system-properties" default="fallback">
+        <xsd:simpleType>
+            <xsd:restriction base="xsd:NMTOKEN">
+                <xsd:enumeration value="never"/>
+                <xsd:enumeration value="fallback"/>
+                <xsd:enumeration value="override"/>
+            </xsd:restriction>
+        </xsd:simpleType>
+    </xsd:attribute>
+    
+    <xsd:attribute name="field-injection" type="xsd:boolean" default="false" />
+
+</xsd:schema>

Added: aries/tags/blueprint-0.3.1/blueprint-core/src/main/resources/org/apache/aries/blueprint/nls/BlueprintMessages.properties
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3.1/blueprint-core/src/main/resources/org/apache/aries/blueprint/nls/BlueprintMessages.properties?rev=1075149&view=auto
==============================================================================
--- aries/tags/blueprint-0.3.1/blueprint-core/src/main/resources/org/apache/aries/blueprint/nls/BlueprintMessages.properties (added)
+++ aries/tags/blueprint-0.3.1/blueprint-core/src/main/resources/org/apache/aries/blueprint/nls/BlueprintMessages.properties Sun Feb 27 21:21:05 2011
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+duplicate.component=The component name {0} is already in use.

Added: aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/AbstractBlueprintTest.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/AbstractBlueprintTest.java?rev=1075149&view=auto
==============================================================================
--- aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/AbstractBlueprintTest.java (added)
+++ aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/AbstractBlueprintTest.java Sun Feb 27 21:21:05 2011
@@ -0,0 +1,75 @@
+/*
+ * 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 java.io.IOException;
+import java.net.URI;
+import java.util.Collections;
+import java.util.Set;
+
+import javax.xml.validation.Schema;
+
+import junit.framework.TestCase;
+
+import org.apache.aries.blueprint.container.NamespaceHandlerRegistry;
+import org.apache.aries.blueprint.container.Parser;
+import org.apache.aries.blueprint.ext.ExtNamespaceHandler;
+import org.apache.aries.blueprint.namespace.ComponentDefinitionRegistryImpl;
+import org.xml.sax.SAXException;
+
+public abstract class AbstractBlueprintTest extends TestCase {
+
+    protected ComponentDefinitionRegistryImpl parse(String name) throws Exception {
+      final URI extensionHandler = new URI("http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0");
+      NamespaceHandlerRegistry.NamespaceHandlerSet handlers = new NamespaceHandlerRegistry.NamespaceHandlerSet() {
+            public Set<URI> getNamespaces() {
+                return null;
+            }
+            public NamespaceHandler getNamespaceHandler(URI namespace) {
+                if (namespace.equals(extensionHandler)) {
+                  return new ExtNamespaceHandler();
+                } else {
+                  return null;
+                }
+            }
+            public void removeListener(NamespaceHandlerRegistry.Listener listener) {
+            }
+            public Schema getSchema() throws SAXException, IOException {
+                return null;
+            }
+            public boolean isComplete() {
+                return false;
+            }
+            public void addListener(NamespaceHandlerRegistry.Listener listener) {
+            }
+            public void destroy() {
+            }
+        };
+        return parse(name, handlers);
+    }
+
+    protected ComponentDefinitionRegistryImpl parse(String name, NamespaceHandlerRegistry.NamespaceHandlerSet handlers) throws Exception {
+        ComponentDefinitionRegistryImpl registry = new ComponentDefinitionRegistryImpl();
+        Parser parser = new Parser();
+        parser.parse(Collections.singletonList(getClass().getResource(name)));
+        parser.populate(handlers, registry);
+        return registry;
+    }
+
+}

Added: aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/CallbackTracker.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/CallbackTracker.java?rev=1075149&view=auto
==============================================================================
--- aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/CallbackTracker.java (added)
+++ aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/CallbackTracker.java Sun Feb 27 21:21:05 2011
@@ -0,0 +1,66 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+
+public class CallbackTracker {
+
+    private static List<Callback> callbacks = new ArrayList<Callback>();
+    
+    public static void add(Callback callback) {
+        callbacks.add(callback);
+    }
+    
+    public static List<Callback> getCallbacks() {
+        return callbacks;
+    }
+    
+    public static void clear() {
+        callbacks.clear();
+    }
+    
+    public static class Callback {
+        
+        public static int INIT = 1;
+        public static int DESTROY = 2;
+        
+        private Object object;
+        private int type;
+        
+        public Callback(int type, Object object) {
+            this.type = type;
+            this.object = object;
+        }        
+        
+        public int getType() {
+            return type;
+        }
+        
+        public Object getObject() {
+            return object;
+        }
+        
+        public String toString() {
+            return type + " " + object;
+        }
+        
+    }
+}

Added: aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/ParserTest.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/ParserTest.java?rev=1075149&view=auto
==============================================================================
--- aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/ParserTest.java (added)
+++ aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/ParserTest.java Sun Feb 27 21:21:05 2011
@@ -0,0 +1,299 @@
+/*
+ * 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 java.net.URI;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.io.IOException;
+
+import javax.xml.validation.Schema;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import org.apache.aries.blueprint.container.NamespaceHandlerRegistry;
+import org.apache.aries.blueprint.reflect.BeanMetadataImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.service.blueprint.reflect.BeanArgument;
+import org.osgi.service.blueprint.reflect.BeanMetadata;
+import org.osgi.service.blueprint.reflect.BeanProperty;
+import org.osgi.service.blueprint.reflect.CollectionMetadata;
+import org.osgi.service.blueprint.reflect.ComponentMetadata;
+import org.osgi.service.blueprint.reflect.Metadata;
+import org.osgi.service.blueprint.reflect.NullMetadata;
+import org.osgi.service.blueprint.reflect.RefMetadata;
+import org.osgi.service.blueprint.reflect.ValueMetadata;
+import org.xml.sax.SAXException;
+
+/**
+ * TODO: constructor injection
+ * TODO: Dependency#setMethod 
+ */
+public class ParserTest extends AbstractBlueprintTest {
+
+    public void test() {
+        Integer[] oo = new Integer[1];
+        Object[] ii = oo;
+    }
+
+    public void testParseComponent() throws Exception {
+        ComponentDefinitionRegistry registry = parse("/test-simple-component.xml");
+        assertNotNull(registry);
+        ComponentMetadata component = registry.getComponentDefinition("pojoA");
+        assertNotNull(component);
+        assertEquals("pojoA", component.getId());
+        assertTrue(component instanceof BeanMetadata);
+        BeanMetadata local = (BeanMetadata) component;
+        List<String> deps = local.getDependsOn();
+        assertNotNull(deps);
+        assertEquals(2, deps.size());
+        assertTrue(deps.contains("pojoB"));
+        assertTrue(deps.contains("pojoC"));
+        assertEquals("org.apache.aries.blueprint.pojos.PojoA", local.getClassName());
+        List<BeanArgument> params = local.getArguments();
+        assertNotNull(params);
+        assertEquals(6, params.size());
+        BeanArgument param = params.get(0);
+        assertNotNull(param);
+        assertEquals(-1, param.getIndex());
+        assertNull(param.getValueType());
+        assertNotNull(param.getValue());
+        assertTrue(param.getValue() instanceof ValueMetadata);
+        assertEquals("val0", ((ValueMetadata) param.getValue()).getStringValue());
+        assertNull(((ValueMetadata) param.getValue()).getType());
+        param = params.get(1);
+        assertNotNull(param);
+        assertEquals(-1, param.getIndex());
+        assertNull(param.getValueType());
+        assertNotNull(param.getValue());
+        assertTrue(param.getValue() instanceof RefMetadata);
+        assertEquals("val1", ((RefMetadata) param.getValue()).getComponentId());
+        param = params.get(2);
+        assertNotNull(param);
+        assertEquals(-1, param.getIndex());
+        assertNull(param.getValueType());
+        assertNotNull(param.getValue());
+        assertTrue(param.getValue() instanceof NullMetadata);
+        param = params.get(3);
+        assertNotNull(param);
+        assertEquals(-1, param.getIndex());
+        assertEquals("java.lang.String", param.getValueType());
+        assertNotNull(param.getValue());
+        assertTrue(param.getValue() instanceof ValueMetadata);
+        assertEquals("val3", ((ValueMetadata) param.getValue()).getStringValue());
+        assertNull(((ValueMetadata) param.getValue()).getType());
+        param = params.get(4);
+        assertNotNull(param);
+        assertEquals(-1, param.getIndex());
+        assertNull(param.getValueType());
+        assertNotNull(param.getValue());
+        assertTrue(param.getValue() instanceof CollectionMetadata);
+        CollectionMetadata array = (CollectionMetadata) param.getValue();
+        assertNull(array.getValueType());
+        assertNotNull(array.getValues());
+        assertEquals(3, array.getValues().size());
+        assertTrue(array.getValues().get(0) instanceof ValueMetadata);
+        assertTrue(array.getValues().get(1) instanceof ComponentMetadata);
+        assertTrue(array.getValues().get(2) instanceof NullMetadata);
+        param = params.get(5);
+        assertNotNull(param);
+        assertEquals(-1, param.getIndex());
+        assertNull(param.getValueType());
+        assertNotNull(param.getValue());
+        assertTrue(param.getValue() instanceof RefMetadata);
+        assertEquals("pojoB", ((RefMetadata) param.getValue()).getComponentId());
+        
+        assertEquals(null, local.getInitMethod());
+        assertEquals(null, local.getDestroyMethod());
+                
+        // test pojoB
+        ComponentMetadata pojoB = registry.getComponentDefinition("pojoB");
+        assertNotNull(pojoB);
+        assertEquals("pojoB", pojoB.getId());
+        assertTrue(pojoB instanceof BeanMetadata);
+        BeanMetadata pojoBLocal = (BeanMetadata) pojoB;
+        assertEquals("initPojo", pojoBLocal.getInitMethod());
+//        assertEquals("", pojoBLocal.getDestroyMethod());
+        
+        params = pojoBLocal.getArguments();
+        assertNotNull(params);
+        assertEquals(2, params.size());
+        param = params.get(0);
+        assertNotNull(param);
+        assertEquals(1, param.getIndex());
+        param = params.get(1);
+        assertNotNull(param);
+        assertEquals(0, param.getIndex());
+    }
+
+    public void testParse() throws Exception {
+        parse("/test.xml");
+    }
+
+
+    public void testCustomNodes() throws Exception {
+        ComponentDefinitionRegistry registry = parse("/test-custom-nodes.xml", new TestNamespaceHandlerSet());
+        
+        ComponentMetadata metadata;
+        
+        metadata = registry.getComponentDefinition("fooService");
+        assertNotNull(metadata);
+        assertTrue(metadata instanceof MyLocalComponentMetadata);
+        MyLocalComponentMetadata comp1 = (MyLocalComponentMetadata) metadata;
+        assertEquals(true, comp1.getCacheReturnValues());
+        assertEquals("getVolatile", comp1.getOperation());
+        
+        metadata = registry.getComponentDefinition("barService");
+        assertNotNull(metadata);
+        assertTrue(metadata instanceof BeanMetadata);
+        BeanMetadata comp2 = (BeanMetadata) metadata;
+        assertEquals(1, comp2.getProperties().size());
+        BeanProperty propertyMetadata = comp2.getProperties().get(0);
+        assertEquals("localCache", propertyMetadata.getName());
+        Metadata propertyValue = propertyMetadata.getValue();
+        assertTrue(propertyValue instanceof BeanMetadata);
+        BeanMetadata innerComp = (BeanMetadata) propertyValue;
+        assertEquals("org.apache.aries.CacheProperty", innerComp.getClassName()); 
+        
+        metadata = registry.getComponentDefinition("myCache");
+        assertNotNull(metadata);
+        assertTrue(metadata instanceof BeanMetadata);
+        BeanMetadata comp3 = (BeanMetadata) metadata;
+        assertEquals("org.apache.aries.Cache", comp3.getClassName());         
+    }
+
+    private static class TestNamespaceHandlerSet implements NamespaceHandlerRegistry.NamespaceHandlerSet {
+
+        private TestNamespaceHandlerSet() {
+        }
+
+        public Set<URI> getNamespaces() {
+            return Collections.singleton(URI.create("http://cache.org"));
+        }
+
+        public boolean isComplete() {
+            return true;
+        }
+
+        public NamespaceHandler getNamespaceHandler(URI namespace) {
+            URI u = URI.create("http://cache.org");
+            if (u.equals(namespace)) {
+                return new TestNamespaceHandler();
+            } else {
+                return null;
+            }
+        }
+
+        public Schema getSchema() throws SAXException, IOException {
+            return null;
+        }
+
+        public void addListener(NamespaceHandlerRegistry.Listener listener) {
+        }
+
+        public void removeListener(NamespaceHandlerRegistry.Listener listener) {
+        }
+
+        public void destroy() {
+        }
+    }
+
+    private static class TestNamespaceHandler implements NamespaceHandler {
+
+        public URL getSchemaLocation(String namespace) {
+            return getClass().getResource("/cache.xsd");
+        }
+
+        public Set<Class> getManagedClasses() {
+            return new HashSet<Class>();
+        }
+
+        public ComponentMetadata decorate(Node node,
+                                          ComponentMetadata component,
+                                          ParserContext context) {
+            //System.out.println("decorate: " + node + " " + component + " " + container.getEnclosingComponent().getId());
+            
+            if (node instanceof Attr) {
+                Attr attr = (Attr) node;
+                MyLocalComponentMetadata decoratedComp = new MyLocalComponentMetadata((BeanMetadata)component);
+                decoratedComp.setCacheReturnValues(Boolean.parseBoolean(attr.getValue()));
+                return decoratedComp;
+            } else if (node instanceof Element) {
+                Element element = (Element) node;                
+                MyLocalComponentMetadata decoratedComp = (MyLocalComponentMetadata) component;
+                decoratedComp.setOperation(element.getAttribute("name"));
+                return decoratedComp;
+            } else {
+                throw new RuntimeException("Unhandled node: " + node);
+            }
+        }
+
+        public Metadata parse(Element element, ParserContext context) {
+            String comp = (context.getEnclosingComponent() == null) ? null : context.getEnclosingComponent().getId();
+            //System.out.println("parse: " + element.getLocalName() + " " + comp);
+            
+            String className;
+            if (context.getEnclosingComponent() == null) {
+                className = "org.apache.aries.Cache";
+            } else {
+                className = "org.apache.aries.CacheProperty";
+            }
+                        
+            BeanMetadataImpl p = new BeanMetadataImpl();
+            p.setId(element.getAttribute("id"));
+            p.setClassName(className);
+            
+            return p;
+        }
+        
+    }
+    
+    private static class MyLocalComponentMetadata extends BeanMetadataImpl {
+        
+        private boolean cacheReturnValues;
+        private String operation;
+        
+        public MyLocalComponentMetadata(BeanMetadata impl) {
+            super(impl);
+        }
+        
+        public boolean getCacheReturnValues() {
+            return cacheReturnValues;
+        }
+        
+        public void setCacheReturnValues(boolean value) {
+            cacheReturnValues = value;
+        }
+        
+        public void setOperation(String operation) {
+            this.operation = operation;
+        }
+        
+        public String getOperation() {
+            return this.operation;
+        }
+    }
+
+}

Added: aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBlueprintContainer.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBlueprintContainer.java?rev=1075149&view=auto
==============================================================================
--- aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBlueprintContainer.java (added)
+++ aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBlueprintContainer.java Sun Feb 27 21:21:05 2011
@@ -0,0 +1,50 @@
+/*
+ * 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.container.BlueprintContainerImpl;
+import org.apache.aries.blueprint.namespace.ComponentDefinitionRegistryImpl;
+import org.apache.aries.blueprint.reflect.PassThroughMetadataImpl;
+
+public class TestBlueprintContainer extends BlueprintContainerImpl {
+
+    private ComponentDefinitionRegistryImpl registry;
+    
+    public TestBlueprintContainer(ComponentDefinitionRegistryImpl registry) {
+        super(new TestBundleContext(), null, null, null, null, null);
+        this.registry = registry;
+        if (registry != null) {
+            registry.registerComponentDefinition(new PassThroughMetadataImpl("blueprintContainer", this));
+            registry.registerComponentDefinition(new PassThroughMetadataImpl("blueprintBundle", getBundleContext().getBundle()));
+            registry.registerComponentDefinition(new PassThroughMetadataImpl("blueprintBundleContext", getBundleContext()));
+            registry.registerComponentDefinition(new PassThroughMetadataImpl("blueprintConverter", getConverter()));
+        }
+    }
+
+    @Override
+    public Class loadClass(String name) throws ClassNotFoundException {
+        return Thread.currentThread().getContextClassLoader().loadClass(name);
+    }
+
+    @Override
+    public ComponentDefinitionRegistryImpl getComponentDefinitionRegistry() {
+        return registry;
+    }
+
+}

Added: aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBundleContext.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBundleContext.java?rev=1075149&view=auto
==============================================================================
--- aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBundleContext.java (added)
+++ aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBundleContext.java Sun Feb 27 21:21:05 2011
@@ -0,0 +1,122 @@
+/*
+ * 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 java.io.File;
+import java.io.InputStream;
+import java.util.Dictionary;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkListener;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+public class TestBundleContext implements BundleContext {
+
+    public void addBundleListener(BundleListener arg0) {
+    }
+
+    public void addFrameworkListener(FrameworkListener arg0) {
+    }
+
+    public void addServiceListener(ServiceListener arg0) {
+    }
+
+    public void addServiceListener(ServiceListener arg0, String arg1)
+        throws InvalidSyntaxException {
+    }
+
+    public Filter createFilter(String arg0) throws InvalidSyntaxException {
+        return null;
+    }
+
+    public ServiceReference[] getAllServiceReferences(String arg0, String arg1)
+        throws InvalidSyntaxException {
+        return null;
+    }
+
+    public Bundle getBundle() {
+        return null;
+    }
+
+    public Bundle getBundle(long arg0) {
+        return null;
+    }
+
+    public Bundle[] getBundles() {
+        return null;
+    }
+
+    public File getDataFile(String arg0) {
+        return null;
+    }
+
+    public String getProperty(String arg0) {
+        return null;
+    }
+
+    public Object getService(ServiceReference arg0) {
+        return null;
+    }
+
+    public ServiceReference getServiceReference(String arg0) {
+        return null;
+    }
+
+    public ServiceReference[] getServiceReferences(String arg0, String arg1)
+    throws InvalidSyntaxException {
+        return null;
+    }
+
+    public Bundle installBundle(String arg0) throws BundleException {
+        return null;
+    }
+
+    public Bundle installBundle(String arg0, InputStream arg1) throws BundleException {
+        return null;
+    }
+
+    public ServiceRegistration registerService(String[] arg0, Object arg1, Dictionary arg2) {
+        return null;
+    }
+
+    public ServiceRegistration registerService(String arg0, Object arg1, Dictionary arg2) {
+        return null;
+    }
+
+    public void removeBundleListener(BundleListener arg0) {
+    }
+
+    public void removeFrameworkListener(FrameworkListener arg0) {
+    }
+
+    public void removeServiceListener(ServiceListener arg0) {
+    }
+
+    public boolean ungetService(ServiceReference arg0) {
+        return false;
+    }
+
+}

Added: aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/WiringTest.java
URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/WiringTest.java?rev=1075149&view=auto
==============================================================================
--- aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/WiringTest.java (added)
+++ aries/tags/blueprint-0.3.1/blueprint-core/src/test/java/org/apache/aries/blueprint/WiringTest.java Sun Feb 27 21:21:05 2011
@@ -0,0 +1,471 @@
+/*
+ * 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 java.math.BigInteger;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import junit.framework.Assert;
+
+import org.apache.aries.blueprint.CallbackTracker.Callback;
+import org.apache.aries.blueprint.container.BlueprintRepository;
+import org.apache.aries.blueprint.di.CircularDependencyException;
+import org.apache.aries.blueprint.di.Repository;
+import org.apache.aries.blueprint.namespace.ComponentDefinitionRegistryImpl;
+import org.apache.aries.blueprint.pojos.AmbiguousPojo;
+import org.apache.aries.blueprint.pojos.BeanD;
+import org.apache.aries.blueprint.pojos.BeanF;
+import org.apache.aries.blueprint.pojos.FITestBean;
+import org.apache.aries.blueprint.pojos.Multiple;
+import org.apache.aries.blueprint.pojos.PojoA;
+import org.apache.aries.blueprint.pojos.PojoB;
+import org.apache.aries.blueprint.pojos.PojoGenerics;
+import org.apache.aries.blueprint.pojos.PojoListener;
+import org.apache.aries.blueprint.pojos.PojoRecursive;
+import org.apache.aries.blueprint.pojos.Primavera;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.blueprint.container.ComponentDefinitionException;
+
+public class WiringTest extends AbstractBlueprintTest {
+
+    public void testWiring() throws Exception {
+        ComponentDefinitionRegistryImpl registry = parse("/test-wiring.xml");
+        Repository repository = new TestBlueprintContainer(registry).getRepository();
+        
+        Object obj1 = repository.create("pojoA");
+        assertNotNull(obj1);
+        assertTrue(obj1 instanceof PojoA);
+        PojoA pojoa = (PojoA) obj1;
+        // test singleton scope
+        assertTrue(obj1 == repository.create("pojoA"));
+        
+        Object obj2 = repository.create("pojoB");
+        assertNotNull(obj2);
+        assertTrue(obj2 instanceof PojoB);
+        PojoB pojob = (PojoB) obj2;
+        
+        assertNotNull(pojoa.getPojob());
+        assertNotNull(pojoa.getPojob().getUri());
+        
+        assertNotNull(pojoa.getList());
+        assertEquals("list value", pojoa.getList().get(0));
+        assertEquals(new Integer(55), pojoa.getList().get(2));
+        assertEquals(URI.create("http://geronimo.apache.org"), pojoa.getList().get(3));
+        Object c0 = pojoa.getList().get(1);
+        Object c1 = pojoa.getList().get(4);
+        assertNotNull(c0);
+        assertNotNull(c1);
+        assertEquals(PojoB.class, c0.getClass());
+        assertEquals(PojoB.class, c1.getClass());
+        assertNotSame(c0, c1);
+
+        assertNotNull(pojoa.getArray());
+        assertEquals("list value", pojoa.getArray()[0]);
+        assertEquals(pojob, pojoa.getArray()[1]);
+        assertEquals(new Integer(55), pojoa.getArray()[2]);
+        assertEquals(URI.create("http://geronimo.apache.org"), pojoa.getArray()[3]);
+        
+        assertNotNull(pojoa.getSet());
+        assertTrue(pojoa.getSet().contains("set value"));
+        assertTrue(pojoa.getSet().contains(pojob));
+        assertTrue(pojoa.getSet().contains(URI.create("http://geronimo.apache.org")));
+        
+        assertNotNull(pojoa.getMap());
+        assertEquals("val", pojoa.getMap().get("key"));
+        assertEquals(pojob, pojoa.getMap().get(pojob));      
+        assertEquals(URI.create("http://geronimo.apache.org"), pojoa.getMap().get(new Integer(5)));
+        
+        assertNotNull(pojoa.getProps());
+        assertEquals("value1", pojoa.getProps().get("key1"));
+        assertEquals("value2", pojoa.getProps().get("2"));
+        assertEquals("bar", pojoa.getProps().get("foo"));
+        
+        assertNotNull(pojoa.getNumber());
+        assertEquals(new BigInteger("10"), pojoa.getNumber());
+        
+        assertNotNull(pojoa.getIntArray());
+        assertEquals(3, pojoa.getIntArray().length);
+        assertEquals(1, pojoa.getIntArray()[0]);
+        assertEquals(50, pojoa.getIntArray()[1]);
+        assertEquals(100, pojoa.getIntArray()[2]);
+        
+        assertNotNull(pojoa.getNumberArray());
+        assertEquals(4, pojoa.getNumberArray().length);
+        assertEquals(new Integer(1), pojoa.getNumberArray()[0]);
+        assertEquals(new BigInteger("50"), pojoa.getNumberArray()[1]);
+        assertEquals(new Long(100), pojoa.getNumberArray()[2]);
+        assertEquals(new Integer(200), pojoa.getNumberArray()[3]);
+        
+        // test init-method
+        assertEquals(true, pojob.getInitCalled());
+        
+        // test service
+        Object obj3 = repository.create("service1");
+        assertNotNull(obj3);
+        assertTrue(obj3 instanceof ServiceRegistration);    
+        
+        // tests 'prototype' scope
+        Object obj4 = repository.create("pojoC");
+        assertNotNull(obj4);
+        
+        assertTrue(obj4 != repository.create("pojoC"));
+        
+        repository.destroy();
+        
+        // test destroy-method
+        assertEquals(true, pojob.getDestroyCalled());
+    }
+    
+    public void testSetterDisambiguation() throws Exception {
+        ComponentDefinitionRegistryImpl registry = parse("/test-wiring.xml");
+        Repository repository = new TestBlueprintContainer(registry).getRepository();
+
+        AmbiguousPojo pojo = (AmbiguousPojo) repository.create("ambiguousViaInt");
+        assertEquals(5, pojo.getSum());
+        
+        pojo = (AmbiguousPojo) repository.create("ambiguousViaList");
+        assertEquals(7, pojo.getSum());
+        
+        
+    }
+    
+    public void testFieldInjection() throws Exception {
+      ComponentDefinitionRegistryImpl registry = parse("/test-wiring.xml");
+      Repository repository = new TestBlueprintContainer(registry).getRepository();
+      
+      Object fiTestBean = repository.create("FITestBean");
+      assertNotNull(fiTestBean);
+      assertTrue(fiTestBean instanceof FITestBean);
+      
+      FITestBean bean = (FITestBean) fiTestBean;
+      // single field injection
+      assertEquals("value", bean.getAttr());
+      // prefer setter injection to field injection
+      assertEquals("IS_LOWER", bean.getUpperCaseAttr());
+      // support cascaded injection 'bean.name' via fields
+      assertEquals("aName", bean.getBeanName());
+      
+      // fail if field-injection is not specified
+      try {
+          repository.create("FIFailureTestBean");
+          Assert.fail("Expected exception");
+      } catch (ComponentDefinitionException cde) {}
+      
+      // fail if field-injection is false
+      try {
+          repository.create("FIFailureTest2Bean");
+          Assert.fail("Expected exception");
+      } catch (ComponentDefinitionException cde) {}
+    }
+    
+    public void testCompoundProperties() throws Exception {
+        ComponentDefinitionRegistryImpl registry = parse("/test-wiring.xml");
+        Repository repository = new TestBlueprintContainer(registry).getRepository();
+        
+        Object obj5 = repository.create("compound");
+        assertNotNull(obj5);
+        assertTrue(obj5 instanceof PojoB);
+        PojoB pojob = (PojoB) obj5;
+    
+        assertEquals("hello bean property", pojob.getBean().getName());
+
+        Object obj = repository.create("goodIdRef");
+        assertNotNull(obj);
+        assertTrue(obj instanceof BeanD);
+        BeanD bean = (BeanD) obj;
+
+        assertEquals("pojoA", bean.getName());
+    }
+
+    public void testIdRefs() throws Exception {
+        ComponentDefinitionRegistryImpl registry = parse("/test-bad-id-ref.xml");
+
+        try {
+            new TestBlueprintContainer(registry).getRepository();
+            fail("Did not throw exception");
+        } catch (RuntimeException e) {
+            // we expect exception
+            // TODO: check error string?
+        }
+    }
+    
+    public void testDependencies() throws Exception {
+        CallbackTracker.clear();
+
+        ComponentDefinitionRegistryImpl registry = parse("/test-depends-on.xml");
+        Repository repository = new TestBlueprintContainer(registry).getRepository();
+        Map instances = repository.createAll(Arrays.asList("c", "d", "e"));
+        
+        List<Callback> callback = CallbackTracker.getCallbacks();
+        assertEquals(3, callback.size());
+        checkInitCallback(instances.get("d"), callback.get(0));
+        checkInitCallback(instances.get("c"), callback.get(1));
+        checkInitCallback(instances.get("e"), callback.get(2));
+                
+        repository.destroy();
+        
+        assertEquals(6, callback.size());
+        checkDestroyCallback(instances.get("e"), callback.get(3));
+        checkDestroyCallback(instances.get("c"), callback.get(4));
+        checkDestroyCallback(instances.get("d"), callback.get(5));
+    }
+
+    private void checkInitCallback(Object obj, Callback callback) { 
+        assertEquals(Callback.INIT, callback.getType());
+        assertEquals(obj, callback.getObject());
+    }
+    
+    private void checkDestroyCallback(Object obj, Callback callback) { 
+        assertEquals(Callback.DESTROY, callback.getType());
+        assertEquals(obj, callback.getObject());
+    }
+    
+    public void testConstructor() throws Exception {
+        ComponentDefinitionRegistryImpl registry = parse("/test-constructor.xml");
+        Repository repository = new TestBlueprintContainer(registry).getRepository();
+
+        Object obj1 = repository.create("pojoA");
+        assertNotNull(obj1);
+        assertTrue(obj1 instanceof PojoA);
+        PojoA pojoa = (PojoA) obj1;
+        
+        Object obj2 = repository.create("pojoB");
+        testPojoB(obj2, URI.create("urn:myuri"), 10);
+        
+        assertEquals(obj2, pojoa.getPojob());
+        assertEquals(new BigInteger("10"), pojoa.getNumber());
+        
+        Object obj3 = repository.create("pojoC");
+        testPojoB(obj3, URI.create("urn:myuri-static"), 15);
+        
+        Object obj4 = repository.create("pojoD");
+        testPojoB(obj4, URI.create("urn:myuri-static"), 15);
+        
+        Object obj5 = repository.create("pojoE");
+        testPojoB(obj5, URI.create("urn:myuri-dynamic"), 20);
+        
+        Object obj6 = repository.create("multipleInt");
+        testMultiple(obj6, null, 123, null);
+        
+        Object obj7 = repository.create("multipleInteger");
+        testMultiple(obj7, null, -1, new Integer(123));
+        
+        Object obj8 = repository.create("multipleString");
+        testMultiple(obj8, "123", -1, null);
+
+        // TODO: check the below tests when the incoherence between TCK / spec is solved
+//        try {
+//            graph.create("multipleStringConvertable");
+//            fail("Did not throw exception");
+//        } catch (RuntimeException e) {
+//            // we expect exception
+//        }
+        
+        Object obj10 = repository.create("multipleFactory1");
+        testMultiple(obj10, null, 1234, null);
+
+        Object obj11 = repository.create("multipleFactory2");
+        testMultiple(obj11, "helloCreate-boolean", -1, null);        
+        
+        try {
+            repository.create("multipleFactoryNull");
+            fail("Did not throw exception");
+        } catch (RuntimeException e) {
+            // we expect exception 
+            // TODO: check the exception string?
+        }
+        
+        Object obj12 = repository.create("multipleFactoryTypedNull");
+        testMultiple(obj12, "hello-boolean", -1, null);
+
+        // TODO: check the below tests when the incoherence between TCK / spec is solved
+//        Object obj13 = graph.create("mapConstruction");
+//        Object obj14 = graph.create("propsConstruction");
+
+        BeanF obj15 = (BeanF) repository.create("booleanWrapped");
+        assertNotNull(obj15.getWrapped());
+        assertEquals(false, (boolean) obj15.getWrapped());
+        assertNull(obj15.getPrim());
+
+        // TODO: check the below tests when the incoherence between TCK / spec is solved
+//        BeanF obj16 = (BeanF) graph.create("booleanPrim");
+//        assertNotNull(obj16.getPrim());
+//        assertEquals(false, (boolean) obj16.getPrim());
+//        assertNull(obj16.getWrapped());
+    }
+    
+    private void testPojoB(Object obj, URI uri, int intValue) {
+        assertNotNull(obj);
+        assertTrue(obj instanceof PojoB);
+        PojoB pojob = (PojoB) obj;
+        assertEquals(uri, pojob.getUri());
+        assertEquals(intValue, pojob.getNumber());
+    }
+    
+    private void testMultiple(Object obj, String stringValue, int intValue, Integer integerValue) {
+        assertNotNull(obj);
+        assertTrue(obj instanceof Multiple);
+        assertEquals(intValue, ((Multiple)obj).getInt());
+        assertEquals(stringValue, ((Multiple)obj).getString());
+        assertEquals(integerValue, ((Multiple)obj).getInteger());        
+    }
+
+    public void testGenerics() throws Exception {
+        ComponentDefinitionRegistryImpl registry = parse("/test-generics.xml");
+        Repository repository = new TestBlueprintContainer(registry).getRepository();
+
+        List<Integer> expectedList = new ArrayList<Integer>();
+        expectedList.add(new Integer(10));
+        expectedList.add(new Integer(20));
+        expectedList.add(new Integer(50));
+        
+        Set<Long> expectedSet = new HashSet<Long>();
+        expectedSet.add(new Long(1000));
+        expectedSet.add(new Long(2000));
+        expectedSet.add(new Long(5000));
+        
+        Map<Short, Boolean> expectedMap = new HashMap<Short, Boolean>();
+        expectedMap.put(new Short((short)1), Boolean.TRUE);
+        expectedMap.put(new Short((short)2), Boolean.FALSE);
+        expectedMap.put(new Short((short)5), Boolean.TRUE);
+        
+        Object obj;
+        PojoGenerics pojo;
+        
+        obj = repository.create("method");
+        assertTrue(obj instanceof PojoGenerics);
+        pojo = (PojoGenerics) obj;
+        
+        assertEquals(expectedList, pojo.getList());
+        assertEquals(expectedSet, pojo.getSet());
+        assertEquals(expectedMap, pojo.getMap());
+        
+        obj = repository.create("constructorList");
+        assertTrue(obj instanceof PojoGenerics);
+        pojo = (PojoGenerics) obj;
+        
+        assertEquals(expectedList, pojo.getList());
+        
+        obj = repository.create("constructorSet");
+        assertTrue(obj instanceof PojoGenerics);
+        pojo = (PojoGenerics) obj;
+        
+        assertEquals(expectedSet, pojo.getSet());
+        
+        obj = repository.create("constructorMap");
+        assertTrue(obj instanceof PojoGenerics);
+        pojo = (PojoGenerics) obj;
+        
+        assertEquals(expectedMap, pojo.getMap());
+        
+        obj = repository.create("genericPojo");
+        assertTrue(obj instanceof Primavera);
+        assertEquals("string", ((Primavera) obj).prop);
+        
+        obj = repository.create("doubleGenericPojo");
+        assertTrue(obj instanceof Primavera);
+        assertEquals("stringToo", ((Primavera) obj).prop);
+    }
+    
+    public void testCircular() throws Exception {
+        BlueprintRepository repository = createBlueprintContainer().getRepository();
+
+        // this should pass (we allow circular dependencies for components without init method)
+        Object obj1 = repository.create("a");
+                
+        // test service and listener circular dependencies
+        Object obj2 = repository.create("service");
+        assertNotNull(obj2);
+        assertTrue(obj2 instanceof ServiceRegistration);
+        
+        Object obj3 = repository.create("listener");
+        assertNotNull(obj3);
+        assertTrue(obj3 instanceof PojoListener);
+        
+        assertEquals(obj2, ((PojoListener) obj3).getService() );        
+    }
+     
+    public void testCircularPrototype() throws Exception {
+        BlueprintRepository repository = createBlueprintContainer().getRepository();
+        
+        try {
+            repository.create("circularPrototypeDriver");
+            fail("Did not throw exception");  
+        } catch (CircularDependencyException e) {
+            // that's what we expect
+        }
+
+        try {
+            repository.create("circularPrototype");
+            fail("Did not throw exception");  
+        } catch (CircularDependencyException e) {
+            // that's what we expect
+        }
+    }
+    
+    public void testRecursive() throws Exception {
+        BlueprintRepository repository = createBlueprintContainer().getRepository();
+        
+        try {
+            repository.create("recursiveConstructor");
+            fail("Did not throw exception");           
+        } catch (ComponentDefinitionException e) {
+            if (e.getCause() instanceof CircularDependencyException) {                          
+                // that's what we expect
+            } else {
+                fail("Did not throw expected exception");
+                throw e;
+            }
+        }
+        
+        PojoRecursive pojo;
+        
+        pojo = (PojoRecursive) repository.create("recursiveSetter");
+        assertNotNull(pojo);
+                           
+        pojo = (PojoRecursive) repository.create("recursiveInitMethod");
+        assertNotNull(pojo);
+    }
+    
+    public void testCircularBreaking() throws Exception {
+        BlueprintRepository repository;
+        
+        repository = createBlueprintContainer().getRepository();        
+        assertNotNull(repository.create("c1"));
+        
+        repository = createBlueprintContainer().getRepository();        
+        assertNotNull(repository.create("c2"));
+        
+        repository = createBlueprintContainer().getRepository();        
+        assertNotNull(repository.create("c3"));
+    }
+    
+    private TestBlueprintContainer createBlueprintContainer() throws Exception {
+        ComponentDefinitionRegistryImpl registry = parse("/test-circular.xml");
+        return new TestBlueprintContainer(registry);
+    }
+    
+}