summaryrefslogtreecommitdiffstats
path: root/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany
diff options
context:
space:
mode:
Diffstat (limited to 'branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany')
-rw-r--r--branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/config/SCANamespaceHandlerResolver.java59
-rw-r--r--branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/config/ScaApplicationContext.java68
-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
-rw-r--r--branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/model/SpringComponentType.java101
-rw-r--r--branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/model/SpringImplementation.java77
-rw-r--r--branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/model/SpringServiceContract.java31
-rw-r--r--branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/webapp/ScaWebApplicationContext.java130
-rw-r--r--branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/webapp/SpringWebappRuntimeInfo.java41
15 files changed, 1426 insertions, 0 deletions
diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/config/SCANamespaceHandlerResolver.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/config/SCANamespaceHandlerResolver.java
new file mode 100644
index 0000000000..047d2b4ad1
--- /dev/null
+++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/config/SCANamespaceHandlerResolver.java
@@ -0,0 +1,59 @@
+/*
+ * 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.config;
+
+import org.apache.tuscany.spi.model.CompositeComponentType;
+
+import org.springframework.beans.factory.xml.DefaultNamespaceHandlerResolver;
+import org.springframework.beans.factory.xml.NamespaceHandler;
+import org.springframework.sca.config.ScaNamespaceHandler;
+
+/**
+ * Overrides the default Spring namespace resolver to automatically register {@link SCANamespaceHandler} instead of
+ * requiring a value to be supplied in a Spring configuration
+ * <p/>
+ * TODO: Figure out how to activate this impl
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class SCANamespaceHandlerResolver extends DefaultNamespaceHandlerResolver {
+
+ private static final String SCA_NAMESPACE = "http://www.springframework.org/schema/sca";
+
+ private ScaNamespaceHandler handler;
+
+ public SCANamespaceHandlerResolver(ClassLoader classLoader, CompositeComponentType componentType) {
+ super(classLoader);
+ handler = new ScaNamespaceHandler(/*componentType*/);
+ }
+
+ public SCANamespaceHandlerResolver(String handlerMappingsLocation,
+ ClassLoader classLoader,
+ CompositeComponentType componentType) {
+ super(classLoader, handlerMappingsLocation);
+ handler = new ScaNamespaceHandler(/*componentType*/);
+ }
+
+ public NamespaceHandler resolve(String namespaceUri) {
+ if (SCA_NAMESPACE.equals(namespaceUri)) {
+ return handler;
+ }
+ return super.resolve(namespaceUri);
+ }
+}
diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/config/ScaApplicationContext.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/config/ScaApplicationContext.java
new file mode 100644
index 0000000000..cdf33b0ea1
--- /dev/null
+++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/config/ScaApplicationContext.java
@@ -0,0 +1,68 @@
+/*
+ * 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.config;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.AbstractXmlApplicationContext;
+import org.springframework.core.io.Resource;
+import org.springframework.sca.ScaAdapterAware;
+import org.springframework.sca.ScaAdapterPostProcessor;
+
+import org.apache.tuscany.container.spring.impl.SpringScaAdapter;
+import org.apache.tuscany.container.spring.model.SpringComponentType;
+
+/**
+ * @author Andy Piper
+ * @since 2.1
+ */
+public class ScaApplicationContext extends AbstractXmlApplicationContext {
+ public static final String APP_CONTEXT_PROP = "org.springframework.sca.application.context";
+ private Resource appXml;
+ private SpringComponentType componentType;
+
+ public ScaApplicationContext(Resource appXml, SpringComponentType componentType) {
+ this(null, appXml, componentType);
+ }
+
+ public ScaApplicationContext(ApplicationContext parent, Resource appXml, SpringComponentType componentType) {
+ super(parent);
+ this.appXml = appXml;
+ this.componentType = componentType;
+ refresh();
+ }
+
+ protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) {
+ // beanDefinitionReader.setEntityResolver(null);
+ beanDefinitionReader
+ .setNamespaceHandlerResolver(new SCANamespaceHandlerResolver(getClassLoader(), componentType));
+ }
+
+ protected Resource[] getConfigResources() {
+ return new Resource[]{appXml};
+ }
+
+ protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
+ super.postProcessBeanFactory(beanFactory);
+ beanFactory.addBeanPostProcessor(new ScaAdapterPostProcessor(new SpringScaAdapter(componentType)));
+ beanFactory.ignoreDependencyInterface(ScaAdapterAware.class);
+ }
+}
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);
+ */
+ }
+}
diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/model/SpringComponentType.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/model/SpringComponentType.java
new file mode 100644
index 0000000000..d8758ffdb7
--- /dev/null
+++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/model/SpringComponentType.java
@@ -0,0 +1,101 @@
+/*
+ * 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.model;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.spi.model.CompositeComponentType;
+import org.apache.tuscany.spi.model.Property;
+import org.apache.tuscany.spi.model.ReferenceDefinition;
+import org.apache.tuscany.spi.model.ServiceDefinition;
+
+import org.springframework.context.support.AbstractApplicationContext;
+
+/**
+ * Component type information for a Spring composite component implementation type. A component type is associated with
+ * a Spring application context
+ *
+ * @version $Rev$ $Date$
+ */
+public class SpringComponentType<S extends ServiceDefinition,
+ R extends ReferenceDefinition,
+ P extends Property<?>> extends CompositeComponentType<S, R, P> {
+
+ private AbstractApplicationContext applicationContext;
+ private Map<String, Class<?>> serviceTypes = new HashMap<String, Class<?>>();
+ private boolean exposeAllBeans;
+
+ public SpringComponentType(AbstractApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ }
+
+ public SpringComponentType() {
+ }
+
+ // FIXME andyp@bea.com -- this is a component type it should NOT contain bean instances!
+
+ /**
+ * Returns the application context for the component type
+ */
+ public AbstractApplicationContext getApplicationContext() {
+ return applicationContext;
+ }
+
+ public void setApplicationContext(AbstractApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ }
+
+ /**
+ * Returns a collection of service types defined by <code>sca:service</code> elements in a Spring configuration.
+ * Service types define beans that can be targets of services defined in the SCDL Spring composite declaration. For
+ * each service type, there must be a corresponding service definition as part of the Spring composite declaration
+ * per the SCA specification.
+ */
+ public Map<String, Class<?>> getServiceTypes() {
+ return serviceTypes;
+ }
+
+ /**
+ * Adds a service type to the component declaration defined by <code>sca:service</code> elements in a Spring
+ * configuration.
+ *
+ * @param name the name of the service
+ * @param type the interface type of the target bean
+ */
+ public void addServiceType(String name, Class<?> type) {
+ this.serviceTypes.put(name, type);
+ }
+
+ /**
+ * Returns true if all beans in the Spring application context may be service targets or false if service types are
+ * defined
+ */
+ public boolean isExposeAllBeans() {
+ return exposeAllBeans;
+ }
+
+ /**
+ * Sets if all beans in the Spring application context may be service targets or false if service types are defined
+ */
+ public void setExposeAllBeans(boolean exposeAllBeans) {
+ this.exposeAllBeans = exposeAllBeans;
+ }
+
+}
diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/model/SpringImplementation.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/model/SpringImplementation.java
new file mode 100644
index 0000000000..7780894f56
--- /dev/null
+++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/model/SpringImplementation.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.container.spring.model;
+
+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.Implementation;
+import org.apache.tuscany.spi.model.Property;
+
+import org.springframework.core.io.Resource;
+
+/**
+ * Represents a composite whose implementation type is a Spring application context.
+ *
+ * @version $$Rev$$ $$Date$$
+ */
+public class SpringImplementation extends Implementation<SpringComponentType<BoundServiceDefinition<? extends Binding>,
+ BoundReferenceDefinition<? extends Binding>, ? extends Property>> {
+
+ private String location;
+ private Resource applicationResource;
+
+ public SpringImplementation() {
+ }
+
+ public SpringImplementation(SpringComponentType<
+ BoundServiceDefinition<? extends Binding>,
+ BoundReferenceDefinition<? extends Binding>,
+ ? extends Property> componentType) {
+ super(componentType);
+ }
+
+ /**
+ * Returns the path of the Spring application context configuration
+ */
+ public String getLocation() {
+ return location;
+ }
+
+ /**
+ * Sets the path of the Spring application context configuration
+ */
+ public void setLocation(String location) {
+ this.location = location;
+ }
+
+ /**
+ * Returns the Spring configuration resource for the application context
+ */
+ public Resource getApplicationResource() {
+ return applicationResource;
+ }
+
+ /**
+ * Sets the Spring configuration resource for the application context
+ */
+ public void setApplicationResource(Resource applicationXml) {
+ this.applicationResource = applicationXml;
+ }
+}
diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/model/SpringServiceContract.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/model/SpringServiceContract.java
new file mode 100644
index 0000000000..3a88991e4b
--- /dev/null
+++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/model/SpringServiceContract.java
@@ -0,0 +1,31 @@
+/*
+ * 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.model;
+
+import org.apache.tuscany.spi.model.ServiceContract;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class SpringServiceContract extends ServiceContract {
+
+ public SpringServiceContract(String interfaceName) {
+ super(interfaceName);
+ }
+}
diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/webapp/ScaWebApplicationContext.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/webapp/ScaWebApplicationContext.java
new file mode 100644
index 0000000000..2284d32201
--- /dev/null
+++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/webapp/ScaWebApplicationContext.java
@@ -0,0 +1,130 @@
+/*
+ * 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.webapp;
+
+import java.io.File;
+import java.net.URL;
+
+import javax.servlet.ServletContext;
+
+import org.apache.tuscany.api.TuscanyRuntimeException;
+import org.apache.tuscany.container.spring.config.SCANamespaceHandlerResolver;
+import org.apache.tuscany.container.spring.impl.SpringScaAdapter;
+import org.apache.tuscany.container.spring.model.SpringComponentType;
+import org.apache.tuscany.runtime.webapp.WebappRuntime;
+import org.apache.tuscany.runtime.webapp.WebappUtil;
+import org.apache.tuscany.runtime.webapp.WebappUtilImpl;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.core.io.Resource;
+import org.springframework.sca.ScaAdapterAware;
+import org.springframework.sca.ScaAdapterPostProcessor;
+import org.springframework.util.Assert;
+import org.springframework.web.context.ConfigurableWebApplicationContext;
+import org.springframework.web.context.support.XmlWebApplicationContext;
+
+/**
+ * WebApplicationContext implementation that understands SCA extensions.
+ * This class is not very complicated, the key issue is getting hold of a reference
+ * to the Tuscany runtime which the webapp is using.
+ *
+ * @author Andy Piper
+ */
+public class ScaWebApplicationContext extends XmlWebApplicationContext
+ implements ConfigurableWebApplicationContext {
+ private WebappRuntime runtime;
+ private SpringComponentType componentType;
+
+ public ScaWebApplicationContext() {
+ }
+
+ protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) {
+// beanDefinitionReader.setEntityResolver(null);
+ beanDefinitionReader
+ .setNamespaceHandlerResolver(new SCANamespaceHandlerResolver(getClassLoader(), componentType));
+ }
+
+ public Resource getResource(String location) {
+ Assert.notNull(location, "location is required");
+ return super.getResource(location);
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.context.support.AbstractApplicationContext#postProcessBeanFactory(org.springframework.beans.factory.config.ConfigurableListableBeanFactory)
+ */
+ protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
+ super.postProcessBeanFactory(beanFactory);
+ beanFactory.addBeanPostProcessor(new ScaAdapterPostProcessor
+ (new SpringScaAdapter(componentType)));
+ beanFactory.ignoreDependencyInterface(ScaAdapterAware.class);
+ }
+
+ protected void onRefresh() {
+ if (runtime != null) { // egregious hack to prevent recursion in refresh()
+ return;
+ }
+ ServletContext servletContext = getServletContext();
+ WebappUtil utils = getUtils(servletContext);
+
+ try {
+ ClassLoader webappClassLoader = Thread.currentThread().getContextClassLoader();
+ ClassLoader bootClassLoader = utils.getBootClassLoader(webappClassLoader);
+ runtime = utils.getRuntime(bootClassLoader);
+ URL systemScdl = utils.getSystemScdl(bootClassLoader);
+ URL applicationScdl = utils.getApplicationScdl(webappClassLoader);
+
+ runtime.setMonitorFactory(runtime.createDefaultMonitorFactory());
+ runtime.setApplicationName(utils.getApplicationName());
+ runtime.setServletContext(servletContext);
+ runtime.setHostClassLoader(webappClassLoader);
+ runtime.setSystemScdl(systemScdl);
+ runtime.setApplicationScdl(applicationScdl);
+ runtime.setRuntimeInfo(new SpringWebappRuntimeInfo(getApplicationRootDirectory(), this));
+ runtime.initialize();
+ } catch (TuscanyRuntimeException e) {
+ servletContext.log(e.getMessage(), e);
+ throw e;
+ }
+ }
+
+ protected WebappUtil getUtils(ServletContext servletContext) {
+ return new WebappUtilImpl(servletContext);
+ }
+
+ protected void onClose() {
+ if (runtime != null) {
+ runtime.destroy();
+ runtime = null;
+ }
+ }
+
+ /**
+ * What does this do and why to we need it?
+ * @return
+ */
+ private File getApplicationRootDirectory() {
+ String property = System.getProperty("tuscany.applicationRootDir");
+ if (property != null) {
+ return new File(property);
+ }
+
+ return new File(System.getProperty("user.dir"));
+ }
+}
diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/webapp/SpringWebappRuntimeInfo.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/webapp/SpringWebappRuntimeInfo.java
new file mode 100644
index 0000000000..a860049462
--- /dev/null
+++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/webapp/SpringWebappRuntimeInfo.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.container.spring.webapp;
+
+import java.io.File;
+import javax.servlet.ServletContext;
+
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.XmlWebApplicationContext;
+
+import org.apache.tuscany.container.spring.impl.SpringRuntimeInfo;
+import org.apache.tuscany.runtime.webapp.WebappRuntimeInfo;
+
+/**
+ * @author Andy Piper
+ */
+public class SpringWebappRuntimeInfo extends SpringRuntimeInfo implements WebappRuntimeInfo {
+ public SpringWebappRuntimeInfo(File appRootDir, XmlWebApplicationContext applicationContext) {
+ super(appRootDir, applicationContext);
+ }
+
+ public ServletContext getServletContext() {
+ return ((WebApplicationContext) getApplicationContext()).getServletContext();
+ }
+}