summaryrefslogtreecommitdiffstats
path: root/branches/sca-java-1.x/modules/implementation-spring/src/main/java
diff options
context:
space:
mode:
authorramkumar <ramkumar@13f79535-47bb-0310-9956-ffa450edef68>2009-03-09 10:00:30 +0000
committerramkumar <ramkumar@13f79535-47bb-0310-9956-ffa450edef68>2009-03-09 10:00:30 +0000
commitff6d646fcbd9f06f013cf934fcdde66c213c7db2 (patch)
tree26653413a72aade32663a7478c4260ac89b7e2c8 /branches/sca-java-1.x/modules/implementation-spring/src/main/java
parent8075c532ce67243ebdbc82d7f36a055f3e0ea4a2 (diff)
Fixes for TUSCANY-2642, 2909, 2910
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@751642 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'branches/sca-java-1.x/modules/implementation-spring/src/main/java')
-rw-r--r--branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementation.java62
-rw-r--r--branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationProvider.java118
-rw-r--r--branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanElement.java9
-rw-r--r--branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanIntrospector.java27
-rw-r--r--branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringBeanPojoProcessor.java648
-rw-r--r--branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringConstructorArgElement.java9
-rw-r--r--branches/sca-java-1.x/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringXMLComponentTypeLoader.java205
7 files changed, 924 insertions, 154 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