Return-Path: Delivered-To: apmail-aries-commits-archive@www.apache.org Received: (qmail 83546 invoked from network); 27 Feb 2011 21:06:46 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 27 Feb 2011 21:06:46 -0000 Received: (qmail 20683 invoked by uid 500); 27 Feb 2011 21:06:46 -0000 Delivered-To: apmail-aries-commits-archive@aries.apache.org Received: (qmail 20601 invoked by uid 500); 27 Feb 2011 21:06:46 -0000 Mailing-List: contact commits-help@aries.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@aries.apache.org Delivered-To: mailing list commits@aries.apache.org Received: (qmail 20531 invoked by uid 99); 27 Feb 2011 21:06:46 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 27 Feb 2011 21:06:46 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 27 Feb 2011 21:06:41 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 3CC712388C5D; Sun, 27 Feb 2011 21:05:25 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1075147 [18/23] - in /aries/tags/blueprint-0.3: ./ 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-ann... Date: Sun, 27 Feb 2011 21:05:20 -0000 To: commits@aries.apache.org From: zoe@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110227210525.3CC712388C5D@eris.apache.org> Added: aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/utils/ReflectionUtils.java URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/utils/ReflectionUtils.java?rev=1075147&view=auto ============================================================================== --- aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/utils/ReflectionUtils.java (added) +++ aries/tags/blueprint-0.3/blueprint-core/src/main/java/org/apache/aries/blueprint/utils/ReflectionUtils.java Sun Feb 27 21:05:07 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, PropertyDescriptor[][]> beanInfos = Collections.synchronizedMap(new WeakHashMap, 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 getImplementedInterfaces(Set 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 getSuperClasses(Set 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 findCompatibleMethods(Class clazz, String name, Class[] paramTypes) { + List methods = new ArrayList(); + 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 propertyNames = new HashSet(); + Map getters = new HashMap(); + Map> setters = new HashMap>(); + Set illegalProperties = new HashSet(); + + 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()); + 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 props = new HashMap(); + 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 result = new ArrayList(); + 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() { + 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() { + 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() { + 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() { + 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() { + 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() { + 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() { + 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() { + 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 setters; + + private MethodPropertyDescriptor(String name, Method getter, Collection setters) { + super(name); + this.getter = getter; + this.setters = (setters != null) ? setters : Collections.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 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 matchingMethods = new ArrayList(); + 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 + + + + + + + + + + + Added: aries/tags/blueprint-0.3/blueprint-core/src/main/resources/OSGI-INF/permissions.perm URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/resources/OSGI-INF/permissions.perm?rev=1075147&view=auto ============================================================================== --- aries/tags/blueprint-0.3/blueprint-core/src/main/resources/OSGI-INF/permissions.perm (added) +++ aries/tags/blueprint-0.3/blueprint-core/src/main/resources/OSGI-INF/permissions.perm Sun Feb 27 21:05:07 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/blueprint-core/src/main/resources/org/apache/aries/blueprint/ext/blueprint-ext.xsd URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/resources/org/apache/aries/blueprint/ext/blueprint-ext.xsd?rev=1075147&view=auto ============================================================================== --- aries/tags/blueprint-0.3/blueprint-core/src/main/resources/org/apache/aries/blueprint/ext/blueprint-ext.xsd (added) +++ aries/tags/blueprint-0.3/blueprint-core/src/main/resources/org/apache/aries/blueprint/ext/blueprint-ext.xsd Sun Feb 27 21:05:07 2011 @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Added: aries/tags/blueprint-0.3/blueprint-core/src/main/resources/org/apache/aries/blueprint/nls/BlueprintMessages.properties URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/main/resources/org/apache/aries/blueprint/nls/BlueprintMessages.properties?rev=1075147&view=auto ============================================================================== --- aries/tags/blueprint-0.3/blueprint-core/src/main/resources/org/apache/aries/blueprint/nls/BlueprintMessages.properties (added) +++ aries/tags/blueprint-0.3/blueprint-core/src/main/resources/org/apache/aries/blueprint/nls/BlueprintMessages.properties Sun Feb 27 21:05:07 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/blueprint-core/src/test/java/org/apache/aries/blueprint/AbstractBlueprintTest.java URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/test/java/org/apache/aries/blueprint/AbstractBlueprintTest.java?rev=1075147&view=auto ============================================================================== --- aries/tags/blueprint-0.3/blueprint-core/src/test/java/org/apache/aries/blueprint/AbstractBlueprintTest.java (added) +++ aries/tags/blueprint-0.3/blueprint-core/src/test/java/org/apache/aries/blueprint/AbstractBlueprintTest.java Sun Feb 27 21:05:07 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 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/blueprint-core/src/test/java/org/apache/aries/blueprint/CallbackTracker.java URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/test/java/org/apache/aries/blueprint/CallbackTracker.java?rev=1075147&view=auto ============================================================================== --- aries/tags/blueprint-0.3/blueprint-core/src/test/java/org/apache/aries/blueprint/CallbackTracker.java (added) +++ aries/tags/blueprint-0.3/blueprint-core/src/test/java/org/apache/aries/blueprint/CallbackTracker.java Sun Feb 27 21:05:07 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 callbacks = new ArrayList(); + + public static void add(Callback callback) { + callbacks.add(callback); + } + + public static List 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/blueprint-core/src/test/java/org/apache/aries/blueprint/ParserTest.java URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/test/java/org/apache/aries/blueprint/ParserTest.java?rev=1075147&view=auto ============================================================================== --- aries/tags/blueprint-0.3/blueprint-core/src/test/java/org/apache/aries/blueprint/ParserTest.java (added) +++ aries/tags/blueprint-0.3/blueprint-core/src/test/java/org/apache/aries/blueprint/ParserTest.java Sun Feb 27 21:05:07 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 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 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 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 getManagedClasses() { + return new HashSet(); + } + + 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/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBlueprintContainer.java URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBlueprintContainer.java?rev=1075147&view=auto ============================================================================== --- aries/tags/blueprint-0.3/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBlueprintContainer.java (added) +++ aries/tags/blueprint-0.3/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBlueprintContainer.java Sun Feb 27 21:05:07 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/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBundleContext.java URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBundleContext.java?rev=1075147&view=auto ============================================================================== --- aries/tags/blueprint-0.3/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBundleContext.java (added) +++ aries/tags/blueprint-0.3/blueprint-core/src/test/java/org/apache/aries/blueprint/TestBundleContext.java Sun Feb 27 21:05:07 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/blueprint-core/src/test/java/org/apache/aries/blueprint/WiringTest.java URL: http://svn.apache.org/viewvc/aries/tags/blueprint-0.3/blueprint-core/src/test/java/org/apache/aries/blueprint/WiringTest.java?rev=1075147&view=auto ============================================================================== --- aries/tags/blueprint-0.3/blueprint-core/src/test/java/org/apache/aries/blueprint/WiringTest.java (added) +++ aries/tags/blueprint-0.3/blueprint-core/src/test/java/org/apache/aries/blueprint/WiringTest.java Sun Feb 27 21:05:07 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 = 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 expectedList = new ArrayList(); + expectedList.add(new Integer(10)); + expectedList.add(new Integer(20)); + expectedList.add(new Integer(50)); + + Set expectedSet = new HashSet(); + expectedSet.add(new Long(1000)); + expectedSet.add(new Long(2000)); + expectedSet.add(new Long(5000)); + + Map expectedMap = new HashMap(); + 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); + } + +}