diff options
Diffstat (limited to 'branches/sca-java-1.x/modules/implementation-spring')
8 files changed, 924 insertions, 185 deletions
diff --git a/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementation.java b/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementation.java index 165dfae8be..6f22567070 100644 --- a/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementation.java +++ b/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementation.java @@ -18,9 +18,7 @@ */ package org.apache.tuscany.sca.implementation.spring; -import java.lang.reflect.Method; import java.util.Hashtable; -import java.util.Enumeration; import java.util.List; import org.apache.tuscany.sca.assembly.Component; @@ -33,7 +31,6 @@ import org.apache.tuscany.sca.assembly.Service; import org.apache.tuscany.sca.assembly.impl.ImplementationImpl; import org.apache.tuscany.sca.interfacedef.InterfaceContract; import org.apache.tuscany.sca.assembly.builder.ComponentPreProcessor; -import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl; import org.apache.tuscany.sca.implementation.spring.xml.SpringBeanElement; import org.apache.tuscany.sca.policy.util.PolicyHandlerTuple; import org.apache.tuscany.sca.runtime.RuntimeComponent; @@ -58,13 +55,6 @@ public class SpringImplementation extends ImplementationImpl implements Implemen private List<PolicyHandlerTuple> policyHandlerClassNames = null; // List of unresolved bean property references private Hashtable<String, Reference> unresolvedBeanRef; - - // Method marked with @Init annotation - private Method initMethod = null; - // Method marked with @Destroy annotation - private Method destroyMethod = null; - // Method marked with @Constructor annotation - private JavaConstructorImpl<?> constructorDefinition = null; protected SpringImplementation() { this.location = null; @@ -96,30 +86,6 @@ public class SpringImplementation extends ImplementationImpl implements Implemen public Resource getResource() { return resource; } - - public JavaConstructorImpl<?> getConstructor() { - return constructorDefinition; - } - - public void setConstructor(JavaConstructorImpl<?> definition) { - this.constructorDefinition = definition; - } - - public Method getInitMethod() { - return initMethod; - } - - public void setInitMethod(Method initMethod) { - this.initMethod = initMethod; - } - - public Method getDestroyMethod() { - return destroyMethod; - } - - public void setDestroyMethod(Method destroyMethod) { - this.destroyMethod = destroyMethod; - } /* * Returns the componentType for this Spring implementation @@ -219,16 +185,6 @@ public class SpringImplementation extends ImplementationImpl implements Implemen RuntimeComponent rtc = (RuntimeComponent) component; - // Check if the SCDL is properly configured for all the services - // exposed by Spring application context, otherwise report a error - /*Enumeration<SpringBeanElement> itr = serviceMap.elements(); - while (itr.hasMoreElements()) { - SpringBeanElement beanElement = itr.nextElement(); - if (!rtc.getServices().contains(beanElement.getId())) { - throw new AssertionError("Configuration Error:"); - } - }*/ - for (Reference reference : rtc.getReferences()) { if (unresolvedBeanRef.containsKey(reference.getName())) { Reference ref = unresolvedBeanRef.get(reference.getName()); @@ -244,23 +200,7 @@ public class SpringImplementation extends ImplementationImpl implements Implemen this.setPropertyClass(property.getName(), property.getClass()); unresolvedBeanRef.remove(property.getName()); } - } - - // Check if the SCDL is properly configured for all the SCA references - // used in the Spring application context, otherwise report a error - /*for (Reference reference: componentType.getReferences()) { - if (!rtc.getReferences().contains(reference.getName())) { - throw new AssertionError("Configuration Error:"); - } - }*/ - - // Check if the SCDL is properly configured for all the SCA property - // used in the Spring application context, otherwise report a error - /*for (Property property: componentType.getProperties()) { - if (!rtc.getProperties().contains(property.getName())) { - throw new AssertionError("Configuration Error:"); - } - }*/ + } } protected Reference createReference(Reference reference, InterfaceContract interfaze) { diff --git a/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationProvider.java b/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationProvider.java index 4717df2056..88358732ed 100644 --- a/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationProvider.java +++ b/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationProvider.java @@ -16,10 +16,10 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.tuscany.sca.implementation.spring; import java.util.List; +import java.util.Iterator; import org.apache.tuscany.sca.core.invocation.ProxyFactory; import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory; @@ -30,16 +30,22 @@ import org.apache.tuscany.sca.provider.ImplementationProvider; import org.apache.tuscany.sca.runtime.RuntimeComponent; import org.apache.tuscany.sca.runtime.RuntimeComponentService; import org.springframework.beans.factory.xml.XmlBeanFactory; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.GenericApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.context.support.FileSystemXmlApplicationContext; import org.apache.tuscany.sca.implementation.spring.processor.InitDestroyAnnotationProcessor; import org.apache.tuscany.sca.implementation.spring.processor.ReferenceAnnotationProcessor; import org.apache.tuscany.sca.implementation.spring.processor.PropertyAnnotationProcessor; import org.apache.tuscany.sca.implementation.spring.processor.ConstructorAnnotationProcessor; import org.apache.tuscany.sca.implementation.spring.processor.ComponentNameAnnotationProcessor; import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.ConstructorArgumentValues; +import org.springframework.beans.factory.config.TypedStringValue; +import org.springframework.beans.factory.support.ManagedList; -// TODO - create a working version of this class... /** * A provider class for runtime Spring implementation instances * @version $Rev: 511195 $ $Date: 2007-02-24 02:29:46 +0000 (Sat, 24 Feb 2007) $ @@ -51,6 +57,8 @@ public class SpringImplementationProvider implements ImplementationProvider { private AbstractApplicationContext springContext; private SpringImplementation implementation; + + private JavaPropertyValueObjectFactory propertyValueObjectFactory; /** * Constructor for the provider - takes a component definition and a Spring implementation @@ -66,24 +74,15 @@ public class SpringImplementationProvider implements ImplementationProvider { super(); this.implementation = implementation; this.component = component; + this.propertyValueObjectFactory = propertyValueObjectFactory; this.implementation.setPolicyHandlerClassNames(policyHandlerClassNames); SCAParentApplicationContext scaParentContext = new SCAParentApplicationContext(component, implementation, proxyService, propertyValueObjectFactory); - //springContext = new SCAApplicationContext(scaParentContext, implementation.getResource()); + //springContext = new SCAApplicationContext(scaParentContext, implementation.getResource()); XmlBeanFactory beanFactory = new XmlBeanFactory(implementation.getResource()); - BeanPostProcessor initDestroyProcessor = new InitDestroyAnnotationProcessor(); - beanFactory.addBeanPostProcessor(initDestroyProcessor); - BeanPostProcessor referenceProcessor = new ReferenceAnnotationProcessor(component); - beanFactory.addBeanPostProcessor(referenceProcessor); - BeanPostProcessor propertyProcessor = new PropertyAnnotationProcessor(propertyValueObjectFactory, component); - beanFactory.addBeanPostProcessor(propertyProcessor); - BeanPostProcessor componentNameProcessor = new ComponentNameAnnotationProcessor(component); - beanFactory.addBeanPostProcessor(componentNameProcessor); - BeanPostProcessor constructorProcessor = new ConstructorAnnotationProcessor(); - beanFactory.addBeanPostProcessor(constructorProcessor); - springContext = new GenericApplicationContext(beanFactory, scaParentContext); + springContext = createApplicationContext(beanFactory, scaParentContext); } // end constructor @@ -110,10 +109,93 @@ public class SpringImplementationProvider implements ImplementationProvider { * Stop this implementation instance */ public void stop() { - // TODO - complete - springContext.close(); - springContext.stop(); + // TODO - complete + springContext.close(); + if (springContext instanceof GenericApplicationContext) + springContext.stop(); //System.out.println("SpringImplementationProvider: Spring context stopped"); } // end method stop - + + + /** + * Include BeanPostProcessor to deal with SCA Annotations in Spring Bean + */ + private void includeAnnotationProcessors(ConfigurableListableBeanFactory beanFactory) { + + // Processor to deal with @Init and @Destroy SCA Annotations + BeanPostProcessor initDestroyProcessor = new InitDestroyAnnotationProcessor(); + beanFactory.addBeanPostProcessor(initDestroyProcessor); + + // Processor to deal with @Reference SCA Annotations + BeanPostProcessor referenceProcessor = new ReferenceAnnotationProcessor(component); + beanFactory.addBeanPostProcessor(referenceProcessor); + + // Processor to deal with @Property SCA Annotations + BeanPostProcessor propertyProcessor = new PropertyAnnotationProcessor(propertyValueObjectFactory, component); + beanFactory.addBeanPostProcessor(propertyProcessor); + + // Processor to deal with @ComponentName SCA Annotations + BeanPostProcessor componentNameProcessor = new ComponentNameAnnotationProcessor(component); + beanFactory.addBeanPostProcessor(componentNameProcessor); + + // Processor to deal with @Constructor SCA Annotations + BeanPostProcessor constructorProcessor = new ConstructorAnnotationProcessor(); + beanFactory.addBeanPostProcessor(constructorProcessor); + } + + + /** + * Include BeanPostProcessor to deal with SCA Annotations in Spring Bean + */ + private AbstractApplicationContext createApplicationContext(XmlBeanFactory beanFactory, + SCAParentApplicationContext scaParentContext) { + AbstractApplicationContext appContext = null; + + for (String bean : beanFactory.getBeanDefinitionNames()) { + String beanClassName = (beanFactory.getType(bean)).getName(); + if (beanClassName.indexOf(".ClassPathXmlApplicationContext") != -1 || + beanClassName.indexOf(".FileSystemXmlApplicationContext") != -1) + { + BeanDefinition beanDef = beanFactory.getBeanDefinition(bean); + String[] listValues = null; + List<ConstructorArgumentValues.ValueHolder> conArgs = + beanDef.getConstructorArgumentValues().getGenericArgumentValues(); + for (ConstructorArgumentValues.ValueHolder conArg : conArgs) { + if (conArg.getValue() instanceof TypedStringValue) { + TypedStringValue value = (TypedStringValue) conArg.getValue(); + if (value.getValue().indexOf(".xml") != -1) + listValues = new String[]{value.getValue()}; + } + if (conArg.getValue() instanceof ManagedList) { + Iterator itml = ((ManagedList)conArg.getValue()).iterator(); + StringBuffer values = new StringBuffer(); + while (itml.hasNext()) { + TypedStringValue next = (TypedStringValue)itml.next(); + if (next.getValue().indexOf(".xml") != -1) { + values.append(next.getValue()); + values.append("~"); + } + } + listValues = (values.toString()).split("~"); + } + } + + if (beanClassName.indexOf(".ClassPathXmlApplicationContext") != -1) { + appContext = new ClassPathXmlApplicationContext(listValues, false, scaParentContext); + //includeAnnotationProcessors(appContext.getBeanFactory()); + return appContext; + } else { + appContext = new FileSystemXmlApplicationContext(listValues, false, scaParentContext); + //includeAnnotationProcessors(appContext.getBeanFactory()); + return appContext; + } + } + } + + // use the generic application context as default + includeAnnotationProcessors(beanFactory); + appContext = new GenericApplicationContext(beanFactory, scaParentContext); + return appContext; + } + } // end class SpringImplementationProvider diff --git a/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanElement.java b/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanElement.java index f9a9fee58f..629a72e22d 100644 --- a/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanElement.java +++ b/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanElement.java @@ -32,6 +32,7 @@ public class SpringBeanElement { private String id; private String className; + private boolean innerBean = false; private List<SpringPropertyElement> properties = new ArrayList<SpringPropertyElement>(); private List<SpringConstructorArgElement> constructorargs = new ArrayList<SpringConstructorArgElement>(); @@ -63,5 +64,13 @@ public class SpringBeanElement { public void addCustructorArgs(SpringConstructorArgElement args) { constructorargs.add(args); } + + public boolean isInnerBean() { + return innerBean; + } + + public void setInnerBean(boolean innerBean) { + this.innerBean = innerBean; + } } // end class SpringBeanElement diff --git a/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanIntrospector.java b/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanIntrospector.java index 3e526cd20e..df85e4f302 100644 --- a/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanIntrospector.java +++ b/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanIntrospector.java @@ -18,8 +18,6 @@ */ package org.apache.tuscany.sca.implementation.spring.xml; -import java.util.Map; - import org.apache.tuscany.sca.assembly.AssemblyFactory; import org.apache.tuscany.sca.assembly.ComponentType; import org.apache.tuscany.sca.contribution.service.ContributionResolveException; @@ -27,7 +25,6 @@ import org.apache.tuscany.sca.implementation.java.DefaultJavaImplementationFacto import org.apache.tuscany.sca.implementation.java.IntrospectionException; import org.apache.tuscany.sca.implementation.java.JavaImplementation; import org.apache.tuscany.sca.implementation.java.JavaImplementationFactory; -import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; import org.apache.tuscany.sca.implementation.java.introspect.JavaClassVisitor; import org.apache.tuscany.sca.implementation.java.introspect.impl.AllowsPassByReferenceProcessor; import org.apache.tuscany.sca.implementation.java.introspect.impl.BaseJavaClassVisitor; @@ -47,7 +44,6 @@ import org.apache.tuscany.sca.implementation.java.introspect.impl.ScopeProcessor import org.apache.tuscany.sca.implementation.java.introspect.impl.ServiceProcessor; import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; import org.apache.tuscany.sca.policy.PolicyFactory; -import org.apache.tuscany.sca.implementation.spring.SpringImplementation; /** * Provides introspection functions for Spring beans @@ -89,7 +85,7 @@ public class SpringBeanIntrospector { new ResourceProcessor(assemblyFactory), new ScopeProcessor(assemblyFactory), new ServiceProcessor(assemblyFactory, javaFactory), - new HeuristicPojoProcessor(assemblyFactory, javaFactory), + new SpringBeanPojoProcessor(assemblyFactory, javaFactory), new PolicyProcessor(assemblyFactory, policyFactory)}; for (JavaClassVisitor extension : extensions) { javaImplementationFactory.addClassVisitor(extension); @@ -107,8 +103,7 @@ public class SpringBeanIntrospector { * Spring Bean or its componentType * */ - public Map<String, JavaElementImpl> introspectBean(Class<?> beanClass, ComponentType componentType, - SpringImplementation springImplementation) throws ContributionResolveException + public JavaImplementation introspectBean(Class<?> beanClass, ComponentType componentType) throws ContributionResolveException { if (componentType == null) throw new ContributionResolveException("Introspect Spring bean: supplied componentType is null"); @@ -126,21 +121,17 @@ public class SpringBeanIntrospector { componentType.getReferences().addAll(javaImplementation.getReferences()); componentType.getProperties().addAll(javaImplementation.getProperties()); - springImplementation.setInitMethod(javaImplementation.getInitMethod()); - springImplementation.setDestroyMethod(javaImplementation.getDestroyMethod()); - springImplementation.setConstructor(javaImplementation.getConstructor()); - } catch (IntrospectionException e) { throw new ContributionResolveException(e); } // end try - //List<Service> services = javaImplementation.getServices(); - //for (Service service : services) { - //String name = service.getName(); - //System.out.println("Spring Bean: found service with name: " + name); - //} // end for - - return javaImplementation.getPropertyMembers(); + /* List<Service> services = javaImplementation.getServices(); + for (Service service : services) { + String name = service.getName(); + System.out.println("Spring Bean: found service with name: " + name); + } // end for */ + + return javaImplementation; } // end method introspectBean diff --git a/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanPojoProcessor.java b/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanPojoProcessor.java new file mode 100644 index 0000000000..0510a6d338 --- /dev/null +++ b/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanPojoProcessor.java @@ -0,0 +1,648 @@ +/*
+ * 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.tuscany.sca.implementation.spring.xml;
+
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.getAllInterfaces;
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.getPrivateFields;
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.getAllPublicAndProtectedFields;
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.getAllUniquePublicProtectedMethods;
+import static org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper.toPropertyName;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.jws.WebService;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Contract;
+import org.apache.tuscany.sca.assembly.Multiplicity;
+import org.apache.tuscany.sca.implementation.java.IntrospectionException;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl;
+import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl;
+import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl;
+import org.apache.tuscany.sca.interfacedef.Interface;
+import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
+import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper;
+import org.osoa.sca.annotations.Callback;
+import org.osoa.sca.annotations.Context;
+import org.osoa.sca.annotations.Property;
+import org.osoa.sca.annotations.Reference;
+import org.osoa.sca.annotations.Remotable;
+
+import org.apache.tuscany.sca.implementation.java.introspect.impl.BaseJavaClassVisitor;
+import org.apache.tuscany.sca.implementation.java.introspect.impl.NoConstructorException;
+import org.apache.tuscany.sca.implementation.java.introspect.impl.AmbiguousConstructorException;
+import org.apache.tuscany.sca.implementation.java.introspect.impl.JavaIntrospectionHelper;
+import org.apache.tuscany.sca.implementation.java.introspect.impl.InvalidServiceType;
+import org.apache.tuscany.sca.implementation.java.introspect.impl.Resource;
+
+/**
+ * Heuristically evaluates an un-annotated Java implementation type to determine
+ * services, references, and properties according to the algorithm described in
+ * the SCA Java Client and Implementation Model Specification <p/> TODO
+ * Implement: <p/> When no service interface is annotated, need to calculate a
+ * single service comprising all public methods that are not reference or
+ * property injection sites. If that service can be exactly mapped to an
+ * interface implemented by the class then the service interface will be defined
+ * in terms of that interface.
+ *
+ * @version $Rev: 689426 $ $Date: 2008-08-27 14:56:06 +0530 (Wed, 27 Aug 2008) $
+ */
+public class SpringBeanPojoProcessor extends BaseJavaClassVisitor {
+ private JavaInterfaceFactory javaFactory;
+
+ public SpringBeanPojoProcessor(AssemblyFactory assemblyFactory, JavaInterfaceFactory javaFactory) {
+ super(assemblyFactory);
+ this.javaFactory = javaFactory;
+ }
+
+ @Override
+ public <T> void visitEnd(Class<T> clazz, JavaImplementation type) throws IntrospectionException {
+ List<org.apache.tuscany.sca.assembly.Service> services = type.getServices();
+ if (services.isEmpty()) {
+ // heuristically determine the service
+ /**
+ * The following is quoted from Java Specification 1.2.1.3. Introspecting services offered by a Java implementation
+ * In the cases described below, the services offered by a Java implementation class may be determined
+ * through introspection, eliding the need to specify them using @Service. The following algorithm is used
+ * to determine how services are introspected from an implementation class:
+ *
+ * If the interfaces of the SCA services are not specified with the @Service annotation on the
+ * implementation class, it is assumed that all implemented interfaces that have been annotated
+ * as @Remotable are the service interfaces provided by the component. If none of the implemented
+ * interfaces is remotable, then by default the implementation offers a single service whose type
+ * is the implementation class.
+ */
+ Set<Class> interfaces = getAllInterfaces(clazz);
+ for (Class<?> i : interfaces) {
+ if (i.isAnnotationPresent(Remotable.class) || i.isAnnotationPresent(WebService.class)) {
+ addService(type, i);
+ }
+ }
+ if (services.isEmpty()) {
+ // class is the interface
+ addService(type, clazz);
+ }
+ }
+ Set<Method> methods = getAllUniquePublicProtectedMethods(clazz, false);
+ if (!type.getReferenceMembers().isEmpty() || !type.getPropertyMembers().isEmpty()) {
+ // references and properties have been explicitly defined
+ // if (type.getServices().isEmpty()) {
+ // calculateServiceInterface(clazz, type, methods);
+ // if (type.getServices().isEmpty()) {
+ // throw new ServiceTypeNotFoundException(clazz.getName());
+ // }
+ // }
+ evaluateConstructor(type, clazz);
+ return;
+ }
+ calcPropRefs(methods, services, type, clazz);
+ evaluateConstructor(type, clazz);
+ }
+
+ private void addService(JavaImplementation type, Class<?> clazz) throws IntrospectionException {
+ try {
+ org.apache.tuscany.sca.assembly.Service service = createService(clazz);
+ type.getServices().add(service);
+ } catch (InvalidInterfaceException e) {
+ throw new IntrospectionException(e);
+ }
+ }
+
+ private boolean isPublicSetter(Method method) {
+ return method.getParameterTypes().length == 1 && Modifier.isPublic(method.getModifiers())
+ && method.getName().startsWith("set")
+ && method.getReturnType() == void.class;
+ }
+
+ private boolean isProtectedSetter(Method method) {
+ return method.getParameterTypes().length == 1 && Modifier.isProtected(method.getModifiers())
+ && method.getName().startsWith("set")
+ && method.getReturnType() == void.class;
+ }
+
+ private <T> void calcPropRefs(Set<Method> methods,
+ List<org.apache.tuscany.sca.assembly.Service> services,
+ JavaImplementation type,
+ Class<T> clazz) throws IntrospectionException {
+ // heuristically determine the properties references
+ // make a first pass through all public methods with one param
+ Set<String> setters = new HashSet<String>();
+ Set<String> others = new HashSet<String>();
+ for (Method method : methods) {
+ if (!isPublicSetter(method)) {
+ continue;
+ }
+ if (method.isAnnotationPresent(Callback.class) || method.isAnnotationPresent(Context.class)) {
+ // Add the property name as others
+ others.add(toPropertyName(method.getName()));
+ continue;
+ }
+ if (!isInServiceInterface(method, services)) {
+ // Not part of the service interface
+ String name = toPropertyName(method.getName());
+ setters.add(name);
+ // avoid duplicate property or ref names
+ if (!type.getPropertyMembers().containsKey(name) && !type.getReferenceMembers().containsKey(name)) {
+ Class<?> param = method.getParameterTypes()[0];
+ Type genericType = method.getGenericParameterTypes()[0];
+ if (isReferenceType(param, genericType)) {
+ type.getReferences().add(createReference(name, param));
+ type.getReferenceMembers().put(name, new JavaElementImpl(method, 0));
+ } else {
+ type.getProperties().add(createProperty(name, param));
+ type.getPropertyMembers().put(name, new JavaElementImpl(method, 0));
+ }
+ }
+ }
+ }
+ // second pass for protected methods with one param
+ for (Method method : methods) {
+ if (!isProtectedSetter(method)) {
+ continue;
+ }
+ if (method.isAnnotationPresent(Callback.class) || method.isAnnotationPresent(Context.class)) {
+ // Add the property name as others
+ others.add(toPropertyName(method.getName()));
+ continue;
+ }
+ Class<?> param = method.getParameterTypes()[0];
+ String name = toPropertyName(method.getName());
+ setters.add(name);
+ // avoid duplicate property or ref names
+ if (isReferenceType(param, method.getGenericParameterTypes()[0])) {
+ if (!type.getReferenceMembers().containsKey(name)) {
+ type.getReferences().add(createReference(name, param));
+ type.getReferenceMembers().put(name, new JavaElementImpl(method, 0));
+ }
+ } else {
+ if (!type.getPropertyMembers().containsKey(name)) {
+ type.getProperties().add(createProperty(name, param));
+ type.getPropertyMembers().put(name, new JavaElementImpl(method, 0));
+ }
+ }
+ }
+
+ // Public or protected fields unless there is a public or protected
+ // setter method
+ // for the same name
+ Set<Field> fields = getAllPublicAndProtectedFields(clazz, false);
+ for (Field field : fields) {
+ if (field.isAnnotationPresent(Callback.class) || field.isAnnotationPresent(Context.class)) {
+ continue;
+ }
+ if (setters.contains(field.getName()) || others.contains(field.getName())) {
+ continue;
+ }
+ String name = field.getName();
+ Class<?> paramType = field.getType();
+ if (isReferenceType(paramType, field.getGenericType())) {
+ if (!type.getReferenceMembers().containsKey(name)) {
+ type.getReferences().add(createReference(name, paramType));
+ type.getReferenceMembers().put(name, new JavaElementImpl(field));
+ }
+ } else {
+ if (!type.getPropertyMembers().containsKey(name)) {
+ type.getProperties().add(createProperty(name, paramType));
+ type.getPropertyMembers().put(name, new JavaElementImpl(field));
+ }
+ }
+ }
+
+ // Private fields unless there is a public or protected
+ // setter method for the same name
+ Set<Field> privateFields = getPrivateFields(clazz);
+ for (Field field : privateFields) {
+ if (field.isAnnotationPresent(Callback.class) || field.isAnnotationPresent(Context.class)) {
+ continue;
+ }
+ if (setters.contains(field.getName()) || others.contains(field.getName())) {
+ continue;
+ }
+ String name = field.getName();
+ Class<?> paramType = field.getType();
+ if (isReferenceType(paramType, field.getGenericType())) {
+ if (!type.getReferenceMembers().containsKey(name)) {
+ type.getReferences().add(createReference(name, paramType));
+ type.getReferenceMembers().put(name, new JavaElementImpl(field));
+ }
+ } else {
+ if (!type.getPropertyMembers().containsKey(name)) {
+ type.getProperties().add(createProperty(name, paramType));
+ type.getPropertyMembers().put(name, new JavaElementImpl(field));
+ }
+ }
+ }
+ }
+
+ /**
+ * Determines the constructor to use based on the component type's
+ * references and properties
+ *
+ * @param type the component type
+ * @param clazz the implementation class corresponding to the component type
+ * @throws NoConstructorException if no suitable constructor is found
+ * @throws AmbiguousConstructorException if the parameters of a constructor
+ * cannot be unambiguously mapped to references and properties
+ */
+ @SuppressWarnings("unchecked")
+ private <T> void evaluateConstructor(JavaImplementation type, Class<T> clazz) throws IntrospectionException {
+ // determine constructor if one is not annotated
+ JavaConstructorImpl<?> definition = type.getConstructor();
+ Constructor constructor;
+ boolean explict = false;
+ if (definition != null && definition.getConstructor()
+ .isAnnotationPresent(org.osoa.sca.annotations.Constructor.class)) {
+ // the constructor was already defined explicitly
+ return;
+ } else if (definition != null) {
+ explict = true;
+ constructor = definition.getConstructor();
+ } else {
+ // no definition, heuristically determine constructor
+ Constructor[] constructors = clazz.getConstructors();
+ if (constructors.length == 0) {
+ throw new NoConstructorException("No public constructor for class");
+ } else if (constructors.length == 1) {
+ // Only one constructor, take it
+ constructor = constructors[0];
+ } else {
+ // FIXME multiple constructors, none yet done
+ Constructor<T> selected = null;
+ int sites = type.getPropertyMembers().size() + type.getReferenceMembers().size();
+ for (Constructor<T> ctor : constructors) {
+ if (ctor.getParameterTypes().length == 0) {
+ selected = ctor;
+ }
+ if (ctor.getParameterTypes().length == sites) {
+ // TODO finish
+ // selected = constructor;
+ // select constructor
+ // break;
+ }
+ }
+ if (selected == null) {
+ throw new NoConstructorException();
+ }
+ constructor = selected;
+ definition = type.getConstructors().get(selected);
+ type.setConstructor(definition);
+ // return;
+ }
+ definition = type.getConstructors().get(constructor);
+ type.setConstructor(definition);
+ }
+ JavaParameterImpl[] parameters = definition.getParameters();
+ if (parameters.length == 0) {
+ return;
+ }
+ Map<String, JavaElementImpl> props = type.getPropertyMembers();
+ Map<String, JavaElementImpl> refs = type.getReferenceMembers();
+ Annotation[][] annotations = constructor.getParameterAnnotations();
+ if (!explict) {
+ // the constructor wasn't defined by an annotation, so check to see
+ // if any of the params have an annotation
+ // which we can impute as explicitly defining the constructor, e.g.
+ // @Property, @Reference, or @Autowire
+ explict = injectionAnnotationsPresent(annotations);
+ }
+ if (explict) {
+ for (int i = 0; i < parameters.length; i++) {
+ if (isAnnotated(parameters[i])) {
+ continue;
+ } else if (!findReferenceOrProperty(parameters[i], props, refs)) {
+ throw new AmbiguousConstructorException(parameters[i].toString());
+ }
+ }
+ } else {
+ if (!areUnique(parameters)) {
+ throw new AmbiguousConstructorException("Cannot resolve non-unique parameter types, use @Constructor");
+ }
+ if (!calcPropRefUniqueness(props.values(), refs.values())) {
+ throw new AmbiguousConstructorException("Cannot resolve non-unique parameter types, use @Constructor");
+ }
+ if (!(props.isEmpty() && refs.isEmpty())) {
+ calcParamNames(parameters, props, refs);
+ } else {
+ heuristicParamNames(type, parameters);
+
+ }
+ }
+ }
+
+ private void calcParamNames(JavaParameterImpl[] parameters,
+ Map<String, JavaElementImpl> props,
+ Map<String, JavaElementImpl> refs) throws AmbiguousConstructorException {
+ // the constructor param types must unambiguously match defined
+ // reference or property types
+ for (JavaParameterImpl param : parameters) {
+ if (!findReferenceOrProperty(param, props, refs)) {
+ throw new AmbiguousConstructorException(param.getName());
+ }
+ }
+ }
+
+ private void heuristicParamNames(JavaImplementation type, JavaParameterImpl[] parameters)
+ throws IntrospectionException {
+ // heuristically determine refs and props from the parameter types
+ for (JavaParameterImpl p : parameters) {
+ String name = p.getType().getSimpleName().toLowerCase();
+ if (isReferenceType(p.getType(), p.getGenericType())) {
+ type.getReferences().add(createReference(name, p.getType()));
+ p.setClassifer(Reference.class);
+ type.getReferenceMembers().put(name, p);
+ } else {
+ type.getProperties().add(createProperty(name, p.getType()));
+ p.setClassifer(Property.class);
+ type.getPropertyMembers().put(name, p);
+ }
+ p.setName(name);
+ }
+ }
+
+ private static boolean areUnique(Class[] collection) {
+ Set<Class> set = new HashSet<Class>(Arrays.asList(collection));
+ return set.size() == collection.length;
+ }
+
+ /**
+ * Returns true if the union of the given collections of properties and
+ * references have unique Java types
+ */
+ private boolean calcPropRefUniqueness(Collection<JavaElementImpl> props, Collection<JavaElementImpl> refs) {
+
+ Class[] classes = new Class[props.size() + refs.size()];
+ int i = 0;
+ for (JavaElementImpl property : props) {
+ classes[i] = property.getType();
+ i++;
+ }
+ for (JavaElementImpl reference : refs) {
+ classes[i] = reference.getType();
+ i++;
+ }
+ return areUnique(classes);
+ }
+
+ /**
+ * Unambiguously finds the reference or property associated with the given
+ * type
+ *
+ * @return the name of the reference or property if found, null if not
+ * @throws AmbiguousConstructorException if the constructor parameter cannot
+ * be resolved to a property or reference
+ */
+ private boolean findReferenceOrProperty(JavaParameterImpl parameter,
+ Map<String, JavaElementImpl> props,
+ Map<String, JavaElementImpl> refs) throws AmbiguousConstructorException {
+
+ boolean found = false;
+ if (!"".equals(parameter.getName())) {
+ // Match by name
+ JavaElementImpl prop = props.get(parameter.getName());
+ if (prop != null && prop.getType() == parameter.getType()) {
+ parameter.setClassifer(Property.class);
+ return true;
+ }
+ JavaElementImpl ref = refs.get(parameter.getName());
+ if (ref != null && ref.getType() == parameter.getType()) {
+ parameter.setClassifer(Reference.class);
+ return true;
+ }
+ }
+ for (JavaElementImpl property : props.values()) {
+ if (property.getType() == parameter.getType()) {
+ if (found) {
+ throw new AmbiguousConstructorException("Ambiguous property or reference for constructor type",
+ (Member)parameter.getAnchor());
+ }
+ parameter.setClassifer(Property.class);
+ parameter.setName(property.getName());
+ found = true;
+ // do not break since ambiguities must be checked, i.e. more
+ // than one prop or ref of the same type
+ }
+ }
+ for (JavaElementImpl reference : refs.values()) {
+ if (reference.getType() == parameter.getType()) {
+ if (found) {
+ throw new AmbiguousConstructorException("Ambiguous property or reference for constructor type",
+ (Member)parameter.getAnchor());
+ }
+ parameter.setClassifer(Reference.class);
+ parameter.setName(reference.getName());
+ found = true;
+ // do not break since ambiguities must be checked, i.e. more
+ // than one prop or ref of the same type
+ }
+ }
+ return found;
+ }
+
+ /**
+ * Returns true if a given type is reference according to the SCA
+ * specification rules for determining reference types The following rules
+ * are used to determine whether an unannotated field or setter method is a
+ * property or reference:
+ * <ol>
+ * <li>If its type is simple, then it is a property.
+ * <li>If its type is complex, then if the type is an interface marked by
+ *
+ * @Remotable, then it is a reference; otherwise, it is a property.
+ * <li>Otherwise, if the type associated with the member is an
+ * array or a java.util.Collection, the basetype is the element
+ * type of the array or the parameterized type of the
+ * Collection; otherwise the basetype is the member type. If the
+ * basetype is an interface with an
+ * @Remotable or
+ * @Service annotation then the member is defined as a reference. Otherwise,
+ * it is defined as a property.
+ * </ol>
+ * <p>
+ * The name of the reference or of the property is derived from the
+ * name found on the setter method or on the field.
+ */
+ private boolean isReferenceType(Class<?> cls, Type genericType) {
+ Class<?> baseType = JavaIntrospectionHelper.getBaseType(cls, genericType);
+ return baseType.isInterface() && baseType.isAnnotationPresent(Remotable.class);
+ }
+
+ /**
+ * Returns true if the given operation is defined in the collection of
+ * service interfaces
+ */
+ private boolean isInServiceInterface(Method operation, List<org.apache.tuscany.sca.assembly.Service> services) {
+ for (org.apache.tuscany.sca.assembly.Service service : services) {
+ Interface interface1 = service.getInterfaceContract().getInterface();
+ if (interface1 instanceof JavaInterface) {
+ Class<?> clazz = ((JavaInterface)interface1).getJavaClass();
+ if (isMethodMatched(clazz, operation)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Test if the class declares a method which matches the signature of the
+ * given method
+ *
+ * @param clazz
+ * @param method
+ * @return
+ */
+ private boolean isMethodMatched(Class<?> clazz, Method method) {
+ if (method.getDeclaringClass() == clazz) {
+ return true;
+ }
+ Method[] methods = clazz.getMethods();
+ for (Method m : methods) {
+ if (JavaIntrospectionHelper.exactMethodMatch(method, m)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Creates a mapped property.
+ *
+ * @param name the property name
+ * @param paramType the property type
+ */
+ private org.apache.tuscany.sca.assembly.Property createProperty(String name, Class<?> paramType) {
+ org.apache.tuscany.sca.assembly.Property property = assemblyFactory.createProperty();
+ property.setName(name);
+ property.setXSDType(JavaXMLMapper.getXMLType(paramType));
+ return property;
+ }
+
+ private boolean isAnnotated(JavaParameterImpl parameter) {
+ for (Annotation annotation : parameter.getAnnotations()) {
+ Class<? extends Annotation> annotType = annotation.annotationType();
+ if (annotType.equals(Property.class) || annotType.equals(Reference.class)
+ || annotType.equals(Resource.class)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean areUnique(JavaParameterImpl[] parameters) {
+ Set<Class> set = new HashSet<Class>(parameters.length);
+ for (JavaParameterImpl p : parameters) {
+ if (!set.add(p.getType())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public org.apache.tuscany.sca.assembly.Reference createReference(String name, Class<?> paramType)
+ throws IntrospectionException {
+ org.apache.tuscany.sca.assembly.Reference reference = assemblyFactory.createReference();
+ reference.setName(name);
+ JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract();
+ reference.setInterfaceContract(interfaceContract);
+ try {
+ JavaInterface callInterface = javaFactory.createJavaInterface(paramType);
+ reference.getInterfaceContract().setInterface(callInterface);
+ if (callInterface.getCallbackClass() != null) {
+ JavaInterface callbackInterface = javaFactory.createJavaInterface(callInterface.getCallbackClass());
+ reference.getInterfaceContract().setCallbackInterface(callbackInterface);
+ }
+ reference.setMultiplicity(Multiplicity.ZERO_ONE);
+ } catch (InvalidInterfaceException e1) {
+ throw new IntrospectionException(e1);
+ }
+
+ // FIXME: This part seems to have already been taken care above!!
+ try {
+ processCallback(paramType, reference);
+ } catch (InvalidServiceType e) {
+ throw new IntrospectionException(e);
+ }
+ return reference;
+ }
+
+ public org.apache.tuscany.sca.assembly.Service createService(Class<?> interfaze) throws InvalidInterfaceException {
+ org.apache.tuscany.sca.assembly.Service service = assemblyFactory.createService();
+ service.setName(interfaze.getSimpleName());
+
+ JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract();
+ service.setInterfaceContract(interfaceContract);
+
+ JavaInterface callInterface = javaFactory.createJavaInterface(interfaze);
+ service.getInterfaceContract().setInterface(callInterface);
+ if (callInterface.getCallbackClass() != null) {
+ JavaInterface callbackInterface = javaFactory.createJavaInterface(callInterface.getCallbackClass());
+ service.getInterfaceContract().setCallbackInterface(callbackInterface);
+ }
+
+ Interface javaInterface = service.getInterfaceContract().getInterface();
+ javaInterface.setRemotable(interfaze.getAnnotation(Remotable.class) != null);
+ service.getInterfaceContract().setInterface(javaInterface);
+ return service;
+ }
+
+ public void processCallback(Class<?> interfaze, Contract contract) throws InvalidServiceType {
+ Callback callback = interfaze.getAnnotation(Callback.class);
+ if (callback != null && !Void.class.equals(callback.value())) {
+ Class<?> callbackClass = callback.value();
+ JavaInterface javaInterface;
+ try {
+ javaInterface = javaFactory.createJavaInterface(callbackClass);
+ contract.getInterfaceContract().setCallbackInterface(javaInterface);
+ } catch (InvalidInterfaceException e) {
+ throw new InvalidServiceType("Invalid callback interface "+callbackClass, interfaze);
+ }
+ } else if (callback != null && Void.class.equals(callback.value())) {
+ throw new InvalidServiceType("No callback interface specified on annotation", interfaze);
+ }
+ }
+
+ public boolean injectionAnnotationsPresent(Annotation[][] annots) {
+ for (Annotation[] annotations : annots) {
+ for (Annotation annotation : annotations) {
+ Class<? extends Annotation> annotType = annotation.annotationType();
+ if (annotType.equals(Property.class) || annotType.equals(Reference.class)
+ || annotType.equals(Resource.class)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringConstructorArgElement.java b/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringConstructorArgElement.java index 57f4a26ba3..ce83baee05 100644 --- a/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringConstructorArgElement.java +++ b/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringConstructorArgElement.java @@ -31,6 +31,7 @@ public class SpringConstructorArgElement { private String ref;
private String type;
+ private int index;
private List<String> values = new ArrayList<String>();
public SpringConstructorArgElement(String ref, String type) {
@@ -50,6 +51,14 @@ public class SpringConstructorArgElement { this.ref = ref;
}
+ public int getIndex() {
+ return this.index;
+ }
+
+ public void setIndex(int index) {
+ this.index = index;
+ }
+
public List<String> getValues() {
return this.values;
}
diff --git a/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringXMLComponentTypeLoader.java b/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringXMLComponentTypeLoader.java index d584329e88..0100bb8fc5 100644 --- a/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringXMLComponentTypeLoader.java +++ b/branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringXMLComponentTypeLoader.java @@ -47,7 +47,10 @@ import org.apache.tuscany.sca.assembly.Reference; import org.apache.tuscany.sca.assembly.Service; import org.apache.tuscany.sca.contribution.service.ContributionReadException; import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; import org.apache.tuscany.sca.implementation.java.impl.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaConstructorImpl; +import org.apache.tuscany.sca.implementation.java.impl.JavaParameterImpl; import org.apache.tuscany.sca.implementation.spring.SpringImplementation; import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; import org.apache.tuscany.sca.interfacedef.java.JavaInterface; @@ -72,6 +75,7 @@ public class SpringXMLComponentTypeLoader { private ClassLoader cl; private SpringBeanIntrospector beanIntrospector; + private String contextPath; public SpringXMLComponentTypeLoader(AssemblyFactory assemblyFactory, JavaInterfaceFactory javaFactory, @@ -94,7 +98,7 @@ public class SpringXMLComponentTypeLoader { */ public void load(SpringImplementation implementation) throws ContributionReadException { //System.out.println("Spring TypeLoader - load method start"); - ComponentType componentType = implementation.getComponentType(); + ComponentType componentType = implementation.getComponentType(); /* Check that there is a component type object already set */ if (componentType == null) { throw new ContributionReadException("SpringXMLLoader load: implementation has no ComponentType object"); @@ -124,22 +128,22 @@ public class SpringXMLComponentTypeLoader { Resource resource; - String location = implementation.getLocation(); + contextPath = implementation.getLocation(); try { // FIXME - is the ContextClassLoader the right place to start the search? cl = Thread.currentThread().getContextClassLoader(); - resource = getApplicationContextResource(location, cl); + resource = getApplicationContextResource(contextPath, cl); implementation.setResource(resource); // The URI is used to uniquely identify the Implementation - implementation.setURI(resource.getURL().toString()); + implementation.setURI(resource.getURL().toString()); // FIXME - need a better way to handle the XMLInputFactory than allocating a new one every time XMLInputFactory xmlFactory = XMLInputFactory.newInstance(); reader = xmlFactory.createXMLStreamReader(resource.getInputStream()); // System.out.println("Spring TypeLoader - starting to read context file"); - readContextDefinition(reader, beans, services, references, scaproperties); + readContextDefinition(reader, beans, services, references, scaproperties); } catch (IOException e) { throw new ContributionReadException(e); @@ -153,18 +157,18 @@ public class SpringXMLComponentTypeLoader { generateComponentType(implementation, beans, services, references, scaproperties); return; - } // end method loadFromXML + } // end method loadFromXML /** * Method which returns the XMLStreamReader for the Spring application-context.xml file * specified in the location attribute */ - private XMLStreamReader getApplicationContextReader (String location) throws ContributionReadException { + private XMLStreamReader getApplicationContextReader(String location) throws ContributionReadException { try { // FIXME - is the ContextClassLoader the right place to start the search? - cl = Thread.currentThread().getContextClassLoader(); - Resource resource = getApplicationContextResource(location, cl); + cl = Thread.currentThread().getContextClassLoader(); + Resource resource = getApplicationContextResource(location, cl); // FIXME - need a better way to handle the XMLInputFactory than allocating a new one every time XMLInputFactory xmlFactory = XMLInputFactory.newInstance(); XMLStreamReader reader = xmlFactory.createXMLStreamReader(resource.getInputStream()); @@ -199,7 +203,9 @@ public class SpringXMLComponentTypeLoader { //FIXME - put the sequence of code below which gets the ireader into a subsidiary method String location = reader.getAttributeValue(null, "resource"); if (location != null) { - XMLStreamReader ireader = getApplicationContextReader(location); + // FIXME - need to find a right way of generating this path + String resourcePath = contextPath.substring(0, contextPath.lastIndexOf("/")+1) + location; + XMLStreamReader ireader = getApplicationContextReader(resourcePath); // Read the context definition for the identified imported resource readContextDefinition(ireader, beans, services, references, scaproperties); } @@ -264,6 +270,7 @@ public class SpringXMLComponentTypeLoader { if (Constants.BEAN_ELEMENT.equals(qname)) { innerbean = new SpringBeanElement(reader.getAttributeValue(null, "id"), reader .getAttributeValue(null, "class")); + innerbean.setInnerBean(true); beans.add(innerbean); readBeanDefinition(reader, innerbean, beans, services, references, scaproperties); } else if (Constants.PROPERTY_ELEMENT.equals(qname)) { @@ -273,6 +280,20 @@ public class SpringXMLComponentTypeLoader { } else if (Constants.CONSTRUCTORARG_ELEMENT.equals(qname)) { constructorArg = new SpringConstructorArgElement(reader.getAttributeValue(null, "ref"), reader.getAttributeValue(null, "type")); + if (reader.getAttributeValue(null, "index") != null) + constructorArg.setIndex((new Integer(reader.getAttributeValue(null, "index"))).intValue()); + if (reader.getAttributeValue(null, "value") != null) { + String value = reader.getAttributeValue(null, "value"); + constructorArg.addValue(value); + if ((value.indexOf(".xml") != -1)) { + if ((bean.getClassName().indexOf(".ClassPathXmlApplicationContext") != -1) || + (bean.getClassName().indexOf(".FileSystemXmlApplicationContext") != -1)) { + XMLStreamReader creader = getApplicationContextReader(value); + // Read the context definition for the constructor-arg resources + readContextDefinition(creader, beans, services, references, scaproperties); + } + } + } bean.addCustructorArgs(constructorArg); } else if (Constants.REF_ELEMENT.equals(qname)) { String ref = reader.getAttributeValue(null, "bean"); @@ -282,11 +303,9 @@ public class SpringXMLComponentTypeLoader { if (constructorArg != null) constructorArg.setRef(ref); } else if (Constants.VALUE_ELEMENT.equals(qname)) { String value = reader.getElementText(); - // Check if the parent element is a property - if (property != null) property.addValue(value); // Check if the parent element is a constructor-arg if (constructorArg != null) { - constructorArg.addValue(value); + constructorArg.addValue(value); // Identify the XML resource specified for the constructor-arg element if ((value.indexOf(".xml") != -1)) { if ((bean.getClassName().indexOf(".ClassPathXmlApplicationContext") != -1) || @@ -327,14 +346,15 @@ public class SpringXMLComponentTypeLoader { /* * 1. Each sca:service becomes a service in the component type * 2. Each sca:reference becomes a reference in the component type - * 3. IF there are no explicit service elements, each bean becomes a service - * 4. Each bean property which is a reference not pointing at another bean in the + * 3. Each sca:property becomes a property in the component type + * 4. IF there are no explicit service elements, each bean becomes a service + * 5. Each bean property which is a reference not pointing at another bean in the * application context becomes a reference unless it is pointing at one of the references - * 5. Each sca:property becomes a property in the component type * 6. Each bean property which is not a reference and which is not pointing * at another bean in the application context becomes a property in the component type */ + JavaImplementation javaImplementation = null; ComponentType componentType = implementation.getComponentType(); try { @@ -362,6 +382,24 @@ public class SpringXMLComponentTypeLoader { Reference theReference = createReference(interfaze, referenceElement.getName()); componentType.getReferences().add(theReference); } // end while + + // Next handle the properties + Iterator<SpringSCAPropertyElement> itsp = scaproperties.iterator(); + while (itsp.hasNext()) { + SpringSCAPropertyElement scaproperty = itsp.next(); + // Create a component type property if the SCA property element has a name + // and a type declared... + if (scaproperty.getType() != null && scaproperty.getName() != null) { + Property theProperty = assemblyFactory.createProperty(); + theProperty.setName(scaproperty.getName()); + // Get the Java class and then an XSD element type for the property + Class<?> propType = Class.forName(scaproperty.getType()); + theProperty.setXSDType(JavaXMLMapper.getXMLType(propType)); + componentType.getProperties().add(theProperty); + // Remember the Java Class (ie the type) for this property + implementation.setPropertyClass(theProperty.getName(), propType); + } // end if + } // end while // Finally deal with the beans Iterator<SpringBeanElement> itb; @@ -371,11 +409,13 @@ public class SpringXMLComponentTypeLoader { // Loop through all the beans found while (itb.hasNext()) { SpringBeanElement beanElement = itb.next(); + // If its a innerBean, ignore it + if (beanElement.isInnerBean()) continue; // Load the Spring bean class Class<?> beanClass = cl.loadClass(beanElement.getClassName()); // Introspect the bean ComponentType beanComponentType = assemblyFactory.createComponentType(); - beanIntrospector.introspectBean(beanClass, beanComponentType, implementation); + javaImplementation = beanIntrospector.introspectBean(beanClass, beanComponentType); // Get the service interface defined by this Spring Bean and add to // the component type of the Spring Assembly List<Service> beanServices = beanComponentType.getServices(); @@ -386,9 +426,94 @@ public class SpringXMLComponentTypeLoader { } } // end while } // end if - // Now check to see if there are any more references from beans that are not satisfied + itb = beans.iterator(); while (itb.hasNext()) { + SpringBeanElement beanElement = itb.next(); + // Ignore if the bean has no properties and constructor arguments + if (beanElement.getProperties().isEmpty() && beanElement.getCustructorArgs().isEmpty()) + continue; + + Class<?> beanClass = cl.loadClass(beanElement.getClassName()); + // Introspect the bean + ComponentType beanComponentType = assemblyFactory.createComponentType(); + javaImplementation = beanIntrospector.introspectBean(beanClass, beanComponentType); + Map<String, JavaElementImpl> propertyMap = javaImplementation.getPropertyMembers(); + JavaConstructorImpl constructor = javaImplementation.getConstructor(); + // Get the references by this Spring Bean and add the unresolved ones to + // the component type of the Spring Assembly + List<Reference> beanReferences = beanComponentType.getReferences(); + List<Property> beanProperties = beanComponentType.getProperties(); + + Iterator<SpringPropertyElement> itp = beanElement.getProperties().iterator(); + while (itp.hasNext()) { + SpringPropertyElement propertyElement = itp.next(); + if (propertyRefUnresolved(propertyElement.getRef(), beans, references, scaproperties)) { + // This means an unresolved reference from the spring bean... + for (Reference reference : beanReferences) { + if (propertyElement.getName().equals(reference.getName())) { + // The name of the reference in this case is the string in + // the @ref attribute of the Spring property element, NOT the + // name of the field in the Spring bean.... + reference.setName(propertyElement.getRef()); + componentType.getReferences().add(reference); + } // end if + } // end for + + // Store the unresolved references as unresolvedBeanRef in the Spring Implementation type + for (Property scaproperty : beanProperties) { + if (propertyElement.getName().equals(scaproperty.getName())) { + // The name of the reference in this case is the string in + // the @ref attribute of the Spring property element, NOT the + // name of the field in the Spring bean.... + Class<?> interfaze = cl.loadClass((propertyMap.get(propertyElement.getName()).getType()).getName()); + Reference theReference = createReference(interfaze, propertyElement.getRef()); + implementation.setUnresolvedBeanRef(propertyElement.getRef(), theReference); + } // end if + } // end for + } // end if + } // end while + + Iterator<SpringConstructorArgElement> itcr = beanElement.getCustructorArgs().iterator(); + while (itcr.hasNext()) { + SpringConstructorArgElement conArgElement = itcr.next(); + if (propertyRefUnresolved(conArgElement.getRef(), beans, references, scaproperties)) { + for (JavaParameterImpl parameter : constructor.getParameters()) { + String paramType = parameter.getType().getName(); + Class<?> interfaze = cl.loadClass(paramType); + // Create a component type reference/property if the constructor-arg element has a + // type attribute declared... + if (conArgElement.getType() != null && paramType.equals(conArgElement.getType())) { + if (parameter.getClassifer().getName().equals("org.osoa.sca.annotations.Reference")) { + Reference theReference = createReference(interfaze, conArgElement.getRef()); + componentType.getReferences().add(theReference); + } + if (parameter.getClassifer().getName().equals("org.osoa.sca.annotations.Property")) { + Property theProperty = assemblyFactory.createProperty(); + theProperty.setName(conArgElement.getRef()); + theProperty.setXSDType(JavaXMLMapper.getXMLType(interfaze)); + componentType.getProperties().add(theProperty); + // Remember the Java Class (ie the type) for this property + implementation.setPropertyClass(theProperty.getName(), interfaze); + } + } + + // Store the unresolved references as unresolvedBeanRef in the Spring Implementation type + // if the type attribute is absent in the contructor-arg element... + if (conArgElement.getType() == null) { + Reference theReference = createReference(interfaze, conArgElement.getRef()); + implementation.setUnresolvedBeanRef(conArgElement.getRef(), theReference); + } + } // end for + } // end if + } // end while + + } // end while + + + // Now check to see if there are any more references from beans that are not satisfied + /*itb = beans.iterator(); + while (itb.hasNext()) { SpringBeanElement beanElement = itb.next(); boolean unresolvedProperties = false; if (!beanElement.getProperties().isEmpty()) { @@ -406,8 +531,8 @@ public class SpringXMLComponentTypeLoader { Class<?> beanClass = cl.loadClass(beanElement.getClassName()); // Introspect the bean ComponentType beanComponentType = assemblyFactory.createComponentType(); - Map<String, JavaElementImpl> propertyMap = - beanIntrospector.introspectBean(beanClass, beanComponentType, implementation); + javaImplementation = beanIntrospector.introspectBean(beanClass, beanComponentType); + Map<String, JavaElementImpl> propertyMap = javaImplementation.getPropertyMembers(); // Get the references by this Spring Bean and add the unresolved ones to // the component type of the Spring Assembly List<Reference> beanReferences = beanComponentType.getReferences(); @@ -441,48 +566,14 @@ public class SpringXMLComponentTypeLoader { implementation.setUnresolvedBeanRef(propertyElement.getRef(), theReference); resolved = true; } - } - - /*// If the bean property is not already resolved as a reference - // then it must be an SCA property... - for (Property scaproperty : beanProperties) { - if (propertyElement.getName().equals(scaproperty.getName())) { - // The name of the reference in this case is the string in - // the @ref attribute of the Spring property element, NOT the - // name of the field in the Spring bean.... - scaproperty.setName(propertyElement.getRef()); - componentType.getProperties().add(scaproperty); - // Fetch and store the type of the property - implementation.setPropertyClass(propertyElement.getRef(), propertyMap - .get(propertyElement.getName()).getType()); - resolved = true; - } // end if - } // end for */ + } } // end if } // end if } // end while } // end if } // end if - - } // end while - - Iterator<SpringSCAPropertyElement> itsp = scaproperties.iterator(); - while (itsp.hasNext()) { - SpringSCAPropertyElement scaproperty = itsp.next(); - // Create a component type property if the SCA property element has a name - // and a type declared... - if (scaproperty.getType() != null && scaproperty.getName() != null) { - Property theProperty = assemblyFactory.createProperty(); - theProperty.setName(scaproperty.getName()); - // Get the Java class and then an XSD element type for the property - Class<?> propType = Class.forName(scaproperty.getType()); - theProperty.setXSDType(JavaXMLMapper.getXMLType(propType)); - componentType.getProperties().add(theProperty); - // Remember the Java Class (ie the type) for this property - implementation.setPropertyClass(theProperty.getName(), propType); - } // end if - } // end while + } // end while*/ } catch (ClassNotFoundException e) { // Means that either an interface class, property class or a bean was not found @@ -490,7 +581,7 @@ public class SpringXMLComponentTypeLoader { } catch (InvalidInterfaceException e) { throw new ContributionReadException(e); } catch (ContributionResolveException e) { - + } // end try // If we get here, the Spring assembly component type is resolved diff --git a/branches/sca-java-1.x/modules/implementation-spring/src/test/resources/SpringHelloWorld-Imported-context.xml b/branches/sca-java-1.x/modules/implementation-spring/src/test/resources/SpringHelloWorld-Imported-context.xml deleted file mode 100644 index 18ce21805c..0000000000 --- a/branches/sca-java-1.x/modules/implementation-spring/src/test/resources/SpringHelloWorld-Imported-context.xml +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. ---> -<!-- Application context for the SpringHelloWorld testcase --> -<beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:sca="http://www.springframework.org/schema/sca" - xsi:schemaLocation=" -http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd -http://www.springframework.org/schema/sca http://www.osoa.org/xmlns/sca/1.0/spring-sca.xsd"> - - <bean id="testBean" class="org.apache.tuscany.sca.implementation.spring.itests.mock.TestHelloWorldBean" lazy-init="true"> - </bean> - -</beans>
\ No newline at end of file |