summaryrefslogtreecommitdiffstats
path: root/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl
diff options
context:
space:
mode:
authordims <dims@13f79535-47bb-0310-9956-ffa450edef68>2008-06-17 00:23:01 +0000
committerdims <dims@13f79535-47bb-0310-9956-ffa450edef68>2008-06-17 00:23:01 +0000
commitbdd0a41aed7edf21ec2a65cfa17a86af2ef8c48a (patch)
tree38a92061c0793434c4be189f1d70c3458b6bc41d /branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl
Move Tuscany from Incubator to top level.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@668359 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl')
-rw-r--r--branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringComponentTypeLoader.java109
-rw-r--r--branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeBuilder.java88
-rw-r--r--branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeComponent.java252
-rw-r--r--branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringImplementationLoader.java196
-rw-r--r--branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInterceptor.java53
-rw-r--r--branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInvoker.java104
-rw-r--r--branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringRuntimeInfo.java63
-rw-r--r--branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringScaAdapter.java54
8 files changed, 919 insertions, 0 deletions
diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringComponentTypeLoader.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringComponentTypeLoader.java
new file mode 100644
index 0000000000..fa815eee78
--- /dev/null
+++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringComponentTypeLoader.java
@@ -0,0 +1,109 @@
+/*
+ * 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.container.spring.impl;
+
+import org.springframework.context.support.AbstractRefreshableApplicationContext;
+import org.springframework.core.io.Resource;
+import org.springframework.sca.ScaServiceExporter;
+
+import org.apache.tuscany.container.spring.config.ScaApplicationContext;
+import org.apache.tuscany.container.spring.model.SpringComponentType;
+import org.apache.tuscany.container.spring.model.SpringImplementation;
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.ComponentTypeLoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.host.RuntimeInfo;
+
+/**
+ * Loads a component type for a Spring <code>ApplicationContext</code>. The implementation creates a new instance of a
+ * Spring application context which is configured with SCA namespace handlers for generating component type information
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+
+public class SpringComponentTypeLoader extends ComponentTypeLoaderExtension<SpringImplementation> {
+ public static final String SERVICE_BEAN_SUFFIX = ".SCAService";
+
+ private org.apache.tuscany.host.RuntimeInfo runtimeInfo;
+
+ public SpringComponentTypeLoader(@Autowire LoaderRegistry loaderRegistry, @Autowire RuntimeInfo runtimeInfo) {
+ super(loaderRegistry);
+ this.runtimeInfo = runtimeInfo;
+ }
+
+ @Override
+ protected Class<SpringImplementation> getImplementationClass() {
+ return SpringImplementation.class;
+ }
+
+ /**
+ * Responsible for loading the Spring composite component type. The the application context is instantiated here as
+ * it is needed to derive component type information. Since the component type is loaded per SCDL entry (i.e.
+ * composite use) one application context instance will be created per Spring composite instance.
+ */
+ @SuppressWarnings("unchecked")
+ public void load(CompositeComponent parent,
+ SpringImplementation implementation,
+ DeploymentContext deploymentContext) throws LoaderException {
+ if (implementation.getComponentType() != null) {
+ // FIXME hack since the builder registry loads the implementation type and the Spring implementation loader
+ // needs to as well. The second call is done by the builder registry and we just ignore it.
+ return;
+ }
+ Resource resource = implementation.getApplicationResource();
+ SpringComponentType componentType = new SpringComponentType();
+ // REVIEW andyp -- pass in deploymentContext.getClassLoader()?
+ AbstractRefreshableApplicationContext ctx;
+ if (runtimeInfo instanceof SpringRuntimeInfo) {
+ ctx = ((SpringRuntimeInfo) runtimeInfo).getApplicationContext();
+ } else {
+ ctx = new ScaApplicationContext(resource, componentType);
+ }
+ componentType.setApplicationContext(ctx); // FIXME andyp@bea.com -- don't do this!
+
+ // If there are <sca:service> elements, they define (and limit) the services exposed
+ // in the componentType.
+ String [] serviceBeanNames = ctx.getBeanNamesForType(ScaServiceExporter.class);
+ for (String serviceBeanName : serviceBeanNames) {
+ int nSuffix = serviceBeanName.indexOf(SERVICE_BEAN_SUFFIX);
+ if (nSuffix == -1) {
+ continue;
+ }
+
+ String serviceName = serviceBeanName.substring(0, nSuffix);
+ ScaServiceExporter serviceBean = (ScaServiceExporter) ctx.getBean(serviceName);
+ // REVIEW andyp -- use the class directly?
+ String serviceTypeName = serviceBean.getServiceType().getName();
+ try {
+ Class serviceInterface = Class.forName(serviceTypeName, true, deploymentContext.getClassLoader());
+ componentType.addServiceType(serviceName, serviceInterface);
+ //ServiceDefinition service = createService(serviceInterface);
+ //componentType.getServices().put(serviceName, service);
+ } catch (ClassNotFoundException e) {
+ throw new LoaderException(e);
+ }
+ }
+ // if no service tags are specified, expose all beans
+ componentType.setExposeAllBeans(componentType.getServiceTypes().isEmpty());
+ implementation.setComponentType(componentType);
+ }
+}
diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeBuilder.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeBuilder.java
new file mode 100644
index 0000000000..6ec5d8fdd7
--- /dev/null
+++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeBuilder.java
@@ -0,0 +1,88 @@
+/*
+ * 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.container.spring.impl;
+
+import org.apache.tuscany.spi.QualifiedName;
+import org.apache.tuscany.spi.builder.BuilderConfigException;
+import org.apache.tuscany.spi.component.Component;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.component.Reference;
+import org.apache.tuscany.spi.component.Service;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.ComponentBuilderExtension;
+import org.apache.tuscany.spi.model.Binding;
+import org.apache.tuscany.spi.model.BoundReferenceDefinition;
+import org.apache.tuscany.spi.model.BoundServiceDefinition;
+import org.apache.tuscany.spi.model.ComponentDefinition;
+import org.apache.tuscany.spi.model.CompositeComponentType;
+import org.apache.tuscany.spi.model.Property;
+import org.apache.tuscany.spi.wire.InboundInvocationChain;
+import org.apache.tuscany.spi.wire.InboundWire;
+
+import org.apache.tuscany.container.spring.model.SpringImplementation;
+import org.springframework.context.support.AbstractApplicationContext;
+
+/**
+ * Creates a {@link org.apache.tuscany.container.spring.impl.SpringCompositeComponent} from an assembly model
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class SpringCompositeBuilder extends ComponentBuilderExtension<SpringImplementation> {
+
+ public Component build(CompositeComponent parent,
+ ComponentDefinition<SpringImplementation> componentDefinition,
+ DeploymentContext deploymentContext) throws BuilderConfigException {
+ String name = componentDefinition.getName();
+ SpringImplementation implementation = componentDefinition.getImplementation();
+ AbstractApplicationContext applicationContext = implementation.getComponentType().getApplicationContext();
+ SpringCompositeComponent component =
+ new SpringCompositeComponent(name, applicationContext, parent, connector, null);
+ CompositeComponentType<BoundServiceDefinition<? extends Binding>,
+ BoundReferenceDefinition<? extends Binding>,
+ ? extends Property> componentType = implementation.getComponentType();
+
+ // We still need to set the target invoker as opposed to having the connector do it since the
+ // Spring context is "opaque" to the wiring fabric. In other words, the Spring context does not expose
+ // its beans as SCA components to the connector to wire the services to
+ for (BoundServiceDefinition<? extends Binding> serviceDefinition : componentType.getServices().values()) {
+ // call back into builder registry to handle building of services
+ Service service = (Service) builderRegistry.build(parent, serviceDefinition, deploymentContext);
+ // wire serviceDefinition to bean invokers
+ InboundWire wire = service.getInboundWire();
+ QualifiedName targetName = new QualifiedName(serviceDefinition.getTarget().getPath());
+ for (InboundInvocationChain chain : wire.getInvocationChains().values()) {
+ // FIXME this should go to the connector and get policy and be invoked from SpringComposite.prepare()
+ chain.addInterceptor(new SpringInterceptor());
+ chain.setTargetInvoker(component.createTargetInvoker(targetName.getPartName(), chain.getOperation()));
+ }
+ component.register(service);
+ }
+ for (BoundReferenceDefinition<?> referenceDefinition : componentType.getReferences().values()) {
+ // call back into builder registry to handle building of references
+ Reference reference = (Reference) builderRegistry.build(parent, referenceDefinition, deploymentContext);
+ connector.connect(reference);
+ component.register(reference);
+ }
+ return component;
+ }
+
+ protected Class<SpringImplementation> getImplementationType() {
+ return SpringImplementation.class;
+ }
+}
diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeComponent.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeComponent.java
new file mode 100644
index 0000000000..b30202cb96
--- /dev/null
+++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeComponent.java
@@ -0,0 +1,252 @@
+/*
+ * 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.container.spring.impl;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.Locale;
+import java.util.Map;
+
+import org.w3c.dom.Document;
+
+import org.apache.tuscany.spi.builder.Connector;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.component.Reference;
+import org.apache.tuscany.spi.component.SCAObject;
+import org.apache.tuscany.spi.component.ScopeContainer;
+import org.apache.tuscany.spi.component.Service;
+import org.apache.tuscany.spi.extension.CompositeComponentExtension;
+import static org.apache.tuscany.spi.idl.java.JavaIDLUtils.findMethod;
+import org.apache.tuscany.spi.model.Operation;
+import org.apache.tuscany.spi.model.ServiceContract;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.MessageSourceResolvable;
+import org.springframework.context.NoSuchMessageException;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.core.io.Resource;
+
+/**
+ * A composite implementation responsible for managing Spring application contexts.
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class SpringCompositeComponent extends CompositeComponentExtension {
+ private static final String[] EMPTY_ARRAY = new String[0];
+ private AbstractApplicationContext springContext;
+
+ /**
+ * Creates a new composite
+ *
+ * @param name the name of the SCA composite
+ * @param springContext the pre-instantiated Spring applicaiton context
+ * @param parent the SCA composite parent
+ * @param connector the connector to use for wiring children
+ * @param propertyValues the values of this composite's Properties
+ */
+ public SpringCompositeComponent(String name,
+ AbstractApplicationContext springContext,
+ CompositeComponent parent,
+ Connector connector,
+ Map<String, Document> propertyValues) {
+ super(name, parent, connector, propertyValues);
+ SCAApplicationContext scaApplicationContext = new SCAApplicationContext();
+ springContext.setParent(scaApplicationContext);
+ // REVIEW we need to refresh to pick up the parent but this is not optimal
+ springContext.refresh();
+ this.springContext = springContext;
+ }
+
+ public TargetInvoker createTargetInvoker(String targetName, Operation operation) {
+ ServiceContract contract = operation.getServiceContract();
+ Method[] methods = contract.getInterfaceClass().getMethods();
+ Method method = findMethod(operation, methods);
+ // FIXME test m == null
+ // Treat the serviceName as the Spring bean name to look up
+ return new SpringInvoker(targetName, method, springContext);
+ }
+
+ public void setScopeContainer(ScopeContainer scopeContainer) {
+ // not needed
+ }
+
+ public ConfigurableApplicationContext getApplicationContext() {
+ return springContext;
+ }
+
+ public void prepare() {
+ // TODO handle only references with a composite binding
+ }
+
+ public void start() {
+ super.start();
+ for (SCAObject child : children.values()) {
+ child.start();
+ }
+ springContext.start();
+ }
+
+ public void stop() {
+ super.stop();
+ springContext.stop();
+ }
+
+ public <T> T locateService(Class<T> serviceInterface, String name) {
+ return serviceInterface.cast(springContext.getBean(name));
+ }
+
+ /**
+ * An inner class is required to act as the Spring application context parent as opposed to implementing the
+ * interface since the return types for {@link org.springframework.context.ApplicationContext#getParent()} and
+ * {@link org.apache.tuscany.spi.component.CompositeComponent#getParent()} clash
+ */
+ private class SCAApplicationContext implements ApplicationContext {
+
+ public Object getBean(String name) throws BeansException {
+ return getBean(name, null);
+ }
+
+ public Object getBean(String name, Class requiredType) throws BeansException {
+ SCAObject object = children.get(name); // keep cast due to compiler error
+ if (object == null) {
+ return null;
+ }
+ Class<?> type;
+ if (object instanceof Reference) {
+ type = ((Reference) object).getInterface();
+ } else if (object instanceof Service) {
+ type = ((Service) object).getInterface();
+ } else {
+ throw new AssertionError("Illegal object type [" + name + "]");
+ }
+ if (requiredType != null && requiredType.isAssignableFrom(type)) {
+ // need null check since Spring may pass in a null
+ throw new BeanNotOfRequiredTypeException(name, requiredType, type);
+ }
+ return object.getServiceInstance();
+ }
+
+ public boolean containsBean(String name) {
+ return children.get(name) != null;
+ }
+
+ public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
+ return children.get(name) != null;
+ }
+
+ public Class getType(String name) throws NoSuchBeanDefinitionException {
+ return null;
+ }
+
+ public String[] getAliases(String name) throws NoSuchBeanDefinitionException {
+ return EMPTY_ARRAY;
+ }
+
+ public ApplicationContext getParent() {
+ return null;
+ }
+
+ public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException {
+ return null;
+ }
+
+ public String getDisplayName() {
+ return getName();
+ }
+
+ public long getStartupDate() {
+ return 0;
+ }
+
+ public boolean containsBeanDefinition(String beanName) {
+ return false;
+ }
+
+ public int getBeanDefinitionCount() {
+ return 0;
+ }
+
+ public String[] getBeanDefinitionNames() {
+ return new String[0];
+ }
+
+ public String[] getBeanNamesForType(Class type) {
+ return new String[0];
+ }
+
+ public String[] getBeanNamesForType(Class type, boolean includePrototypes, boolean includeFactoryBeans) {
+ return new String[0];
+ }
+
+ public Map getBeansOfType(Class type) throws BeansException {
+ return null;
+ }
+
+ public Map getBeansOfType(Class type, boolean includePrototypes, boolean includeFactoryBeans)
+ throws BeansException {
+ return null;
+ }
+
+ public BeanFactory getParentBeanFactory() {
+ return null;
+ }
+
+ public boolean containsLocalBean(String name) {
+ return false;
+ }
+
+ public String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {
+ return null;
+ }
+
+ public String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException {
+ return null;
+ }
+
+ public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException {
+ return null;
+ }
+
+ public void publishEvent(ApplicationEvent event) {
+
+ }
+
+ public Resource[] getResources(String locationPattern) throws IOException {
+ return new Resource[0];
+ }
+
+ public Resource getResource(String location) {
+ return null;
+ }
+
+ public ClassLoader getClassLoader() {
+ // REVIEW: this is almost certainly flawed, but it's not clear how the SCA runtime's
+ // resource loading mechanism is exposed right now.
+ return this.getClass().getClassLoader();
+ }
+ }
+}
diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringImplementationLoader.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringImplementationLoader.java
new file mode 100644
index 0000000000..c95375cad2
--- /dev/null
+++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringImplementationLoader.java
@@ -0,0 +1,196 @@
+/*
+ * 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.container.spring.impl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URL;
+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 static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import static org.osoa.sca.Version.XML_NAMESPACE_1_0;
+
+import org.apache.tuscany.spi.annotation.Autowire;
+import org.apache.tuscany.spi.component.CompositeComponent;
+import org.apache.tuscany.spi.deployer.DeploymentContext;
+import org.apache.tuscany.spi.extension.LoaderExtension;
+import org.apache.tuscany.spi.loader.LoaderException;
+import org.apache.tuscany.spi.loader.LoaderRegistry;
+import org.apache.tuscany.spi.loader.MissingResourceException;
+import org.apache.tuscany.spi.model.BoundReferenceDefinition;
+import org.apache.tuscany.spi.model.BoundServiceDefinition;
+
+import org.apache.tuscany.container.spring.model.SpringComponentType;
+import org.apache.tuscany.container.spring.model.SpringImplementation;
+import org.apache.tuscany.host.RuntimeInfo;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.UrlResource;
+
+/**
+ * Loader for handling Spring <spring:implementation.spring> elements.
+ */
+public class SpringImplementationLoader extends LoaderExtension<SpringImplementation> {
+ private static final QName IMPLEMENTATION_SPRING = new QName("http://www.osoa.org/xmlns/sca/1.0",
+ "implementation.spring");
+
+ private static final String APPLICATION_CONTEXT = "application-context.xml";
+
+ private static final QName SERVICE_ELEMENT = new QName(XML_NAMESPACE_1_0, "service");
+ private static final QName REFERENCE_ELEMENT = new QName(XML_NAMESPACE_1_0, "reference");
+
+ private final RuntimeInfo runtimeInfo;
+
+ public SpringImplementationLoader(@Autowire LoaderRegistry registry, @Autowire RuntimeInfo runtimeInfo) {
+ super(registry);
+ this.runtimeInfo = runtimeInfo;
+ }
+
+ public QName getXMLType() {
+ return IMPLEMENTATION_SPRING;
+ }
+
+ @SuppressWarnings("unchecked")
+ public SpringImplementation load(CompositeComponent parent,
+ XMLStreamReader reader,
+ DeploymentContext deploymentContext)
+ throws XMLStreamException, LoaderException {
+
+ String locationAttr = reader.getAttributeValue(null, "location");
+ if (locationAttr == null && !contextProvided()) {
+ throw new MissingResourceException("No location supplied");
+ }
+
+ SpringImplementation implementation = new SpringImplementation();
+ ClassLoader classLoader = deploymentContext.getClassLoader();
+ if (!contextProvided()) {
+ implementation.setApplicationResource(getApplicationContextResource(locationAttr, classLoader));
+ }
+ registry.loadComponentType(parent, implementation, deploymentContext);
+ SpringComponentType type = implementation.getComponentType();
+ while (true) {
+ switch (reader.next()) {
+ case START_ELEMENT:
+ QName qname = reader.getName();
+ if (SERVICE_ELEMENT.equals(qname)) {
+ BoundServiceDefinition service =
+ (BoundServiceDefinition) registry.load(parent, reader, deploymentContext);
+ if (!type.isExposeAllBeans()) {
+ String name = service.getName();
+ if (!type.getServiceTypes().containsKey(name)) {
+ LoaderException e = new LoaderException("No service defined in Spring context for ");
+ e.setIdentifier(name);
+ throw e;
+ }
+ }
+ type.getDeclaredServices().put(service.getName(), service);
+ } else if (REFERENCE_ELEMENT.equals(qname)) {
+ BoundReferenceDefinition reference =
+ (BoundReferenceDefinition) registry.load(parent, reader, deploymentContext);
+ type.getDeclaredReferences().put(reference.getName(), reference);
+ }
+ break;
+ case END_ELEMENT:
+ if (IMPLEMENTATION_SPRING.equals(reader.getName())) {
+ return implementation;
+ }
+ }
+ }
+ }
+
+ protected Resource getApplicationContextResource(String locationAttr, ClassLoader cl) throws LoaderException {
+ assert runtimeInfo != null;
+ File manifestFile = null;
+ File appXmlFile;
+ File locationFile = new File(locationAttr);
+
+ if (!locationFile.isAbsolute()) {
+ locationFile = new File(runtimeInfo.getApplicationRootDirectory(), locationAttr);
+ }
+ if (!locationFile.exists()) {
+ // FIXME hack
+ URL url = cl.getResource(locationAttr);
+ if (url != null) {
+ return new UrlResource(url);
+ }
+ throw new MissingResourceException(locationFile.toString());
+ }
+
+ if (locationFile.isDirectory()) {
+ try {
+ manifestFile = new File(locationFile, "META-INF/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) {
+ appXmlFile = new File(locationFile, appCtxPath);
+ if (appXmlFile.exists()) {
+ return new UrlResource(appXmlFile.toURL());
+ }
+ }
+ }
+ // no manifest-specified Spring context, use default
+ appXmlFile = new File(locationFile, APPLICATION_CONTEXT);
+ if (appXmlFile.exists()) {
+ return new UrlResource(appXmlFile.toURL());
+ }
+ } catch (IOException e) {
+ throw new LoaderException("Error reading manifest " + manifestFile);
+ }
+ } else {
+ 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) {
+ je = jf.getJarEntry(appCtxPath);
+ if (je != null) {
+ // TODO return a Spring specific Resouce type for jars
+ return new UrlResource(new URL("jar:" + locationFile.toURL() + "!/" + appCtxPath));
+ }
+ }
+ }
+ je = jf.getJarEntry(APPLICATION_CONTEXT);
+ if (je != null) {
+ return new UrlResource(new URL("jar:" + locationFile.toURI().toURL() + "!" + APPLICATION_CONTEXT));
+ }
+ } catch (IOException e) {
+ // bad archive
+ // TODO: create a more appropriate exception type
+ throw new MissingResourceException(locationAttr, e);
+ }
+ }
+ throw new MissingResourceException(APPLICATION_CONTEXT);
+ }
+
+ private boolean contextProvided() {
+ return runtimeInfo instanceof SpringRuntimeInfo;
+ }
+}
diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInterceptor.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInterceptor.java
new file mode 100644
index 0000000000..fb7f0bd99c
--- /dev/null
+++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInterceptor.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.container.spring.impl;
+
+import org.apache.tuscany.spi.wire.Interceptor;
+import org.apache.tuscany.spi.wire.InvocationRuntimeException;
+import org.apache.tuscany.spi.wire.Message;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+
+/**
+ * A temporary interceptor until the connector is updated
+ *
+ * @version $Rev$ $Date$
+ */
+public class SpringInterceptor implements Interceptor {
+
+ public Message invoke(Message msg) throws InvocationRuntimeException {
+ TargetInvoker invoker = msg.getTargetInvoker();
+ if (invoker == null) {
+ throw new InvocationRuntimeException("No target invoker specified on message");
+ }
+ return invoker.invoke(msg);
+ }
+
+ public void setNext(Interceptor next) {
+ throw new IllegalStateException("This interceptor must be the last one in an target interceptor chain");
+ }
+
+ public Interceptor getNext() {
+ return null;
+ }
+
+ public boolean isOptimizable() {
+ return true;
+ }
+
+}
diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInvoker.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInvoker.java
new file mode 100644
index 0000000000..6e05c888ae
--- /dev/null
+++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInvoker.java
@@ -0,0 +1,104 @@
+/*
+ * 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.container.spring.impl;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.apache.tuscany.spi.component.TargetException;
+import org.apache.tuscany.spi.wire.InvocationRuntimeException;
+import org.apache.tuscany.spi.wire.Message;
+import org.apache.tuscany.spi.wire.TargetInvoker;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+
+/**
+ * Dispatches to an operation on a Spring bean. Since Spring manages bean lifecycle and scope through resolution in the
+ * target proxy, the invoker can safely cache the target proxy.
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class SpringInvoker implements TargetInvoker {
+ private ApplicationContext springContext;
+ // default to true since Spring handles resolution
+ private boolean cacheable = true;
+ private String beanName;
+ private Method method;
+ // caching is thread-safe since Spring handles resolution
+ private Object bean;
+
+ public SpringInvoker(String beanName, Method method, ApplicationContext context) {
+ this.beanName = beanName;
+ this.method = method;
+ springContext = context;
+ }
+
+ public Object invokeTarget(final Object object) throws InvocationTargetException {
+ if (bean == null) {
+ try {
+ bean = springContext.getBean(beanName);
+ } catch (BeansException e) {
+ throw new TargetException(e);
+ }
+ }
+ try {
+ if (object != null && !object.getClass().isArray()) {
+ return method.invoke(bean, object);
+ } else {
+ return method.invoke(bean, (Object[]) object);
+ }
+ } catch (IllegalAccessException e) {
+ throw new InvocationTargetException(e);
+ }
+ }
+
+ public Message invoke(Message msg) throws InvocationRuntimeException {
+ try {
+ Object resp = invokeTarget(msg.getBody());
+ msg.setBody(resp);
+ } catch (InvocationTargetException e) {
+ msg.setBodyWithFault(e.getCause());
+ } catch (Throwable e) {
+ msg.setBodyWithFault(e);
+ }
+ return msg;
+ }
+
+ public boolean isCacheable() {
+ return cacheable;
+ }
+
+ public void setCacheable(boolean cacheable) {
+ this.cacheable = cacheable;
+ }
+
+ public boolean isOptimizable() {
+ return false;
+ }
+
+
+ public SpringInvoker clone() throws CloneNotSupportedException {
+ SpringInvoker invoker = (SpringInvoker) super.clone();
+ invoker.bean = null;
+ return invoker;
+ }
+
+
+}
diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringRuntimeInfo.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringRuntimeInfo.java
new file mode 100644
index 0000000000..8b4f0ac905
--- /dev/null
+++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringRuntimeInfo.java
@@ -0,0 +1,63 @@
+/*
+ * 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.container.spring.impl;
+
+import java.io.File;
+import java.net.URL;
+
+import org.apache.tuscany.host.RuntimeInfo;
+import org.springframework.context.support.AbstractRefreshableApplicationContext;
+
+/**
+ * @author Andy Piper
+ * @since 2.1
+ */
+public class SpringRuntimeInfo implements RuntimeInfo {
+ private AbstractRefreshableApplicationContext applicationContext;
+ private File appRootDir;
+
+ public SpringRuntimeInfo(File appRootDir, AbstractRefreshableApplicationContext applicationContext) {
+ this.appRootDir = appRootDir;
+ this.applicationContext = applicationContext;
+ }
+
+ public AbstractRefreshableApplicationContext getApplicationContext() {
+ return applicationContext;
+ }
+
+ public void setApplicationContext(AbstractRefreshableApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ }
+
+ public File getInstallDirectory() {
+ return null;
+ }
+
+ public File getApplicationRootDirectory() {
+ return appRootDir;
+ }
+
+ public URL getBaseURL() {
+ return null;
+ }
+
+ public boolean isOnline() {
+ return true;
+ }
+}
diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringScaAdapter.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringScaAdapter.java
new file mode 100644
index 0000000000..ca645db823
--- /dev/null
+++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringScaAdapter.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2002-2006 the original author or authors.
+ *
+ * Licensed 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.container.spring.impl;
+
+import org.apache.tuscany.container.spring.model.SpringComponentType;
+import org.springframework.sca.ScaAdapter;
+
+/**
+ * @author Andy Piper
+ * @since 2.1
+ */
+public class SpringScaAdapter implements ScaAdapter {
+ //private final SpringComponentType componentType;
+
+ public SpringScaAdapter(SpringComponentType componentType) {
+ //this.componentType = componentType;
+ }
+
+ public Object getServiceReference(String referenceName, Class referenceType, String moduleName,
+ String defaultServiceName) {
+ /*
+ ReferenceDefinition reference = null;
+ componentType.getReferences().put(referenceName, reference);
+ */
+ return null;
+ }
+
+ public Object getPropertyReference(String propertyName, Class propertyType, String moduleName) {
+ return null;
+ }
+
+ public void publishAsService(Object serviceImplementation, Class serviceInterface, String serviceName,
+ String moduleName) {
+ /*
+ componentType.addServiceType(serviceName, serviceInterface);
+ ServiceDefinition service = null;
+ componentType.getServices().put(serviceName, service);
+ */
+ }
+}