summaryrefslogtreecommitdiffstats
path: root/branches/sca-java-2.0-M4/modules/implementation-spring/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'branches/sca-java-2.0-M4/modules/implementation-spring/src/main')
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringBeanElement.java117
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringConstructorArgElement.java77
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementation.java228
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationBuilder.java41
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationConstants.java73
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringPropertyElement.java60
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAPropertyElement.java52
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAReferenceElement.java78
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAServiceElement.java78
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/introspect/SpringBeanIntrospector.java99
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/introspect/SpringBeanPojoProcessor.java660
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/introspect/SpringXMLComponentTypeLoader.java1153
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/ComponentTie.java41
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/PropertyValueTie.java53
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringContextStub.java134
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringImplementationProvider.java85
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringImplementationProviderFactory.java77
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringImplementationTie.java147
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringInvocationException.java40
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringInvoker.java124
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringImplementationProcessor.java230
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.assembly.builder.ImplementationBuilder18
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor20
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.definitions.xml.Definitions17
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory20
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/impl-spring-validation-messages.properties28
-rw-r--r--branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/org/apache/tuscany/sca/implementation/spring/definitions.xml30
27 files changed, 3780 insertions, 0 deletions
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringBeanElement.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringBeanElement.java
new file mode 100644
index 0000000000..f64c5f9476
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringBeanElement.java
@@ -0,0 +1,117 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents a <bean> element in a Spring application-context
+ * - this has id and className attributes
+ * - plus zero or more property elements as children
+ *
+ * @version $Rev$ $Date$
+ */
+public class SpringBeanElement {
+
+ private String id;
+ private String className = null;
+ private boolean innerBean = false;
+ private boolean abstractBean = false;
+ private boolean parentAttribute = false;
+ private boolean factoryBeanAttribute = false;
+ private boolean factoryMethodAttribute = false;
+
+ private List<SpringPropertyElement> properties = new ArrayList<SpringPropertyElement>();
+ private List<SpringConstructorArgElement> constructorargs = new ArrayList<SpringConstructorArgElement>();
+
+ public SpringBeanElement(String id, String className) {
+ this.id = id;
+ this.className = className;
+ }
+
+ public String getClassName() {
+ return className;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public List<SpringPropertyElement> getProperties() {
+ return properties;
+ }
+
+ public void addProperty(SpringPropertyElement property) {
+ properties.add(property);
+ }
+
+ public List<SpringConstructorArgElement> getCustructorArgs() {
+ return constructorargs;
+ }
+
+ public void addCustructorArgs(SpringConstructorArgElement args) {
+ constructorargs.add(args);
+ }
+
+ public boolean isInnerBean() {
+ return innerBean;
+ }
+
+ public void setInnerBean(boolean innerBean) {
+ this.innerBean = innerBean;
+ }
+
+ public boolean isAbstractBean() {
+ return abstractBean;
+ }
+
+ public void setAbstractBean(boolean abstractBean) {
+ this.abstractBean = abstractBean;
+ }
+
+ public boolean hasParentAttribute() {
+ return parentAttribute;
+ }
+
+ public void setParentAttribute(boolean parentAttribute) {
+ this.parentAttribute = parentAttribute;
+ }
+
+ public boolean hasFactoryBeanAttribute() {
+ return factoryBeanAttribute;
+ }
+
+ public void setFactoryBeanAttribute(boolean factoryBeanAttribute) {
+ this.factoryBeanAttribute = factoryBeanAttribute;
+ }
+
+ public boolean hasFactoryMethodAttribute() {
+ return factoryMethodAttribute;
+ }
+
+ public void setFactoryMethodAttribute(boolean factoryMethodAttribute) {
+ this.factoryMethodAttribute = factoryMethodAttribute;
+ }
+
+} // end class SpringBeanElement
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringConstructorArgElement.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringConstructorArgElement.java
new file mode 100644
index 0000000000..9ae1273592
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringConstructorArgElement.java
@@ -0,0 +1,77 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents a <constructor-arg> element in a Spring application-context
+ * - this has ref attribute
+ *
+ * @version $Rev$ $Date$
+ */
+public class SpringConstructorArgElement {
+
+ private String type;
+ private int autoIndex = -1;
+ private int index = -1;
+ private List<String> refs = new ArrayList<String>();
+ private List<String> values = new ArrayList<String>();
+
+ public SpringConstructorArgElement(String type) {
+ this.type = type;
+ }
+
+ public String getType() {
+ return this.type;
+ }
+
+ public List<String> getRefs() {
+ return this.refs;
+ }
+
+ public void addRef(String ref) {
+ this.refs.add(ref);
+ }
+
+ public int getIndex() {
+ return this.index;
+ }
+
+ public void setIndex(int index) {
+ this.index = index;
+ }
+
+ public int getAutoIndex() {
+ return this.autoIndex;
+ }
+
+ public void setAutoIndex(int index) {
+ this.autoIndex = index;
+ }
+
+ public List<String> getValues() {
+ return this.values;
+ }
+
+ public void addValue(String value) {
+ this.values.add(value);
+ }
+}
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementation.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementation.java
new file mode 100644
index 0000000000..8081fb4911
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementation.java
@@ -0,0 +1,228 @@
+/*
+ * 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;
+
+import java.net.URL;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.ComponentType;
+import org.apache.tuscany.sca.assembly.Extensible;
+import org.apache.tuscany.sca.assembly.Implementation;
+import org.apache.tuscany.sca.assembly.Property;
+import org.apache.tuscany.sca.assembly.Reference;
+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.runtime.RuntimeComponent;
+
+
+/**
+ * Represents a Spring implementation.
+ *
+ * @version $Rev$ $Date$
+ */
+public class SpringImplementation extends ImplementationImpl implements Implementation, Extensible {
+ public final static QName TYPE = new QName(SCA11_NS, "implementation.spring");
+ // The location attribute which points to the Spring application-context XML file
+ private String location;
+ // The application-context file as a Spring Resource
+ private List<URL> resource;
+ private ComponentType componentType;
+ // Mapping of Services to Beans
+ private Hashtable<String, SpringBeanElement> serviceMap;
+ // Mapping of property names to Java class
+ private Hashtable<String, Class<?>> propertyMap;
+ // List of unresolved bean property references
+ private Hashtable<String, Reference> unresolvedBeanRef;
+ private ClassLoader classLoader;
+
+ public SpringImplementation() {
+ super(TYPE);
+ this.location = null;
+ this.resource = null;
+ setUnresolved(true);
+ serviceMap = new Hashtable<String, SpringBeanElement>();
+ propertyMap = new Hashtable<String, Class<?>>();
+ unresolvedBeanRef = new Hashtable<String, Reference>();
+ } // end method SpringImplementation
+
+ /* Returns the location attribute for this Spring implementation */
+ public String getLocation() {
+ return location;
+ }
+
+ /**
+ * Sets the location attribute for this Spring implementation
+ * location - a URI to the Spring application-context file
+ */
+ public void setLocation(String location) {
+ this.location = location;
+ return;
+ }
+
+ public void setResource(List<URL> resource) {
+ this.resource = resource;
+ }
+
+ public List<URL> getResource() {
+ return resource;
+ }
+
+ /*
+ * Returns the componentType for this Spring implementation
+ */
+ public ComponentType getComponentType() {
+ return componentType;
+ }
+
+ /*
+ * Sets the componentType for this Spring implementation
+ */
+ public void setComponentType(ComponentType componentType) {
+ this.componentType = componentType;
+ }
+
+ @Override
+ public List<Service> getServices() {
+ return componentType.getServices();
+ }
+
+ @Override
+ public List<Reference> getReferences() {
+ return componentType.getReferences();
+ }
+
+ @Override
+ public List<Property> getProperties() {
+ return componentType.getProperties();
+ }
+
+ /**
+ * Returns the Spring Bean which implements a particular service
+ * @param service the service
+ * @return the bean which implements the service, as a SpringBeanElement
+ */
+ public SpringBeanElement getBeanFromService(Service service) {
+ SpringBeanElement theBean = serviceMap.get(service.getName());
+ return theBean;
+ }
+
+ /**
+ * Sets the mapping from a service to the Spring Bean that implements the service
+ * @param service the service
+ * @param theBean a SpringBeanElement for the Bean implementing the service
+ */
+ public void setBeanForService(Service service, SpringBeanElement theBean) {
+ serviceMap.put(service.getName(), theBean);
+ }
+
+ /**
+ * Add a mapping from a SCA property name to a Java class for the property
+ * @param propertyName
+ * @param propertyClass
+ */
+ public void setPropertyClass(String propertyName, Class<?> propertyClass) {
+ if (propertyName == null || propertyClass == null)
+ return;
+ propertyMap.put(propertyName, propertyClass);
+ return;
+ } // end method setPropertyClass
+
+ /**
+ * Gets the Java Class for an SCA property
+ * @param propertyName - the property name
+ * @return - a Class object for the type of the property
+ */
+ public Class<?> getPropertyClass(String propertyName) {
+ return propertyMap.get(propertyName);
+ } // end method getPropertyClass
+
+ public void setUnresolvedBeanRef(String refName, Reference reference) {
+ if (refName == null || reference == null)
+ return;
+ unresolvedBeanRef.put(refName, reference);
+ return;
+ } // end method setUnresolvedBeanRef
+
+ public Reference getUnresolvedBeanRef(String refName) {
+ return unresolvedBeanRef.get(refName);
+ } // end method getUnresolvedBeanRef
+
+
+ /**
+ * Use preProcess to validate and map the references and properties dynamically
+ */
+ public void build(Component component) {
+ if (!(component instanceof RuntimeComponent))
+ return;
+
+ RuntimeComponent rtc = (RuntimeComponent) component;
+
+ for (Reference reference : rtc.getReferences()) {
+ if (unresolvedBeanRef.containsKey(reference.getName())) {
+ Reference ref = unresolvedBeanRef.get(reference.getName());
+ componentType.getReferences().add(
+ createReference(reference, ref.getInterfaceContract()));
+ unresolvedBeanRef.remove(reference.getName());
+ }
+ }
+
+ for (Property property : rtc.getProperties()) {
+ if (unresolvedBeanRef.containsKey(property.getName())) {
+ componentType.getProperties().add(createProperty(property));
+ this.setPropertyClass(property.getName(), property.getClass());
+ unresolvedBeanRef.remove(property.getName());
+ }
+ }
+ }
+
+ protected Reference createReference(Reference reference, InterfaceContract interfaze) {
+ Reference newReference;
+ try {
+ newReference = (Reference)reference.clone();
+ if (newReference.getInterfaceContract() == null)
+ newReference.setInterfaceContract(interfaze);
+ } catch (CloneNotSupportedException e) {
+ throw new AssertionError(e); // should not ever happen
+ }
+ return newReference;
+ }
+
+ protected Property createProperty(Property property) {
+ Property newProperty;
+ try {
+ newProperty = (Property)property.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new AssertionError(e); // should not ever happen
+ }
+ return newProperty;
+ }
+
+ public ClassLoader getClassLoader() {
+ return classLoader;
+ }
+
+ public void setClassLoader(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+} \ No newline at end of file
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationBuilder.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationBuilder.java
new file mode 100644
index 0000000000..1a246fa03a
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationBuilder.java
@@ -0,0 +1,41 @@
+/*
+ * 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;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.assembly.Component;
+import org.apache.tuscany.sca.assembly.builder.BuilderContext;
+import org.apache.tuscany.sca.assembly.builder.ImplementationBuilder;
+
+/**
+ *
+ */
+public class SpringImplementationBuilder implements ImplementationBuilder<SpringImplementation> {
+
+ public void build(Component component, SpringImplementation implmentation, BuilderContext context) {
+ implmentation.build(component);
+ }
+
+ public QName getImplementationType() {
+ return SpringImplementation.TYPE;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationConstants.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationConstants.java
new file mode 100644
index 0000000000..caae72fa90
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringImplementationConstants.java
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+import javax.xml.namespace.QName;
+
+/**
+ * Constants used in Spring Application Context XML files.
+ */
+public interface SpringImplementationConstants {
+
+ String SCA_NS = "http://www.springframework.org/schema/sca";
+ String SPRING_NS = "http://www.springframework.org/schema/beans";
+
+ String PROPERTY = "property";
+ QName SCA_PROPERTY_ELEMENT = new QName(SCA_NS, PROPERTY);
+ QName PROPERTY_ELEMENT = new QName(SPRING_NS, PROPERTY);
+
+ String SCASERVICE = "service";
+ QName SCA_SERVICE_ELEMENT = new QName(SCA_NS, SCASERVICE);
+
+ String SCAREFERENCE = "reference";
+ QName SCA_REFERENCE_ELEMENT = new QName(SCA_NS, SCAREFERENCE);
+
+ String BEANS = "beans";
+ QName BEANS_ELEMENT = new QName(SPRING_NS, BEANS);
+
+ String IMPORT = "import";
+ QName IMPORT_ELEMENT = new QName(SPRING_NS, IMPORT);
+
+ String BEAN = "bean";
+ QName BEAN_ELEMENT = new QName(SPRING_NS, BEAN);
+
+ String CONSTRUCTORARG = "constructor-arg";
+ QName CONSTRUCTORARG_ELEMENT = new QName(SPRING_NS, CONSTRUCTORARG);
+
+ String LIST = "list";
+ QName LIST_ELEMENT = new QName(SPRING_NS, LIST);
+
+ String SET = "set";
+ QName SET_ELEMENT = new QName(SPRING_NS, SET);
+
+ String MAP = "map";
+ QName MAP_ELEMENT = new QName(SPRING_NS, MAP);
+
+ String VALUE = "value";
+ QName VALUE_ELEMENT = new QName(SPRING_NS, VALUE);
+
+ String REF = "ref";
+ QName REF_ELEMENT = new QName(SPRING_NS, REF);
+
+ String ENTRY = "entry";
+ QName ENTRY_ELEMENT = new QName(SPRING_NS, ENTRY);
+
+ String APPLICATION_CONTEXT = "application-context.xml";
+}
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringPropertyElement.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringPropertyElement.java
new file mode 100644
index 0000000000..37b8ef37a6
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringPropertyElement.java
@@ -0,0 +1,60 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents a <property> element in a Spring application-context
+ * - this has name and ref attributes
+ *
+ * @version $Rev$ $Date$
+ */
+public class SpringPropertyElement {
+
+ private String name;
+ private List<String> refs = new ArrayList<String>();
+ private List<String> values = new ArrayList<String>();
+
+ public SpringPropertyElement(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public List<String> getRefs() {
+ return this.refs;
+ }
+
+ public void addRef(String ref) {
+ this.refs.add(ref);
+ }
+
+ public List<String> getValues() {
+ return this.values;
+ }
+
+ public void addValue(String value) {
+ this.values.add(value);
+ }
+
+} // end class SpringPropertyElement
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAPropertyElement.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAPropertyElement.java
new file mode 100644
index 0000000000..b192580a78
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAPropertyElement.java
@@ -0,0 +1,52 @@
+/*
+ * 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;
+
+/**
+ * Represents an <sca:property> element in a Spring application-context
+ * - this has name and type attributes
+ * @version $Rev$ $Date$
+ */
+public class SpringSCAPropertyElement {
+
+ private String name;
+ private String type;
+
+ public SpringSCAPropertyElement(String name, String type) {
+ this.name = name;
+ this.type = type;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+} // end class SpringPropertyElement
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAReferenceElement.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAReferenceElement.java
new file mode 100644
index 0000000000..bc010229ad
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAReferenceElement.java
@@ -0,0 +1,78 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.tuscany.sca.policy.Intent;
+import org.apache.tuscany.sca.policy.PolicySet;
+
+/**
+ * Represents a <sca:reference> element in a Spring application-context
+ * - this has id and className attributes
+ * - plus zero or more property elements as children
+ *
+ * @version $Rev$ $Date$
+ */
+public class SpringSCAReferenceElement {
+
+ private String name;
+ private String type;
+ private String defaultBean;
+ private List<Intent> intents = new ArrayList<Intent>();
+ private List<PolicySet> policySets = new ArrayList<PolicySet>();
+
+ public SpringSCAReferenceElement(String name, String type) {
+ this.name = name;
+ this.type = type;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setDefaultBean(String defaultBean) {
+ this.defaultBean = defaultBean;
+ }
+
+ public String getDefaultBean() {
+ return defaultBean;
+ }
+
+ public List<Intent> getRequiredIntents() {
+ return intents;
+ }
+
+ public List<PolicySet> getPolicySets() {
+ return policySets;
+ }
+
+} // end class SpringSCAReferenceElement
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAServiceElement.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAServiceElement.java
new file mode 100644
index 0000000000..dbddc00b33
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/SpringSCAServiceElement.java
@@ -0,0 +1,78 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.tuscany.sca.policy.Intent;
+import org.apache.tuscany.sca.policy.PolicySet;
+
+/**
+ * Represents a <sca:service> element in a Spring application-context
+ * - this has id and className attributes
+ * - plus zero or more property elements as children
+ *
+ * @version $Rev$ $Date$
+ */
+public class SpringSCAServiceElement {
+
+ private String name;
+ private String type;
+ private String target;
+ private List<Intent> intents = new ArrayList<Intent>();
+ private List<PolicySet> policySets = new ArrayList<PolicySet>();
+
+ public SpringSCAServiceElement(String name, String target) {
+ this.name = name;
+ this.target = target;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setTarget(String target) {
+ this.target = target;
+ }
+
+ public String getTarget() {
+ return target;
+ }
+
+ public List<Intent> getRequiredIntents() {
+ return intents;
+ }
+
+ public List<PolicySet> getPolicySets() {
+ return policySets;
+ }
+
+} // end class SpringSCAServiceElement
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/introspect/SpringBeanIntrospector.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/introspect/SpringBeanIntrospector.java
new file mode 100644
index 0000000000..3aa257686d
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/introspect/SpringBeanIntrospector.java
@@ -0,0 +1,99 @@
+/*
+ * 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.introspect;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.ComponentType;
+import org.apache.tuscany.sca.contribution.processor.ContributionResolveException;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+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.spring.SpringConstructorArgElement;
+
+/**
+ * Provides introspection functions for Spring beans
+ * This version leans heavily on the implementation-java classes
+ *
+ * @version $Rev$ $Date$
+ */
+public class SpringBeanIntrospector {
+
+ private JavaImplementationFactory javaImplementationFactory;
+
+ /**
+ * The constructor sets up the various visitor elements that will be used to introspect
+ * the Spring bean and extract SCA information.
+ *
+ * @param assemblyFactory The Assembly Factory to use
+ * @param javaFactory The Java Interface Factory to use
+ * @param policyFactory The Policy Factory to use.
+ */
+ public SpringBeanIntrospector(ExtensionPointRegistry registry,
+ List<SpringConstructorArgElement> conArgs) {
+
+ FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ javaImplementationFactory = factories.getFactory(JavaImplementationFactory.class);
+ } // end constructor
+
+ /**
+ * Introspect a Spring Bean and extract the features important to SCA
+ * @param beanClass the Spring Bean class to introspect
+ * @param componentType the componentType that is filled in through the introspection
+ * process (assumed empty on invocation, filled on return
+ * @return a Map of property names to JavaElementImpl
+ * @throws ContributionResolveException - if there was a problem resolving the
+ * Spring Bean or its componentType
+ *
+ */
+ public JavaImplementation introspectBean(Class<?> beanClass, ComponentType componentType) throws ContributionResolveException
+ {
+ if (componentType == null)
+ throw new ContributionResolveException("Introspect Spring bean: supplied componentType is null");
+
+ // Create a Java implementation ready for the introspection
+ JavaImplementation javaImplementation = javaImplementationFactory.createJavaImplementation();
+
+ try {
+ // Introspect the bean...the results of the introspection are placed into the Java implementation
+ javaImplementationFactory.createJavaImplementation(javaImplementation, beanClass);
+
+ // Extract the services, references & properties found through introspection
+ // put the services, references and properties into the component type
+ componentType.getServices().addAll(javaImplementation.getServices());
+ componentType.getReferences().addAll(javaImplementation.getReferences());
+ componentType.getProperties().addAll(javaImplementation.getProperties());
+
+ } 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;
+
+ } // end method introspectBean
+
+} // end class SpringBeanIntrospector
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/introspect/SpringBeanPojoProcessor.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/introspect/SpringBeanPojoProcessor.java
new file mode 100644
index 0000000000..3a8eec99fa
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/introspect/SpringBeanPojoProcessor.java
@@ -0,0 +1,660 @@
+/*
+ * 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.introspect;
+
+import static org.apache.tuscany.sca.implementation.java.introspect.JavaIntrospectionHelper.getAllInterfaces;
+import static org.apache.tuscany.sca.implementation.java.introspect.JavaIntrospectionHelper.getAllPublicAndProtectedFields;
+import static org.apache.tuscany.sca.implementation.java.introspect.JavaIntrospectionHelper.getAllUniquePublicProtectedMethods;
+import static org.apache.tuscany.sca.implementation.java.introspect.JavaIntrospectionHelper.getPrivateFields;
+import static org.apache.tuscany.sca.implementation.java.introspect.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.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.implementation.java.IntrospectionException;
+import org.apache.tuscany.sca.implementation.java.JavaConstructorImpl;
+import org.apache.tuscany.sca.implementation.java.JavaElementImpl;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaParameterImpl;
+import org.apache.tuscany.sca.implementation.java.introspect.BaseJavaClassVisitor;
+import org.apache.tuscany.sca.implementation.java.introspect.JavaIntrospectionHelper;
+import org.apache.tuscany.sca.implementation.java.introspect.impl.AmbiguousConstructorException;
+import org.apache.tuscany.sca.implementation.java.introspect.impl.InvalidServiceTypeException;
+import org.apache.tuscany.sca.implementation.java.introspect.impl.NoConstructorException;
+import org.apache.tuscany.sca.implementation.java.introspect.impl.Resource;
+import org.apache.tuscany.sca.implementation.spring.SpringConstructorArgElement;
+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.oasisopen.sca.annotation.Callback;
+import org.oasisopen.sca.annotation.Context;
+import org.oasisopen.sca.annotation.Property;
+import org.oasisopen.sca.annotation.Reference;
+import org.oasisopen.sca.annotation.Remotable;
+
+/**
+ * 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$ $Date$
+ */
+public class SpringBeanPojoProcessor extends BaseJavaClassVisitor {
+ private List<SpringConstructorArgElement> conArgs;
+
+ public SpringBeanPojoProcessor(AssemblyFactory assemblyFactory, JavaInterfaceFactory javaFactory, List<SpringConstructorArgElement> conArgs) {
+ super(assemblyFactory);
+ this.javaInterfaceFactory = javaFactory;
+ this.conArgs = conArgs;
+ }
+
+ public SpringBeanPojoProcessor(ExtensionPointRegistry registry) {
+ super(registry);
+ }
+
+ @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();
+ Map<String, JavaElementImpl> props = type.getPropertyMembers();
+ Map<String, JavaElementImpl> refs = type.getReferenceMembers();
+ Constructor constructor;
+ boolean explict = false;
+ if (definition != null && definition.getConstructor()
+ .isAnnotationPresent(org.oasisopen.sca.annotation.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 {
+ // multiple constructors scenario
+ Constructor<T> selected = null;
+ for (Constructor<T> ctor : constructors) {
+ if (ctor.getParameterTypes().length == 0) {
+ selected = ctor;
+ } else if (ctor.getParameterTypes().length == conArgs.size()) {
+ // we will find a constructor which has atleast one
+ // reference or property as its parameter types.
+ Class<?>[] parametersTypes = ctor.getParameterTypes();
+ for (Class<?> pType: parametersTypes) {
+ for (JavaElementImpl property : props.values()) {
+ if (pType.equals(property.getType()))
+ selected = ctor;
+ }
+ for (JavaElementImpl reference : refs.values()) {
+ if (pType.equals(reference.getType()))
+ selected = ctor;
+ }
+ }
+ }
+ }
+ if (selected == null) {
+ throw new NoConstructorException();
+ }
+ constructor = selected;
+ }
+ definition = type.getConstructors().get(constructor);
+ type.setConstructor(definition);
+ }
+
+ JavaParameterImpl[] parameters = definition.getParameters();
+ if (parameters.length == 0) {
+ return;
+ }
+
+ 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 = javaInterfaceFactory.createJavaInterfaceContract();
+ reference.setInterfaceContract(interfaceContract);
+ try {
+ JavaInterface callInterface = javaInterfaceFactory.createJavaInterface(paramType);
+ reference.getInterfaceContract().setInterface(callInterface);
+ if (callInterface.getCallbackClass() != null) {
+ JavaInterface callbackInterface = javaInterfaceFactory.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 (InvalidServiceTypeException 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 = javaInterfaceFactory.createJavaInterfaceContract();
+ service.setInterfaceContract(interfaceContract);
+
+ JavaInterface callInterface = javaInterfaceFactory.createJavaInterface(interfaze);
+ service.getInterfaceContract().setInterface(callInterface);
+ if (callInterface.getCallbackClass() != null) {
+ JavaInterface callbackInterface = javaInterfaceFactory.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 InvalidServiceTypeException {
+ Callback callback = interfaze.getAnnotation(Callback.class);
+ if (callback != null && !Void.class.equals(callback.value())) {
+ Class<?> callbackClass = callback.value();
+ JavaInterface javaInterface;
+ try {
+ javaInterface = javaInterfaceFactory.createJavaInterface(callbackClass);
+ contract.getInterfaceContract().setCallbackInterface(javaInterface);
+ } catch (InvalidInterfaceException e) {
+ throw new InvalidServiceTypeException("Invalid callback interface "+callbackClass, interfaze);
+ }
+ } else if (callback != null && Void.class.equals(callback.value())) {
+ throw new InvalidServiceTypeException("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-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/introspect/SpringXMLComponentTypeLoader.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/introspect/SpringXMLComponentTypeLoader.java
new file mode 100644
index 0000000000..bd3134c5f2
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/introspect/SpringXMLComponentTypeLoader.java
@@ -0,0 +1,1153 @@
+/*
+ * 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.introspect;
+
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.ComponentType;
+import org.apache.tuscany.sca.assembly.Multiplicity;
+import org.apache.tuscany.sca.assembly.Property;
+import org.apache.tuscany.sca.assembly.Reference;
+import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.assembly.xml.PolicySubjectProcessor;
+import org.apache.tuscany.sca.contribution.Artifact;
+import org.apache.tuscany.sca.contribution.ContributionFactory;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.processor.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.processor.ProcessorContext;
+import org.apache.tuscany.sca.contribution.resolver.ClassReference;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.implementation.java.JavaConstructorImpl;
+import org.apache.tuscany.sca.implementation.java.JavaElementImpl;
+import org.apache.tuscany.sca.implementation.java.JavaImplementation;
+import org.apache.tuscany.sca.implementation.java.JavaParameterImpl;
+import org.apache.tuscany.sca.implementation.spring.SpringBeanElement;
+import org.apache.tuscany.sca.implementation.spring.SpringConstructorArgElement;
+import org.apache.tuscany.sca.implementation.spring.SpringImplementation;
+import org.apache.tuscany.sca.implementation.spring.SpringImplementationConstants;
+import org.apache.tuscany.sca.implementation.spring.SpringPropertyElement;
+import org.apache.tuscany.sca.implementation.spring.SpringSCAPropertyElement;
+import org.apache.tuscany.sca.implementation.spring.SpringSCAReferenceElement;
+import org.apache.tuscany.sca.implementation.spring.SpringSCAServiceElement;
+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.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.apache.tuscany.sca.monitor.Problem.Severity;
+import org.apache.tuscany.sca.policy.PolicyFactory;
+
+/**
+ * Introspects a Spring XML application-context configuration file to create <implementation-spring../>
+ * component type information.
+ *
+ * @version $Rev$ $Date$
+ */
+public class SpringXMLComponentTypeLoader {
+ private ExtensionPointRegistry registry;
+ private XMLInputFactory xmlInputFactory;
+ private ContributionFactory contributionFactory;
+ private AssemblyFactory assemblyFactory;
+ private JavaInterfaceFactory javaFactory;
+ private PolicyFactory policyFactory;
+ private PolicySubjectProcessor policyProcessor;
+ private Monitor monitor;
+ private SpringBeanIntrospector beanIntrospector;
+
+ public SpringXMLComponentTypeLoader(ExtensionPointRegistry registry,
+ Monitor monitor) {
+ super();
+ this.registry = registry;
+ FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ this.assemblyFactory = factories.getFactory(AssemblyFactory.class);
+ this.javaFactory = factories.getFactory(JavaInterfaceFactory.class);
+ this.policyFactory = factories.getFactory(PolicyFactory.class);
+ this.policyProcessor = new PolicySubjectProcessor(policyFactory);
+ this.contributionFactory = factories.getFactory(ContributionFactory.class);
+ this.xmlInputFactory = factories.getFactory(XMLInputFactory.class);
+ this.monitor = monitor;
+ }
+
+ /**
+ * Report a exception.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(String message, Object model, Exception ex) {
+ if (monitor != null) {
+ Problem problem = monitor.createProblem(this.getClass().getName(), "impl-spring-validation-messages", Severity.ERROR, model, message, ex);
+ monitor.problem(problem);
+ }
+ }
+
+ /**
+ * Report a error.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(String message, Object model, Object... messageParameters) {
+ if (monitor != null) {
+ Problem problem = monitor.createProblem(this.getClass().getName(), "impl-spring-validation-messages", Severity.ERROR, model, message, (Object[])messageParameters);
+ monitor.problem(problem);
+ }
+ }
+
+ protected Class<SpringImplementation> getImplementationClass() {
+ return SpringImplementation.class;
+ }
+
+ /**
+ * Base method which loads the component type from the application-context attached to the
+ * Spring implementation
+ *
+ */
+ public void load(SpringImplementation implementation, ModelResolver resolver, ProcessorContext context) throws ContributionReadException {
+ //System.out.println("Spring TypeLoader - load method start");
+ 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");
+ }
+ if (componentType.isUnresolved()) {
+ /* Fetch the location of the application-context file from the implementation */
+ loadFromXML(implementation, resolver, context);
+ if (!componentType.isUnresolved())
+ implementation.setUnresolved(false);
+ } // end if
+ //System.out.println("Spring TypeLoader - load method complete");
+ } // end method load
+
+ private Class<?> resolveClass(ModelResolver resolver, String className, ProcessorContext context) throws ClassNotFoundException {
+ ClassReference classReference = new ClassReference(className);
+ classReference = resolver.resolveModel(ClassReference.class, classReference, context);
+ if (classReference.isUnresolved()) {
+ throw new ClassNotFoundException(className);
+ }
+ Class<?> javaClass = classReference.getJavaClass();
+ return javaClass;
+ }
+
+ /**
+ * Method which fills out the component type for a Spring implementation by reading the
+ * Spring application-context.xml file.
+ *
+ * @param implementation SpringImplementation into which to load the component type information
+ * @throws ContributionReadException Failed to read the contribution
+ */
+ private void loadFromXML(SpringImplementation implementation, ModelResolver resolver, ProcessorContext context) throws ContributionReadException {
+ XMLStreamReader reader;
+ List<SpringBeanElement> beans = new ArrayList<SpringBeanElement>();
+ List<SpringSCAServiceElement> services = new ArrayList<SpringSCAServiceElement>();
+ List<SpringSCAReferenceElement> references = new ArrayList<SpringSCAReferenceElement>();
+ List<SpringSCAPropertyElement> scaproperties = new ArrayList<SpringSCAPropertyElement>();
+
+ URL resource;
+ List<URL> contextResources = new ArrayList<URL>();
+ String contextPath = implementation.getLocation();
+
+ try {
+ resource = resolveLocation(resolver, contextPath, context);
+ contextResources = getApplicationContextResource(resource);
+
+ implementation.setClassLoader(new ContextClassLoader(resolver, context));
+ implementation.setResource(contextResources);
+ // The URI is used to uniquely identify the Implementation
+ implementation.setURI(resource.toString());
+
+ for (URL contextResource : contextResources) {
+ List<SpringBeanElement> appCxtBeans = new ArrayList<SpringBeanElement>();
+ List<SpringSCAServiceElement> appCxtServices = new ArrayList<SpringSCAServiceElement>();
+ List<SpringSCAReferenceElement> appCxtReferences = new ArrayList<SpringSCAReferenceElement>();
+ List<SpringSCAPropertyElement> appCxtProperties = new ArrayList<SpringSCAPropertyElement>();
+ reader = xmlInputFactory.createXMLStreamReader(contextResource.openStream());
+ // Read the beans, services, references and properties for individual application context
+ readContextDefinition(resolver, reader, contextPath, appCxtBeans, appCxtServices, appCxtReferences, appCxtProperties, context);
+ // Validate the beans from individual application context for uniqueness
+ validateBeans(appCxtBeans, appCxtServices, appCxtReferences, appCxtProperties);
+ // Add all the validated beans to the generic list
+ beans.addAll(appCxtBeans);
+ services.addAll(appCxtServices);
+ references.addAll(appCxtReferences);
+ scaproperties.addAll(appCxtProperties);
+ reader.close();
+ }
+ } catch (IOException e) {
+ throw new ContributionReadException(e);
+ } catch (XMLStreamException e) {
+ throw new ContributionReadException(e);
+ }
+
+ /* At this point, the complete application-context.xml file has been read and its contents */
+ /* stored in the lists of beans, services, references. These are now used to generate */
+ /* the implied componentType for the application context */
+ generateComponentType(implementation, resolver, beans, services, references, scaproperties, context);
+
+ return;
+ } // end method loadFromXML
+
+ private URL resolveLocation(ModelResolver resolver, String contextPath, ProcessorContext context) throws MalformedURLException,
+ ContributionReadException {
+ URL resource = null;
+ URI uri = URI.create(contextPath);
+ if (!uri.isAbsolute()) {
+ Artifact artifact = contributionFactory.createArtifact();
+ artifact.setUnresolved(true);
+ artifact.setURI(contextPath);
+ artifact = resolver.resolveModel(Artifact.class, artifact, context);
+ if (!artifact.isUnresolved()) {
+ resource = new URL(artifact.getLocation());
+ } else {
+ throw new ContributionReadException("Location cannot be resloved: " + contextPath);
+ }
+ } else {
+ resource = new URL(contextPath);
+ }
+ return resource;
+ }
+
+ /**
+ * Method which returns the XMLStreamReader for the Spring application-context.xml file
+ * specified in the location attribute
+ */
+ private XMLStreamReader getApplicationContextReader(ModelResolver resolver, String location, ProcessorContext context) throws ContributionReadException {
+
+ try {
+ URL resource = getApplicationContextResource(resolveLocation(resolver, location, context)).get(0);
+ XMLStreamReader reader =
+ xmlInputFactory.createXMLStreamReader(resource.openStream());
+ return reader;
+ } catch (IOException e) {
+ throw new ContributionReadException(e);
+ } catch (XMLStreamException e) {
+ throw new ContributionReadException(e);
+ }
+ }
+
+ /**
+ * Method which reads the spring context definitions from Spring application-context.xml
+ * file and identifies the defined beans, properties, services and references
+ * @param context
+ */
+ private void readContextDefinition(ModelResolver resolver,
+ XMLStreamReader reader,
+ String contextPath,
+ List<SpringBeanElement> beans,
+ List<SpringSCAServiceElement> services,
+ List<SpringSCAReferenceElement> references,
+ List<SpringSCAPropertyElement> scaproperties, ProcessorContext context) throws ContributionReadException {
+
+ SpringBeanElement bean = null;
+
+ try {
+ boolean completed = false;
+ while (!completed) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ QName qname = reader.getName();
+ //System.out.println("Spring TypeLoader - found element with name: " + qname.toString());
+ if (SpringImplementationConstants.IMPORT_ELEMENT.equals(qname)) {
+ //FIXME - put the sequence of code below which gets the ireader into a subsidiary method
+ String location = reader.getAttributeValue(null, "resource");
+ if (location != null) {
+ // FIXME - need to find a right way of generating this path
+ String resourcePath = contextPath.substring(0, contextPath.lastIndexOf("/")+1) + location;
+ XMLStreamReader ireader = getApplicationContextReader(resolver, resourcePath, context);
+ // Read the context definition for the identified imported resource
+ readContextDefinition(resolver, ireader, contextPath, beans, services, references, scaproperties, context);
+ }
+ } else if (SpringImplementationConstants.SCA_SERVICE_ELEMENT.equals(qname)) {
+ // The value of the @name attribute of an <sca:service/> subelement of a <beans/>
+ // element MUST be unique amongst the <sca:service/> subelements of the <beans/> element.
+ if (!services.isEmpty() && (services.contains(reader.getAttributeValue(null, "name"))))
+ error("ScaServiceNameNotUnique", resolver);
+
+ SpringSCAServiceElement service =
+ new SpringSCAServiceElement(reader.getAttributeValue(null, "name"),
+ reader.getAttributeValue(null, "target"));
+ if (reader.getAttributeValue(null, "type") != null)
+ service.setType(reader.getAttributeValue(null, "type"));
+ policyProcessor.readPolicies(service, reader);
+ services.add(service);
+ } else if (SpringImplementationConstants.SCA_REFERENCE_ELEMENT.equals(qname)) {
+ // The value of the @name attribute of an <sca:reference/> subelement of a <beans/>
+ // element MUST be unique amongst the @name attributes of the <sca:reference/> subelements,
+ // of the <beans/> element.
+ if (!references.isEmpty() && (references.contains(reader.getAttributeValue(null, "name"))))
+ error("ScaReferenceNameNotUnique", resolver);
+
+ SpringSCAReferenceElement reference =
+ new SpringSCAReferenceElement(reader.getAttributeValue(null, "name"),
+ reader.getAttributeValue(null, "type"));
+ if (reader.getAttributeValue(null, "default") != null)
+ reference.setDefaultBean(reader.getAttributeValue(null, "default"));
+ policyProcessor.readPolicies(reference, reader);
+ references.add(reference);
+ } else if (SpringImplementationConstants.SCA_PROPERTY_ELEMENT.equals(qname)) {
+ // The value of the @name attribute of an <sca:property/> subelement of a <beans/>
+ // element MUST be unique amongst the @name attributes of the <sca:property/> subelements,
+ // of the <beans/> element.
+ if (!scaproperties.isEmpty() && (scaproperties.contains(reader.getAttributeValue(null, "name"))))
+ error("ScaPropertyNameNotUnique", resolver);
+
+ SpringSCAPropertyElement scaproperty =
+ new SpringSCAPropertyElement(reader.getAttributeValue(null, "name"), reader
+ .getAttributeValue(null, "type"));
+ scaproperties.add(scaproperty);
+ } else if (SpringImplementationConstants.BEAN_ELEMENT.equals(qname)) {
+ bean = new SpringBeanElement(reader.getAttributeValue(null, "id"),
+ reader.getAttributeValue(null, "class"));
+ if (reader.getAttributeValue(null, "abstract") != null)
+ if (reader.getAttributeValue(null, "abstract").equals("true"))
+ bean.setAbstractBean(true);
+ if (reader.getAttributeValue(null, "parent") != null)
+ if (!reader.getAttributeValue(null, "parent").equals(""))
+ bean.setParentAttribute(true);
+ if (reader.getAttributeValue(null, "factory-bean") != null)
+ if (!reader.getAttributeValue(null, "factory-bean").equals(""))
+ bean.setFactoryBeanAttribute(true);
+ if (reader.getAttributeValue(null, "factory-method") != null)
+ if (!reader.getAttributeValue(null, "factory-method").equals(""))
+ bean.setFactoryMethodAttribute(true);
+ // Set the first name as bean name, when the @id attribute is absent.
+ if (reader.getAttributeValue(null, "id") == null) {
+ if (reader.getAttributeValue(null, "name") != null) {
+ String[] names = (reader.getAttributeValue(null, "name")).split(",");
+ bean.setId(names[0]);
+ }
+ }
+ beans.add(bean);
+ // Read the <bean> element and its child elements
+ readBeanDefinition(reader, bean, beans);
+ } // end if
+ break;
+ case END_ELEMENT:
+ if (SpringImplementationConstants.BEANS_ELEMENT.equals(reader.getName())) {
+ //System.out.println("Spring TypeLoader - finished read of context file");
+ completed = true;
+ break;
+ } // end if
+ } // end switch
+ } // end while
+ } catch (XMLStreamException e) {
+ throw new ContributionReadException(e);
+ }
+ }
+
+
+ /**
+ * Method which reads the bean definitions from Spring application-context.xml file and identifies
+ * the defined beans, properties, services and references
+ */
+ private void readBeanDefinition(XMLStreamReader reader,
+ SpringBeanElement bean,
+ List<SpringBeanElement> beans) throws ContributionReadException {
+
+ SpringBeanElement innerbean = null;
+ SpringPropertyElement property = null;
+ SpringConstructorArgElement constructorArg = null;
+
+ try {
+ boolean completed = false;
+ while (!completed) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ QName qname = reader.getName();
+ if (SpringImplementationConstants.BEAN_ELEMENT.equals(qname)) {
+ innerbean = new SpringBeanElement(reader.getAttributeValue(null, "id"), reader
+ .getAttributeValue(null, "class"));
+ // Set the first name as bean name, when the @id attribute is absent.
+ if (reader.getAttributeValue(null, "id") == null) {
+ if (reader.getAttributeValue(null, "name") != null) {
+ String[] names = (reader.getAttributeValue(null, "name")).split(",");
+ innerbean.setId(names[0]);
+ }
+ }
+ innerbean.setInnerBean(true);
+ beans.add(innerbean);
+ readBeanDefinition(reader, innerbean, beans);
+ } else if (SpringImplementationConstants.PROPERTY_ELEMENT.equals(qname)) {
+ property = new SpringPropertyElement(reader.getAttributeValue(null, "name"));
+ if (reader.getAttributeValue(null, "ref") != null)
+ property.addRef(reader.getAttributeValue(null, "ref"));
+ bean.addProperty(property);
+ } else if (SpringImplementationConstants.CONSTRUCTORARG_ELEMENT.equals(qname)) {
+ constructorArg = new SpringConstructorArgElement(reader.getAttributeValue(null, "type"));
+ if (reader.getAttributeValue(null, "ref") != null)
+ constructorArg.addRef(reader.getAttributeValue(null, "ref"));
+ if (reader.getAttributeValue(null, "index") != null)
+ constructorArg.setIndex((new Integer(reader.getAttributeValue(null, "index"))).intValue());
+ if (reader.getAttributeValue(null, "value") != null)
+ constructorArg.addValue(reader.getAttributeValue(null, "value"));
+ bean.addCustructorArgs(constructorArg);
+ } else if (SpringImplementationConstants.REF_ELEMENT.equals(qname)) {
+ String ref = reader.getAttributeValue(null, "bean");
+ // Check if the parent element is a property
+ if (property != null) property.addRef(ref);
+ // Check if the parent element is a constructor-arg
+ if (constructorArg != null) constructorArg.addRef(ref);
+ } else if (SpringImplementationConstants.VALUE_ELEMENT.equals(qname)) {
+ String value = reader.getElementText();
+ // Check if the parent element is a constructor-arg
+ if (constructorArg != null) constructorArg.addValue(value);
+ } else if (SpringImplementationConstants.LIST_ELEMENT.equals(qname) ||
+ SpringImplementationConstants.SET_ELEMENT.equals(qname) ||
+ SpringImplementationConstants.MAP_ELEMENT.equals(qname)) {
+ if (property != null)
+ readCollections(reader, bean, beans, property, null);
+ if (constructorArg != null)
+ readCollections(reader, bean, beans, null, constructorArg);
+ } // end if
+ break;
+ case END_ELEMENT:
+ if (SpringImplementationConstants.BEAN_ELEMENT.equals(reader.getName())) {
+ completed = true;
+ break;
+ } else if (SpringImplementationConstants.PROPERTY_ELEMENT.equals(reader.getName())) {
+ property = null;
+ } else if (SpringImplementationConstants.CONSTRUCTORARG_ELEMENT.equals(reader.getName())) {
+ constructorArg = null;
+ } // end if
+ } // end switch
+ } // end while
+ } catch (XMLStreamException e) {
+ throw new ContributionReadException(e);
+ }
+ }
+
+
+ /**
+ * Method which reads the collection elements from Spring application-context.xml file and identifies
+ * the defined beans, list, maps and sets
+ */
+ private void readCollections(XMLStreamReader reader,
+ SpringBeanElement bean,
+ List<SpringBeanElement> beans,
+ SpringPropertyElement property,
+ SpringConstructorArgElement constructorArg) throws ContributionReadException {
+
+ SpringBeanElement innerbean = null;
+
+ try {
+ boolean completed = false;
+ while (!completed) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ QName qname = reader.getName();
+ if (SpringImplementationConstants.BEAN_ELEMENT.equals(qname)) {
+ innerbean = new SpringBeanElement(reader.getAttributeValue(null, "id"), reader
+ .getAttributeValue(null, "class"));
+ // Set the first name as bean name, when the @id attribute is absent.
+ if (reader.getAttributeValue(null, "id") == null)
+ if (reader.getAttributeValue(null, "name") != null) {
+ String[] names = (reader.getAttributeValue(null, "name")).split(",");
+ innerbean.setId(names[0]);
+ }
+ innerbean.setInnerBean(true);
+ beans.add(innerbean);
+ readBeanDefinition(reader, innerbean, beans);
+ } else if (SpringImplementationConstants.REF_ELEMENT.equals(qname)) {
+ String ref = reader.getAttributeValue(null, "bean");
+ if (property != null) property.addRef(ref);
+ if (constructorArg != null) constructorArg.addRef(ref);
+ } else if (SpringImplementationConstants.LIST_ELEMENT.equals(qname) ||
+ SpringImplementationConstants.SET_ELEMENT.equals(qname) ||
+ SpringImplementationConstants.MAP_ELEMENT.equals(qname)) {
+ if (property != null)
+ readCollections(reader, innerbean, beans, property, null);
+ if (constructorArg != null)
+ readCollections(reader, innerbean, beans, null, constructorArg);
+ } else if (SpringImplementationConstants.ENTRY_ELEMENT.equals(qname)) {
+ String keyRef = reader.getAttributeValue(null, "key-ref");
+ String valueRef = reader.getAttributeValue(null, "value-ref");
+ if (property != null) {property.addRef(keyRef); property.addRef(valueRef);}
+ if (constructorArg != null) {constructorArg.addRef(keyRef); constructorArg.addRef(valueRef);}
+ } // end if
+ break;
+ case END_ELEMENT:
+ if (SpringImplementationConstants.LIST_ELEMENT.equals(reader.getName())) {
+ completed = true;
+ break;
+ } else if (SpringImplementationConstants.SET_ELEMENT.equals(reader.getName())) {
+ completed = true;
+ break;
+ } else if (SpringImplementationConstants.MAP_ELEMENT.equals(reader.getName())) {
+ completed = true;
+ break;
+ } // end if
+ } // end switch
+ } // end while
+ } catch (XMLStreamException e) {
+ throw new ContributionReadException(e);
+ }
+ }
+
+ /**
+ * Generates the Spring implementation component type from the configuration contained in the
+ * lists of beans, services, references and scaproperties derived from the application context
+ */
+ private void generateComponentType(SpringImplementation implementation,
+ ModelResolver resolver,
+ List<SpringBeanElement> beans,
+ List<SpringSCAServiceElement> services,
+ List<SpringSCAReferenceElement> references,
+ List<SpringSCAPropertyElement> scaproperties,
+ ProcessorContext context) throws ContributionReadException {
+ /*
+ * 1. Each sca:service becomes a service in the component type
+ * 2. Each sca:reference becomes a reference in the component type
+ * 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
+ * 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 {
+ // Deal with the services first....
+ Iterator<SpringSCAServiceElement> its = services.iterator();
+ while (its.hasNext()) {
+ SpringSCAServiceElement serviceElement = its.next();
+ Class<?> interfaze = resolveClass(resolver, serviceElement.getType(), context);
+ Service theService = createService(interfaze, serviceElement.getName());
+ // Spring allows duplication of bean definitions in multiple context scenario,
+ // in such cases, the latest bean definition overrides the older ones, hence
+ // we will remove any older definition and use the latest.
+ Service duplicate = null;
+ for (Service service : componentType.getServices()) {
+ if (service.getName().equals(theService.getName()))
+ duplicate = service;
+ }
+ if (duplicate != null)
+ componentType.getServices().remove(duplicate);
+
+ componentType.getServices().add(theService);
+ // Add this service to the Service / Bean map
+ String beanName = serviceElement.getTarget();
+ for (SpringBeanElement beanElement : beans) {
+ if (beanName.equals(beanElement.getId())) {
+ if (isvalidBeanForService(beanElement)) {
+ // add the required intents and policySets for the service
+ theService.getRequiredIntents().addAll(serviceElement.getRequiredIntents());
+ theService.getPolicySets().addAll(serviceElement.getPolicySets());
+ implementation.setBeanForService(theService, beanElement);
+ }
+ }
+ } // end for
+ } // end while
+
+ // Next handle the references
+ Iterator<SpringSCAReferenceElement> itr = references.iterator();
+ while (itr.hasNext()) {
+ SpringSCAReferenceElement referenceElement = itr.next();
+ Class<?> interfaze = resolveClass(resolver, referenceElement.getType(), context);
+ Reference theReference = createReference(interfaze, referenceElement.getName());
+ // Override the older bean definition with the latest ones
+ // for the duplicate definitions found.
+ Reference duplicate = null;
+ for (Reference reference : componentType.getReferences()) {
+ if (reference.getName().equals(theReference.getName()))
+ duplicate = reference;
+ }
+ if (duplicate != null)
+ componentType.getReferences().remove(duplicate);
+
+ // add the required intents and policySets for this reference
+ theReference.getRequiredIntents().addAll(referenceElement.getRequiredIntents());
+ theReference.getPolicySets().addAll(referenceElement.getPolicySets());
+ 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));
+ // Override the older bean definition with the latest ones
+ // for the duplicate definitions found.
+ Property duplicate = null;
+ for (Property property : componentType.getProperties()) {
+ if (property.getName().equals(theProperty.getName()))
+ duplicate = property;
+ }
+ if (duplicate != null)
+ componentType.getProperties().remove(duplicate);
+
+ 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;
+ // If there are no explicit service elements, then expose all the beans
+ if (services.isEmpty()) {
+ itb = beans.iterator();
+ // Loop through all the beans found
+ while (itb.hasNext()) {
+ SpringBeanElement beanElement = itb.next();
+ // If its not a valid bean for service, ignore it
+ if (!isvalidBeanForService(beanElement)) continue;
+ // Load the Spring bean class
+ Class<?> beanClass = resolveClass(resolver, beanElement.getClassName(), context);
+ // Introspect the bean
+ beanIntrospector =
+ new SpringBeanIntrospector(registry, beanElement.getCustructorArgs());
+ ComponentType beanComponentType = assemblyFactory.createComponentType();
+ javaImplementation = beanIntrospector.introspectBean(beanClass, beanComponentType);
+ // Set the service name as bean name
+ for (Service componentService : beanComponentType.getServices())
+ componentService.setName(beanElement.getId());
+ // Get the service interface defined by this Spring Bean and add to
+ // the component type of the Spring Assembly
+ List<Service> beanServices = beanComponentType.getServices();
+ componentType.getServices().addAll(beanServices);
+ // Add these services to the Service / Bean map
+ for (Service beanService : beanServices) {
+ implementation.setBeanForService(beanService, beanElement);
+ }
+ } // end while
+ } // end if
+
+ 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 = resolveClass(resolver, beanElement.getClassName(), context);
+ // Introspect the bean
+ beanIntrospector =
+ new SpringBeanIntrospector(registry, beanElement.getCustructorArgs());
+ 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();
+ for (String propertyRef : propertyElement.getRefs()) {
+ if (propertyRefUnresolved(propertyRef, 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(propertyRef);
+ 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 = resolveClass(resolver, (propertyMap.get(propertyElement.getName()).getType()).getName(), context);
+ Reference theReference = createReference(interfaze, propertyRef);
+ implementation.setUnresolvedBeanRef(propertyRef, theReference);
+ } // end if
+ } // end for
+ } // end if
+ } // end for
+ } // end while
+
+ Iterator<SpringConstructorArgElement> itcr = beanElement.getCustructorArgs().iterator();
+ while (itcr.hasNext()) {
+ SpringConstructorArgElement conArgElement = itcr.next();
+ for (String constructorArgRef : conArgElement.getRefs()) {
+ if (propertyRefUnresolved(constructorArgRef, beans, references, scaproperties)) {
+ for (JavaParameterImpl parameter : constructor.getParameters()) {
+ String paramType = parameter.getType().getName();
+ Class<?> interfaze = resolveClass(resolver, paramType, context);
+ // Create a component type reference/property if the constructor-arg element has a
+ // type attribute OR index attribute declared...
+ if ((conArgElement.getType() != null && paramType.equals(conArgElement.getType())) ||
+ (conArgElement.getIndex() != -1 && (conArgElement.getIndex() == parameter.getIndex())))
+ {
+ if (parameter.getClassifer().getName().equals("org.osoa.sca.annotations.Reference")) {
+ Reference theReference = createReference(interfaze, constructorArgRef);
+ componentType.getReferences().add(theReference);
+ }
+ if (parameter.getClassifer().getName().equals("org.osoa.sca.annotations.Property")) {
+ // Store the unresolved references as unresolvedBeanRef in the Spring Implementation type
+ // we might need to verify with the component definition later.
+ Reference theReference = createReference(interfaze, constructorArgRef);
+ implementation.setUnresolvedBeanRef(constructorArgRef, theReference);
+ }
+ }
+ } // end for
+ } // end if
+ } // end for
+ } // end while
+
+ } // end while
+
+ } catch (ClassNotFoundException e) {
+ // Means that either an interface class, property class or a bean was not found
+ throw new ContributionReadException(e);
+ } catch (InvalidInterfaceException e) {
+ throw new ContributionReadException(e);
+ } catch (ContributionResolveException e) {
+
+ } // end try
+
+ // If we get here, the Spring assembly component type is resolved
+ componentType.setUnresolved(false);
+ implementation.setComponentType(componentType);
+ return;
+ } // end method generateComponentType
+
+ /*
+ * Determines whether a reference attribute of a Spring property element is resolved either
+ * by a bean in the application context or by an SCA reference element or by an SCA property
+ * element
+ * @param ref - a String containing the name of the reference - may be null
+ * @param beans - a List of SpringBean elements
+ * @param references - a List of SCA reference elements
+ * @return true if the property is not resolved, false if it is resolved
+ */
+ private boolean propertyRefUnresolved(String ref,
+ List<SpringBeanElement> beans,
+ List<SpringSCAReferenceElement> references,
+ List<SpringSCAPropertyElement> scaproperties) {
+ boolean unresolved = true;
+
+ if (ref != null) {
+ // Scan over the beans looking for a match
+ Iterator<SpringBeanElement> itb = beans.iterator();
+ while (itb.hasNext()) {
+ SpringBeanElement beanElement = itb.next();
+ // Does the bean name match the ref?
+ if (ref.equals(beanElement.getId())) {
+ unresolved = false;
+ break;
+ } // end if
+ } // end while
+ // Scan over the SCA reference elements looking for a match
+ if (unresolved) {
+ Iterator<SpringSCAReferenceElement> itr = references.iterator();
+ while (itr.hasNext()) {
+ SpringSCAReferenceElement referenceElement = itr.next();
+ if (ref.equals(referenceElement.getName())) {
+ unresolved = false;
+ break;
+ } // end if
+ } // end while
+ } // end if
+ // Scan over the SCA property elements looking for a match
+ if (unresolved) {
+ Iterator<SpringSCAPropertyElement> itsp = scaproperties.iterator();
+ while (itsp.hasNext()) {
+ SpringSCAPropertyElement propertyElement = itsp.next();
+ if (ref.equals(propertyElement.getName())) {
+ unresolved = false;
+ break;
+ } // end if
+ } // end while
+ } // end if
+ } else {
+ // In the case where ref = null, the property is not going to be a reference of any
+ // kind and can be ignored
+ unresolved = false;
+ } // end if
+
+ return unresolved;
+
+ } // end method propertyRefUnresolved
+
+ /**
+ * Validates whether the <sca:service>, <sca:reference> and <sca:property> elements
+ * has unique names within the application context.
+ */
+ private void validateBeans(List<SpringBeanElement> beans,
+ List<SpringSCAServiceElement> services,
+ List<SpringSCAReferenceElement> references,
+ List<SpringSCAPropertyElement> scaproperties) throws ContributionReadException {
+
+ // The @target attribute of a <service/> subelement of a <beans/> element
+ // MUST have the value of the @name attribute of one of the <bean/>
+ // subelements of the <beans/> element.
+ Iterator<SpringSCAServiceElement> its = services.iterator();
+ while (its.hasNext()) {
+ SpringSCAServiceElement serviceElement = its.next();
+ boolean targetBeanExists = false;
+ Iterator<SpringBeanElement> itb = beans.iterator();
+ while (itb.hasNext()) {
+ SpringBeanElement beanElement = itb.next();
+ if (serviceElement.getTarget().equals(beanElement.getId()))
+ targetBeanExists = true;
+ }
+ if (!targetBeanExists)
+ error("TargetBeanDoesNotExist", beans);
+ } // end while
+
+ // The value of the @name attribute of an <sca:reference/> subelement of a <beans/>
+ // element MUST be unique amongst the @name attributes of the <sca:property/>
+ // subelements and the <bean/> subelements of the <beans/> element.
+ // AND
+ // The @default attribute of a <sca:reference/> subelement of a <beans/>
+ // element MUST have the value of the @name attribute of one of the <bean/>
+ // subelements of the <beans/> element.
+ Iterator<SpringSCAReferenceElement> itr = references.iterator();
+ while (itr.hasNext()) {
+ SpringSCAReferenceElement referenceElement = itr.next();
+ boolean defaultBeanExists = true;
+ boolean isUniqueReferenceName = true;
+ Iterator<SpringBeanElement> itb = beans.iterator();
+ while (itb.hasNext()) {
+ SpringBeanElement beanElement = itb.next();
+ if (referenceElement.getDefaultBean() != null)
+ if (referenceElement.getDefaultBean().equals(beanElement.getId()))
+ defaultBeanExists = false;
+ if (referenceElement.getName().equals(beanElement.getId()))
+ isUniqueReferenceName = false;
+ }
+ Iterator<SpringSCAPropertyElement> itp = scaproperties.iterator();
+ while (itp.hasNext()) {
+ SpringSCAPropertyElement propertyElement = itp.next();
+ if (referenceElement.getName().equals(propertyElement.getName()))
+ isUniqueReferenceName = false;
+ }
+ if (!defaultBeanExists)
+ error("DefaultBeanDoesNotExist", beans);
+ if (!isUniqueReferenceName)
+ error("ScaReferenceNameNotUnique", beans);
+ } // end while
+
+ // The value of the @name attribute of an <sca:property/> subelement of a <beans/>
+ // element MUST be unique amongst the @name attributes of the <sca:reference/>
+ // subelements and the <bean/> subelements of the <beans/> element.
+ Iterator<SpringSCAPropertyElement> itp = scaproperties.iterator();
+ while (itp.hasNext()) {
+ SpringSCAPropertyElement propertyElement = itp.next();
+ boolean isUniquePropertyName = true;
+ Iterator<SpringBeanElement> itb = beans.iterator();
+ while (itb.hasNext()) {
+ SpringBeanElement beanElement = itb.next();
+ if (propertyElement.getName().equals(beanElement.getId()))
+ isUniquePropertyName = false;
+ }
+ Iterator<SpringSCAReferenceElement> itrp = references.iterator();
+ while (itrp.hasNext()) {
+ SpringSCAReferenceElement referenceElement = itrp.next();
+ if (propertyElement.getName().equals(referenceElement.getName()))
+ isUniquePropertyName = false;
+ }
+ if (!isUniquePropertyName)
+ error("ScaPropertyNameNotUnique", beans);
+ } // end while
+ }
+
+ /**
+ * Validates whether a bean definition is valid for exposing as service.
+ */
+ private boolean isvalidBeanForService(SpringBeanElement beanElement) {
+
+ if (beanElement.isInnerBean())
+ return false;
+ if (beanElement.hasParentAttribute())
+ return false;
+ if (beanElement.hasFactoryMethodAttribute())
+ return false;
+ if (beanElement.hasFactoryBeanAttribute())
+ return false;
+ if (beanElement.getClassName() == null)
+ return false;
+ if (beanElement.getClassName().startsWith("org.springframework"))
+ return false;
+ // return true otherwise
+ return true;
+ }
+
+
+ /**
+ * Gets hold of the application-context.xml file as a Spring resource
+ * @param locationAttr - the location attribute from the <implementation.spring../> element
+ * @param cl - the ClassLoader for the Spring implementation
+ */
+ protected List<URL> getApplicationContextResource(URL url)
+ throws ContributionReadException {
+ File manifestFile = null;
+ File appXmlFile;
+ File appXmlFolder;
+ File locationFile = null;
+ List<URL> appCtxResources = new ArrayList<URL>();
+
+ if (url != null) {
+ String path = url.getPath();
+ locationFile = new File(path);
+ } else {
+ throw new ContributionReadException("SpringXMLComponentTypeLoader getApplicationContextResource: "
+ + "unable to find resource file " + url);
+ }
+
+ if (locationFile.isDirectory()) {
+ try {
+ manifestFile = new File(locationFile, "META-INF"+ File.separator +"MANIFEST.MF");
+ if (manifestFile.exists()) {
+ Manifest mf = new Manifest(new FileInputStream(manifestFile));
+ Attributes mainAttrs = mf.getMainAttributes();
+ String appCtxPath = mainAttrs.getValue("Spring-Context");
+ if (appCtxPath != null) {
+ String[] cxtPaths = appCtxPath.split(";");
+ for (String path : cxtPaths) {
+ appXmlFile = new File(locationFile, path.trim());
+ if (appXmlFile.exists()) {
+ appCtxResources.add(appXmlFile.toURI().toURL());
+ }
+ }
+ return appCtxResources;
+ }
+ }
+ // No MANIFEST.MF file OR no manifest-specified Spring context , then read all the
+ // xml files available in the META-INF/spring folder.
+ appXmlFolder = new File(locationFile, "META-INF" + File.separator + "spring");
+ if (appXmlFolder.exists()) {
+ File[] files = appXmlFolder.listFiles();
+ for (File appFile: files) {
+ if (appFile.getName().endsWith(".xml")) {
+ appCtxResources.add(appFile.toURI().toURL());
+ }
+ }
+ return appCtxResources;
+ }
+ } catch (IOException e) {
+ throw new ContributionReadException("Error reading manifest " + manifestFile);
+ }
+ } else {
+ if (locationFile.isFile() && locationFile.getName().endsWith(".jar")) {
+ try {
+ JarFile jf = new JarFile(locationFile);
+ JarEntry je;
+ Manifest mf = jf.getManifest();
+ if (mf != null) {
+ Attributes mainAttrs = mf.getMainAttributes();
+ String appCtxPath = mainAttrs.getValue("Spring-Context");
+ if (appCtxPath != null) {
+ String[] cxtPaths = appCtxPath.split(";");
+ for (String path : cxtPaths) {
+ je = jf.getJarEntry(path.trim());
+ if (je != null)
+ appCtxResources.add(new URL("jar:" + locationFile.toURI().toURL() + "!/" + appCtxPath));
+ }
+ return appCtxResources;
+ }
+ }
+ // No MANIFEST.MF file OR no manifest-specified Spring context , then read all the
+ // .xml files available in the META-INF/spring folder.
+ Enumeration<JarEntry> entries = jf.entries();
+ while (entries.hasMoreElements()) {
+ je = entries.nextElement();
+ if (je.getName().startsWith("META-INF/spring/") && je.getName().endsWith(".xml")) {
+ appCtxResources.add(new URL("jar:" + locationFile.toURI().toURL() + "!/" + je.getName()));
+ }
+ }
+ return appCtxResources;
+ } catch (IOException e) {
+ // TODO: create a more appropriate exception type
+ throw new ContributionReadException("SpringXMLComponentTypeLoader getApplicationContextResource: "
+ + " IO exception reading context file.", e);
+ }
+ }
+ else {
+ if (locationFile.getName().endsWith(".xml")) {
+ appCtxResources.add(url);
+ return appCtxResources;
+ }
+ else {
+ // Deal with the directory inside a jar file, in case the contribution itself is a JAR file.
+ try {
+ if (locationFile.getPath().indexOf(".jar") > 0) {
+ String jarPath = url.getPath().substring(5, url.getPath().indexOf("!"));
+ JarFile jf = new JarFile(jarPath);
+ JarEntry je = jf.getJarEntry(url.getPath().substring(url.getPath().indexOf("!/")+2)
+ + "/" + "META-INF" + "/" + "MANIFEST.MF");
+ if (je != null) {
+ Manifest mf = new Manifest(jf.getInputStream(je));
+ Attributes mainAttrs = mf.getMainAttributes();
+ String appCtxPath = mainAttrs.getValue("Spring-Context");
+ if (appCtxPath != null) {
+ String[] cxtPaths = appCtxPath.split(";");
+ for (String path : cxtPaths) {
+ je = jf.getJarEntry(url.getPath().substring(url.getPath().indexOf("!/")+2) + "/" + path.trim());
+ if (je != null) {
+ appCtxResources.add(new URL("jar:" + url.getPath() + "/" + path.trim()));
+ }
+ }
+ return appCtxResources;
+ }
+ }
+ // No MANIFEST.MF file OR no manifest-specified Spring context , then read all the
+ // .xml files available in the META-INF/spring folder.
+ Enumeration<JarEntry> entries = jf.entries();
+ while (entries.hasMoreElements()) {
+ je = entries.nextElement();
+ if (je.getName().startsWith("META-INF/spring/") && je.getName().endsWith(".xml")) {
+ appCtxResources.add(new URL("jar:" + url.getPath() + "/" + je.getName()));
+ }
+ }
+ return appCtxResources;
+ }
+ } catch (IOException e) {
+ throw new ContributionReadException("Error reading manifest " + manifestFile);
+ }
+ }
+ }
+ }
+
+ throw new ContributionReadException("SpringXMLComponentTypeLoader getApplicationContextResource: "
+ + "unable to read resource file " + url);
+ } // end method getApplicationContextResource
+
+ /**
+ * Creates a Service for the component type based on its name and Java interface
+ */
+ public Service createService(Class<?> interfaze, String name) throws InvalidInterfaceException {
+ Service service = assemblyFactory.createService();
+ JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract();
+ service.setInterfaceContract(interfaceContract);
+
+ // Set the name for the service
+ service.setName(name);
+
+ // Set the call interface and, if present, the callback interface
+ JavaInterface callInterface = javaFactory.createJavaInterface(interfaze);
+ service.getInterfaceContract().setInterface(callInterface);
+ if (callInterface.getCallbackClass() != null) {
+ JavaInterface callbackInterface = javaFactory.createJavaInterface(callInterface.getCallbackClass());
+ service.getInterfaceContract().setCallbackInterface(callbackInterface);
+ }
+ return service;
+ } // end method createService
+
+ /**
+ * Creates a Reference for the component type based on its name and Java interface
+ */
+ private org.apache.tuscany.sca.assembly.Reference createReference(Class<?> interfaze, String name)
+ throws InvalidInterfaceException {
+ org.apache.tuscany.sca.assembly.Reference reference = assemblyFactory.createReference();
+ JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract();
+ reference.setInterfaceContract(interfaceContract);
+
+ // Set the name of the reference to the supplied name and the multiplicity of the reference
+ // to 1..1 - for Spring implementations, this is the only multiplicity supported
+ reference.setName(name);
+ reference.setMultiplicity(Multiplicity.ONE_ONE);
+
+ // Set the call interface and, if present, the callback interface
+ JavaInterface callInterface = javaFactory.createJavaInterface(interfaze);
+ reference.getInterfaceContract().setInterface(callInterface);
+ if (callInterface.getCallbackClass() != null) {
+ JavaInterface callbackInterface = javaFactory.createJavaInterface(callInterface.getCallbackClass());
+ reference.getInterfaceContract().setCallbackInterface(callbackInterface);
+ }
+
+ return reference;
+ }
+
+ private class ContextClassLoader extends ClassLoader {
+ public ContextClassLoader(ModelResolver resolver, ProcessorContext context) {
+ super();
+ this.resolver = resolver;
+ this.context = context;
+ }
+
+ private ModelResolver resolver;
+ private ProcessorContext context;
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ return SpringXMLComponentTypeLoader.this.resolveClass(resolver, name, context);
+ }
+
+ @Override
+ protected URL findResource(String name) {
+ try {
+ return resolveLocation(resolver, name, context);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ @Override
+ protected Enumeration<URL> findResources(String name) throws IOException {
+ URL url = findResource(name);
+ if (url != null) {
+ return Collections.enumeration(Arrays.asList(url));
+ } else {
+ Collection<URL> urls = Collections.emptyList();
+ return Collections.enumeration(urls);
+ }
+ }
+ }
+} // end class SpringXMLComponentTypeLoader \ No newline at end of file
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/ComponentTie.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/ComponentTie.java
new file mode 100644
index 0000000000..b97c02d216
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/ComponentTie.java
@@ -0,0 +1,41 @@
+/*
+ * 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.invocation;
+
+/**
+ * This is the Tuscany side tie for the corresponding Spring runtime side stub class.
+ * It enables the Tuscany code to invoke methods on a Spring context without
+ * needing to know about any Spring classes. See the ComponentStub class
+ * in the implementation-spring-runtime module for what the stub does.
+ */
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+public class ComponentTie {
+
+ private RuntimeComponent component;
+
+ public ComponentTie(RuntimeComponent component) {
+ this.component = component;
+ }
+
+ public Object getService(Class<?> type, String name) {
+ return component.getComponentContext().getService(type, name);
+ }
+}
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/PropertyValueTie.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/PropertyValueTie.java
new file mode 100644
index 0000000000..89d14961ac
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/PropertyValueTie.java
@@ -0,0 +1,53 @@
+/*
+ * 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.invocation;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.ComponentProperty;
+import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * This is the Tuscany side tie for the corresponding Spring runtime side stub class.
+ * It enables the Tuscany code to invoke methods on a Spring context without
+ * needing to know about any Spring classes. See the PropertyValueStub class
+ * in the implementation-spring-runtime module for what the stub does.
+ */
+public class PropertyValueTie {
+
+ private RuntimeComponent component;
+ private JavaPropertyValueObjectFactory propertyFactory;
+
+ public PropertyValueTie(RuntimeComponent component, JavaPropertyValueObjectFactory propertyFactory) {
+ this.component = component;
+ this.propertyFactory = propertyFactory;
+ }
+
+ public Object getPropertyObj(Class<?> type, String name) {
+ List<ComponentProperty> props = component.getProperties();
+ for (ComponentProperty prop : props) {
+ if (prop.getName().equals(name)) {
+ return propertyFactory.createValueFactory(prop, prop.getValue(), type).getInstance();
+ }
+ }
+ return null; // property name not found
+ }
+}
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringContextStub.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringContextStub.java
new file mode 100644
index 0000000000..dcb9a53a33
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringContextStub.java
@@ -0,0 +1,134 @@
+/*
+ * 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.invocation;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+
+import org.apache.tuscany.sca.core.invocation.ProxyFactory;
+import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory;
+import org.apache.tuscany.sca.implementation.spring.SpringImplementation;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * This is the Tuscany side stub for the corresponding runtime tie class.
+ * It enables the Tuscany code to invoke methods on a Spring context without
+ * needing to know about any Spring classes. See the SpringContextTie class
+ * in the implementation-spring-runtime module for what the tie does.
+ */
+public class SpringContextStub {
+
+ private Object tie;
+ private Method startMethod;
+ private Method closeMethod;
+ private Method getBeanMethod;
+
+ public SpringContextStub(RuntimeComponent component,
+ SpringImplementation implementation,
+ ProxyFactory proxyService,
+ JavaPropertyValueObjectFactory propertyValueObjectFactory) {
+
+ initTie(component, implementation, propertyValueObjectFactory);
+
+ }
+
+ private void initTie(RuntimeComponent component,
+ SpringImplementation implementation,
+ JavaPropertyValueObjectFactory propertyValueObjectFactory) {
+
+ // TODO: what class loader to use?
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+
+ try {
+
+ Class<?> stubClass = Class.forName("org.apache.tuscany.sca.implementation.spring.runtime.context.SpringImplementationStub", true, cl);
+ Constructor<?> stubConstructor = stubClass.getConstructor(new Class<?>[]{Object.class});
+ Object stub = stubConstructor.newInstance(new SpringImplementationTie(implementation, component, propertyValueObjectFactory));
+
+ Class<?> tieClass = Class.forName("org.apache.tuscany.sca.implementation.spring.runtime.context.SpringContextTie", true, cl);
+ Constructor<?> tieConstructor = tieClass.getConstructor(new Class<?>[]{stubClass, List.class});
+ this.tie = tieConstructor.newInstance(stub, implementation.getResource());
+
+ this.startMethod = tieClass.getMethod("start");
+ this.closeMethod = tieClass.getMethod("close");
+ this.getBeanMethod = tieClass.getMethod("getBean", String.class);
+
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ } catch (SecurityException e) {
+ throw new RuntimeException(e);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException(e);
+ } catch (InstantiationException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void start() {
+ try {
+ startMethod.invoke(tie);
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void close() {
+ try {
+ closeMethod.invoke(tie);
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
+ public Object getBean(String id) throws SpringInvocationException {
+ try {
+
+ return getBeanMethod.invoke(tie, id);
+
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringImplementationProvider.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringImplementationProvider.java
new file mode 100644
index 0000000000..0ecd00d5a8
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringImplementationProvider.java
@@ -0,0 +1,85 @@
+/*
+ * 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.invocation;
+
+import org.apache.tuscany.sca.core.invocation.ProxyFactory;
+import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory;
+import org.apache.tuscany.sca.implementation.spring.SpringImplementation;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.provider.ImplementationProvider;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+
+/**
+ * A provider class for runtime Spring implementation instances
+ * @version $Rev$ $Date$
+ */
+public class SpringImplementationProvider implements ImplementationProvider {
+ private RuntimeComponent component;
+
+ // A Spring application context object
+ private SpringContextStub springContext;
+
+ private SpringImplementation implementation;
+
+ private JavaPropertyValueObjectFactory propertyValueObjectFactory;
+
+ /**
+ * Constructor for the provider - takes a component definition and a Spring implementation
+ * description
+ * @param component - the component in the assembly
+ * @param implementation - the implementation
+ */
+ public SpringImplementationProvider(RuntimeComponent component,
+ SpringImplementation implementation,
+ ProxyFactory proxyService,
+ JavaPropertyValueObjectFactory propertyValueObjectFactory) {
+ super();
+ this.implementation = implementation;
+ this.component = component;
+ this.propertyValueObjectFactory = propertyValueObjectFactory;
+
+ springContext = new SpringContextStub(component, implementation, proxyService, propertyValueObjectFactory);
+
+ } // end constructor
+
+ public Invoker createInvoker(RuntimeComponentService service, Operation operation) {
+ return new SpringInvoker(component, springContext, service, operation);
+ }
+
+ public boolean supportsOneWayInvocation() {
+ return false;
+ }
+
+ /**
+ * Start this Spring implementation instance
+ */
+ public void start() {
+ springContext.start();
+ }
+
+ /**
+ * Stop this implementation instance
+ */
+ public void stop() {
+ springContext.close();
+ }
+
+} // end class SpringImplementationProvider
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringImplementationProviderFactory.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringImplementationProviderFactory.java
new file mode 100644
index 0000000000..5dfdbffd84
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringImplementationProviderFactory.java
@@ -0,0 +1,77 @@
+/*
+ * 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.invocation;
+
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory;
+import org.apache.tuscany.sca.core.invocation.ProxyFactory;
+import org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint;
+import org.apache.tuscany.sca.databinding.impl.MediatorImpl;
+import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory;
+import org.apache.tuscany.sca.implementation.spring.SpringImplementation;
+import org.apache.tuscany.sca.provider.ImplementationProvider;
+import org.apache.tuscany.sca.provider.ImplementationProviderFactory;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * ImplementationProviderFactory for Spring implementation type
+ * @version $Rev$ $Date$
+ *
+ */
+public class SpringImplementationProviderFactory implements ImplementationProviderFactory<SpringImplementation> {
+
+ private ProxyFactory proxyFactory;
+ private JavaPropertyValueObjectFactory propertyFactory;
+
+ /**
+ * Simple constructor
+ *
+ */
+ public SpringImplementationProviderFactory(ExtensionPointRegistry extensionPoints) {
+ super();
+
+ ProxyFactoryExtensionPoint proxyFactories = extensionPoints.getExtensionPoint(ProxyFactoryExtensionPoint.class);
+ proxyFactory = new ExtensibleProxyFactory(proxyFactories);
+
+ // TODO: could the runtime have a default PropertyValueObjectFactory?
+ propertyFactory = new JavaPropertyValueObjectFactory(new MediatorImpl(extensionPoints));
+ }
+
+ /**
+ * Returns a SpringImplementationProvider for a given component and Spring implementation
+ * @param component the component for which implementation instances are required
+ * @param implementation the Spring implementation with details of the component
+ * implementation
+ * @return the SpringImplementationProvider for the specified component
+ */
+ public ImplementationProvider createImplementationProvider(RuntimeComponent component,
+ SpringImplementation implementation) {
+ return new SpringImplementationProvider(component,
+ implementation,
+ proxyFactory,
+ propertyFactory);
+ }
+
+ /**
+ * Returns the class of the Spring implementation
+ */
+ public Class<SpringImplementation> getModelType() {
+ return SpringImplementation.class;
+ }
+} // end class SpringImplementationProviderFactory
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringImplementationTie.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringImplementationTie.java
new file mode 100644
index 0000000000..6caa5207e4
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringImplementationTie.java
@@ -0,0 +1,147 @@
+/*
+ * 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.invocation;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.ComponentProperty;
+import org.apache.tuscany.sca.assembly.Property;
+import org.apache.tuscany.sca.assembly.Reference;
+import org.apache.tuscany.sca.core.factory.ObjectFactory;
+import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory;
+import org.apache.tuscany.sca.implementation.spring.SpringImplementation;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+
+/**
+ * This is the Tuscany side tie for the corresponding runtime stub class.
+ * It enables the Sping code in the runtime module to invoke methods on a
+ * Tuscany SpringImplementation without the Spring runtime module
+ * needing to know about any Tuscany classes. See the SpringImplementationStub class
+ * in the implementation-spring-runtime module for what the stub does.
+ */
+public class SpringImplementationTie {
+
+ private SpringImplementation implementation;
+ private RuntimeComponent component;
+ private JavaPropertyValueObjectFactory propertyFactory;
+
+ public SpringImplementationTie(SpringImplementation implementation, RuntimeComponent component, JavaPropertyValueObjectFactory propertyFactory) {
+ this.implementation = implementation;
+ this.component = component;
+ this.propertyFactory = propertyFactory;
+ }
+
+ public String getURI() {
+ throw new IllegalStateException("Not yet impl");
+ }
+
+ public String getComponentName() {
+ return component.getName();
+ }
+ /**
+ * Method to create a Java Bean for a Property value
+ * @param <B> the class type of the Bean
+ * @param requiredType - a Class object for the required type
+ * @param name - the Property name
+ * @return - a Bean of the specified property, with value set
+ */
+ private <B> B getPropertyBean(Class<?> requiredType, String name) {
+ B propertyObject = null;
+ // Get the component's list of properties
+ List<ComponentProperty> props = component.getProperties();
+ for (ComponentProperty prop : props) {
+ if (prop.getName().equals(name)) {
+ // On finding the property, create a factory for it and create a Bean using
+ // the factory
+ ObjectFactory<?> factory = propertyFactory.createValueFactory(prop, prop.getValue(), requiredType);
+ propertyObject = (B)factory.getInstance();
+ } // end if
+ } // end for
+
+ return propertyObject;
+ }
+
+ /**
+ * Creates a proxy Bean for a reference
+ * @param <B> the Business interface type for the reference
+ * @param businessInterface - the business interface as a Class
+ * @param referenceName - the name of the Reference
+ * @return an Bean of the type defined by <B>
+ */
+ private <B> B getService(Class<B> businessInterface, String referenceName) {
+ return component.getComponentContext().getService(businessInterface, referenceName);
+ }
+
+ /**
+ * Get a Bean for a reference or for a property.
+ *
+ * @param name - the name of the Bean required
+ * @param requiredType - the required type of the Bean (either a Java class or a Java interface)
+ * @return Object - a Bean which matches the requested bean
+ */
+ public Object getBean(String name, Class<?> requiredType) {
+ // The expectation is that the requested Bean is either a reference or a property
+ // from the Spring context
+ for (Reference reference : implementation.getReferences()) {
+ if (reference.getName().equals(name)) {
+ // Extract the Java interface for the reference (it can't be any other interface type
+ // for a Spring application context)
+ if (requiredType == null) {
+ JavaInterface javaInterface = (JavaInterface)reference.getInterfaceContract().getInterface();
+ requiredType = javaInterface.getJavaClass();
+ }
+ // Create and return the proxy for the reference
+ return getService(requiredType, reference.getName());
+ } // end if
+ } // end for
+
+ // For a property, get the name and the required Java type and create a Bean
+ // of that type with the value inserted.
+ for (Property property : implementation.getProperties()) {
+ if (property.getName().equals(name)) {
+ if (requiredType == null) {
+ // The following code only deals with a subset of types and was superceded
+ // by the information from the implementation (which uses Classes as found
+ // in the Spring implementation itself.
+ //requiredType = JavaXMLMapper.getJavaType( property.getXSDType() );
+ requiredType = implementation.getPropertyClass(name);
+ }
+ return getPropertyBean(requiredType, property.getName());
+ } // end if
+ } // end for
+ // TODO: NoSuchBeanException
+ throw new RuntimeException("Unable to find Bean with name " + name);
+
+ } // end method getBean( String, Class )
+
+ public Object getComponentTie() {
+ return new ComponentTie(component);
+ }
+
+ public Object getPropertyValueTie() {
+ return new PropertyValueTie(component, propertyFactory);
+ }
+
+ public ClassLoader getClassLoader() {
+ return implementation.getClassLoader();
+ }
+
+} \ No newline at end of file
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringInvocationException.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringInvocationException.java
new file mode 100644
index 0000000000..6a23830aa9
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringInvocationException.java
@@ -0,0 +1,40 @@
+/*
+ * 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.invocation;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class SpringInvocationException extends Exception {
+
+ private static final long serialVersionUID = -1157790036638157513L;
+
+ public SpringInvocationException(String msg) {
+ super(msg);
+ }
+
+ public SpringInvocationException(Throwable e) {
+ super(e);
+ }
+
+ public SpringInvocationException(String msg,Throwable e) {
+ super(msg,e);
+ }
+
+}
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringInvoker.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringInvoker.java
new file mode 100644
index 0000000000..1f9796ccc4
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/invocation/SpringInvoker.java
@@ -0,0 +1,124 @@
+/*
+ * 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.invocation;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.apache.tuscany.sca.implementation.spring.SpringBeanElement;
+import org.apache.tuscany.sca.implementation.spring.SpringImplementation;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.invocation.Message;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+
+/**
+ * Initial implementation of a Spring bean invoker
+ * @version $Rev$ $Date$
+ */
+public class SpringInvoker implements Invoker {
+
+ private Method theMethod = null;
+ private Object bean;
+ private SpringBeanElement beanElement;
+ private boolean badInvoker = false;
+
+ private SpringContextStub springContext;
+ private Operation operation;
+
+ /**
+ * SpringInvoker constructor
+ * @param component - the Spring component to invoke
+ * @param service - the service to invoke
+ * @param operation - the operation to invoke
+ */
+ public SpringInvoker(RuntimeComponent component,
+ SpringContextStub springContext,
+ RuntimeComponentService service,
+ Operation operation) {
+
+ this.springContext = springContext;
+ this.operation = operation;
+
+ // From the component and the service, identify the Spring Bean which is the target
+ SpringImplementation theImplementation = (SpringImplementation)component.getImplementation();
+ beanElement = theImplementation.getBeanFromService(service.getService());
+
+ if (beanElement == null) {
+ badInvoker = true;
+ return;
+ }
+
+ } // end constructor SpringInvoker
+
+ // Lazy-load the method to avoid timing problems with the Spring Context
+ private void setupMethod() throws SpringInvocationException{
+ try {
+ bean = springContext.getBean(beanElement.getId());
+ Class<?> beanClass = bean.getClass();
+ theMethod = JavaInterfaceUtil.findMethod(beanClass, operation);
+ //System.out.println("SpringInvoker - found method " + theMethod.getName() );
+ } catch (NoSuchMethodException e) {
+ throw new SpringInvocationException(e);
+ }
+ }
+
+ private Object doInvoke(Object payload) throws SpringInvocationException {
+ if (theMethod == null)
+ setupMethod();
+
+ if (badInvoker)
+ throw new SpringInvocationException("Spring invoker incorrectly configured");
+ // Invoke the method on the Spring bean using the payload, returning the results
+ try {
+ Object ret;
+
+ if (payload != null && !payload.getClass().isArray()) {
+ ret = theMethod.invoke(bean, payload);
+ } else {
+ ret = theMethod.invoke(bean, (Object[])payload);
+ }
+ return ret;
+ } catch (InvocationTargetException e) {
+ throw new SpringInvocationException("Spring invoker invoke method '"+ theMethod.getName()+"' error.",e.getCause());
+ } catch (Exception e) {
+ throw new SpringInvocationException("Spring invoker invoke method '"+ theMethod.getName()+"' error.",e);
+ }
+
+ } // end method doInvoke
+
+ /**
+ * @param msg the message to invoke on the target bean
+ */
+ public Message invoke(Message msg) {
+ try {
+ Object resp = doInvoke(msg.getBody());
+ msg.setBody(resp);
+ } catch (SpringInvocationException e) {
+ msg.setFaultBody(e.getCause());
+ }catch (Throwable e) {
+ msg.setFaultBody(e);
+ }
+ //System.out.println("Spring Invoker - invoke called");
+ return msg;
+ } // end method invoke
+
+} // end class SpringInvoker
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringImplementationProcessor.java b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringImplementationProcessor.java
new file mode 100644
index 0000000000..0cd85d1e33
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/java/org/apache/tuscany/sca/implementation/spring/xml/SpringImplementationProcessor.java
@@ -0,0 +1,230 @@
+/*
+ * 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 javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.ComponentType;
+import org.apache.tuscany.sca.assembly.xml.Constants;
+import org.apache.tuscany.sca.assembly.xml.PolicySubjectProcessor;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.processor.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.processor.ContributionWriteException;
+import org.apache.tuscany.sca.contribution.processor.ProcessorContext;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.implementation.spring.SpringImplementation;
+import org.apache.tuscany.sca.implementation.spring.introspect.SpringXMLComponentTypeLoader;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.apache.tuscany.sca.monitor.Problem.Severity;
+
+/**
+ * SpringArtifactProcessor is responsible for processing the XML of an <implementation.spring.../>
+ * element in an SCA SCDL file.
+ *
+ * @version $Rev$ $Date$
+ */
+public class SpringImplementationProcessor implements StAXArtifactProcessor<SpringImplementation> {
+
+ private static final String LOCATION = "location";
+ private static final String IMPLEMENTATION_SPRING = "implementation.spring";
+ private static final QName IMPLEMENTATION_SPRING_QNAME = new QName(Constants.SCA11_NS, IMPLEMENTATION_SPRING);
+ private static final String MSG_LOCATION_MISSING = "Reading implementation.spring - location attribute missing";
+
+ private ExtensionPointRegistry registry;
+ private AssemblyFactory assemblyFactory;
+ private PolicySubjectProcessor policyProcessor;
+
+
+ private FactoryExtensionPoint factories;
+
+ public SpringImplementationProcessor(ExtensionPointRegistry registry) {
+ this.registry = registry;
+ this.factories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ this.assemblyFactory = factories.getFactory(AssemblyFactory.class);
+ this.policyProcessor = new PolicySubjectProcessor(registry);
+ }
+
+ /**
+ * Report a exception.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(Monitor monitor, String message, Object model, Exception ex) {
+ if (monitor != null) {
+ Problem problem = monitor.createProblem(this.getClass().getName(), "impl-spring-validation-messages", Severity.ERROR, model, message, ex);
+ monitor.problem(problem);
+ }
+ }
+
+ /**
+ * Report a error.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(Monitor monitor, String message, Object model, Object... messageParameters) {
+ if (monitor != null) {
+ Problem problem = monitor.createProblem(this.getClass().getName(), "impl-spring-validation-messages", Severity.ERROR, model, message, (Object[])messageParameters);
+ monitor.problem(problem);
+ }
+ }
+
+ /*
+ * Read the XML and parse out the attributes.
+ *
+ * <implementation.spring.../> has a single required attribute:
+ * "location" - which is the target URI of of an archive file or a directory that contains the Spring
+ * application context files.
+ * If the resource identified by the location attribute is an archive file, then the file
+ * META-INF/MANIFEST.MF is read from the archive.
+ * If the location URI identifies a directory, then META-INF/MANIFEST.MF must exist
+ * underneath that directory.
+ * If the manifest file contains a header "Spring-Context" of the format:
+ * Spring-Context ::= path ( ';' path )*
+ *
+ * Where path is a relative path with respect to the location URI, then the set of paths
+ * specified in the header identify the context configuration files.
+ * If there is no MANIFEST.MF file or no Spring-Context header within that file,
+ * then the default behaviour is to build an application context using all the *.xml files
+ * in the METAINF/spring directory.
+ */
+ public SpringImplementation read(XMLStreamReader reader, ProcessorContext context) throws ContributionReadException, XMLStreamException {
+
+ // Create the Spring implementation
+ SpringImplementation springImplementation = null;
+
+ // Read the location attribute for the spring implementation
+ String springLocation = reader.getAttributeValue(null, LOCATION);
+ if (springLocation != null) {
+ springImplementation = new SpringImplementation();
+ springImplementation.setLocation(springLocation);
+ springImplementation.setUnresolved(true);
+ processComponentType(springImplementation);
+ } else {
+ error(context.getMonitor(), "LocationAttributeMissing", reader);
+ //throw new ContributionReadException(MSG_LOCATION_MISSING);
+ }
+
+ // Read policies
+ policyProcessor.readPolicies(springImplementation, reader);
+
+ // Skip to end element
+ while (reader.hasNext()) {
+ if (reader.next() == END_ELEMENT && IMPLEMENTATION_SPRING_QNAME.equals(reader.getName())) {
+ break;
+ }
+ } // end while
+
+ return springImplementation;
+ } // end read
+
+ /*
+ * Handles the component type for the Spring implementation
+ * @param springImplementation - a Spring implementation. The component type information
+ * is created for this implementation
+ *
+ */
+ private void processComponentType(SpringImplementation springImplementation) {
+
+ // Create a ComponentType and mark it unresolved
+ ComponentType componentType = assemblyFactory.createComponentType();
+ componentType.setUnresolved(true);
+ springImplementation.setComponentType(componentType);
+ } // end processComponentType
+
+ /*
+ * Write out the XML representation of the Spring implementation
+ * <implementation.spring location="..." />
+ */
+ public void write(SpringImplementation springImplementation, XMLStreamWriter writer, ProcessorContext context) throws ContributionWriteException, XMLStreamException {
+
+ // Write <implementation.spring>
+ writer.writeStartElement(Constants.SCA11_NS, IMPLEMENTATION_SPRING);
+ policyProcessor.writePolicyAttributes(springImplementation, writer);
+
+ if (springImplementation.getLocation() != null) {
+ writer.writeAttribute(LOCATION, springImplementation.getLocation());
+ }
+
+ writer.writeEndElement();
+
+ } // end write
+
+ /**
+ * Resolves the Spring implementation - loads the Spring application-context XML and
+ * derives the spring implementation componentType from it
+ */
+ public void resolve(SpringImplementation springImplementation, ModelResolver resolver, ProcessorContext context)
+ throws ContributionResolveException {
+
+ if (springImplementation == null)
+ return;
+
+ Monitor monitor = context.getMonitor();
+ /* Load the Spring component type by reading the Spring application context */
+ SpringXMLComponentTypeLoader springLoader =
+ new SpringXMLComponentTypeLoader(registry, monitor);
+ try {
+ // Load the Spring Implementation information from its application context file...
+ springLoader.load(springImplementation, resolver, context);
+ } catch (ContributionReadException e) {
+ ContributionResolveException ce = new ContributionResolveException(e);
+ error(monitor, "ContributionResolveException", resolver, ce);
+ throw ce;
+ }
+
+ ComponentType ct = springImplementation.getComponentType();
+ if (ct.isUnresolved()) {
+ // If the introspection fails to resolve, try to find a side file...
+ ComponentType componentType = resolver.resolveModel(ComponentType.class, ct, context);
+ if (componentType.isUnresolved()) {
+ error(monitor, "UnableToResolveComponentType", resolver);
+ //throw new ContributionResolveException("SpringArtifactProcessor: unable to resolve componentType for Spring component");
+ } else {
+ springImplementation.setComponentType(componentType);
+ springImplementation.setUnresolved(false);
+ }
+
+ } // end if
+
+ } // end method resolve
+
+ public QName getArtifactType() {
+ return IMPLEMENTATION_SPRING_QNAME;
+ }
+
+ public Class<SpringImplementation> getModelType() {
+ return SpringImplementation.class;
+ }
+
+} // end class SpringArtifactProcessor
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.assembly.builder.ImplementationBuilder b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.assembly.builder.ImplementationBuilder
new file mode 100644
index 0000000000..501eb945d8
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.assembly.builder.ImplementationBuilder
@@ -0,0 +1,18 @@
+# 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.
+org.apache.tuscany.sca.implementation.spring.SpringImplementationBuilder;qname=http://docs.oasis-open.org/ns/opencsa/sca/200903#implementation.spring
+
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor
new file mode 100644
index 0000000000..b04b952fae
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Implementation class for the artifact processor extension
+org.apache.tuscany.sca.implementation.spring.xml.SpringImplementationProcessor;qname=http://docs.oasis-open.org/ns/opencsa/sca/200903#implementation.spring,model=org.apache.tuscany.sca.implementation.spring.SpringImplementation
+
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.definitions.xml.Definitions b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.definitions.xml.Definitions
new file mode 100644
index 0000000000..4a9270d094
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.definitions.xml.Definitions
@@ -0,0 +1,17 @@
+# 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.
+org/apache/tuscany/sca/implementation/spring/definitions.xml
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory
new file mode 100644
index 0000000000..edd3d2e529
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Implementation class for the implementation extension
+org.apache.tuscany.sca.implementation.spring.invocation.SpringImplementationProviderFactory;model=org.apache.tuscany.sca.implementation.spring.SpringImplementation
+
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/impl-spring-validation-messages.properties b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/impl-spring-validation-messages.properties
new file mode 100644
index 0000000000..28bd31ca11
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/impl-spring-validation-messages.properties
@@ -0,0 +1,28 @@
+#
+#
+# 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.
+#
+#
+LocationAttributeMissing = Reading implementation.spring - location attribute missing
+ContributionResolveException = ContributionResolveException occured due to:
+UnableToResolveComponentType = SpringArtifactProcessor: unable to resolve componentType for Spring component
+ScaServiceNameNotUnique = The value of the @name attribute of an <sca:service/> element MUST be unique amongst the <sca:service/> subelements of the <beans/> element
+ScaReferenceNameNotUnique = The value of the @name attribute of an <sca:reference/> element MUST be unique amongst the <sca:reference/> subelements of the <beans/> element
+ScaPropertyNameNotUnique = The value of the @name attribute of an <sca:property/> element MUST be unique amongst the <sca:property/> subelements of the <beans/> element
+DefaultBeanDoesNotExist = The @default attribute of a <sca:reference/> element MUST have the value of the @name attribute of one of the <bean/> subelements of the <beans/> element.
+TargetBeanDoesNotExist = The @target attribute of a <sca:service/> element MUST have the value of the @name attribute of one of the <bean/> subelements of the <beans/> element.
diff --git a/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/org/apache/tuscany/sca/implementation/spring/definitions.xml b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/org/apache/tuscany/sca/implementation/spring/definitions.xml
new file mode 100644
index 0000000000..d03e42a7a2
--- /dev/null
+++ b/branches/sca-java-2.0-M4/modules/implementation-spring/src/main/resources/org/apache/tuscany/sca/implementation/spring/definitions.xml
@@ -0,0 +1,30 @@
+<?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.
+-->
+
+<!-- $Rev$ $Date$ -->
+
+<sca:definitions xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200903"
+ targetNamespace="http://docs.oasis-open.org/ns/opencsa/sca/200903"
+ xmlns:sca="http://docs.oasis-open.org/ns/opencsa/sca/200903"
+ xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.1">
+
+ <sca:implementationType type="sca:implementation.spring" mayProvide="" alwaysProvides=""/>
+
+ </sca:definitions>