summaryrefslogtreecommitdiffstats
path: root/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main')
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/config/SCANamespaceHandlerResolver.java59
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/config/ScaApplicationContext.java68
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringComponentTypeLoader.java109
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeBuilder.java88
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeComponent.java252
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringImplementationLoader.java196
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInterceptor.java53
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInvoker.java104
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringRuntimeInfo.java63
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringScaAdapter.java54
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/model/SpringComponentType.java101
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/model/SpringImplementation.java77
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/model/SpringServiceContract.java31
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/webapp/ScaWebApplicationContext.java130
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/webapp/SpringWebappRuntimeInfo.java41
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/DefaultScaAdapter.java46
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaAdapter.java45
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaAdapterAware.java31
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaAdapterPostProcessor.java52
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaComposite.java77
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaPostProcessor.java147
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaPropertyProxyFactoryBean.java123
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaServiceExporter.java105
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaServiceProxyFactoryBean.java144
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaCompositeBeanDefinitionParser.java67
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaContextBuilder.java68
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaNamespaceHandler.java44
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaPropertyBeanDefinitionParser.java63
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaReferenceBeanDefinitionParser.java66
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaServiceBeanDefinitionParser.java65
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/intercept/OneWayAdvisor.java82
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/AnnotationServiceMetadata.java95
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/BeanFactoryDeploymentMetadata.java55
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/DeploymentMetadata.java28
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/FieldInjection.java68
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/Injection.java76
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/MethodInjection.java65
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/NoSuchServiceException.java24
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/ServiceMetadata.java56
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/resources/META-INF/sca/spring.system.scdl40
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/resources/META-INF/spring.handlers3
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/resources/META-INF/spring.schemas1
-rw-r--r--sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/resources/org/springframework/sca/xml/spring-sca.xsd101
43 files changed, 3263 insertions, 0 deletions
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/config/SCANamespaceHandlerResolver.java b/sca-java-1.x/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/sca-java-1.x/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/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/config/ScaApplicationContext.java b/sca-java-1.x/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/sca-java-1.x/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/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringComponentTypeLoader.java b/sca-java-1.x/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/sca-java-1.x/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/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeBuilder.java b/sca-java-1.x/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/sca-java-1.x/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/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeComponent.java b/sca-java-1.x/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/sca-java-1.x/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/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringImplementationLoader.java b/sca-java-1.x/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/sca-java-1.x/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/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInterceptor.java b/sca-java-1.x/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/sca-java-1.x/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/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInvoker.java b/sca-java-1.x/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/sca-java-1.x/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/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringRuntimeInfo.java b/sca-java-1.x/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/sca-java-1.x/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/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringScaAdapter.java b/sca-java-1.x/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/sca-java-1.x/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/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/model/SpringComponentType.java b/sca-java-1.x/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/sca-java-1.x/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/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/model/SpringImplementation.java b/sca-java-1.x/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/sca-java-1.x/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/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/model/SpringServiceContract.java b/sca-java-1.x/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/sca-java-1.x/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/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/webapp/ScaWebApplicationContext.java b/sca-java-1.x/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/sca-java-1.x/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/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/webapp/SpringWebappRuntimeInfo.java b/sca-java-1.x/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/sca-java-1.x/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();
+ }
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/DefaultScaAdapter.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/DefaultScaAdapter.java
new file mode 100644
index 0000000000..e2071e27c3
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/DefaultScaAdapter.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ *
+ * Created on 11-Apr-2006 by Adrian Colyer
+ */
+package org.springframework.sca;
+
+/**
+ * @author Adrian Colyer
+ * @since 2.0
+ */
+public class DefaultScaAdapter implements ScaAdapter {
+
+ public Object getServiceReference(String referenceName,
+ Class referenceType,
+ String moduleName,
+ String defaultServiceName) {
+ // TODO
+ return new Object();
+ }
+
+ public Object getPropertyReference(String propertyName, Class propertyType, String moduleName) {
+ // TODO
+ return new Object();
+ }
+
+ public void publishAsService(Object serviceImplementation,
+ Class serviceInterface,
+ String serviceName,
+ String moduleName) {
+ // TODO
+ }
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaAdapter.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaAdapter.java
new file mode 100644
index 0000000000..e5aae6f0a2
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaAdapter.java
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ *
+ * Created on 11-Apr-2006 by Adrian Colyer
+ */
+package org.springframework.sca;
+
+/**
+ * Encapsulates interaction with an SCA runtime
+ *
+ * @author Adrian Colyer
+ * @since 2.0
+ */
+public interface ScaAdapter {
+
+ Object getServiceReference(
+ String referenceName,
+ Class referenceType,
+ String moduleName,
+ String defaultServiceName);
+
+ Object getPropertyReference(
+ String propertyName,
+ Class propertyType,
+ String moduleName);
+
+ void publishAsService(
+ Object serviceImplementation,
+ Class serviceInterface,
+ String serviceName,
+ String moduleName);
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaAdapterAware.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaAdapterAware.java
new file mode 100644
index 0000000000..abe975c936
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaAdapterAware.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.springframework.sca;
+
+/**
+ * /** Interface that enables beans to find the ScaAdapter they are defined with.
+ * <p/>
+ * Note that in most circumstances there is no need for a bean to implement this interface.
+ *
+ * @author Andy Piper
+ * @since 2.1
+ */
+public interface ScaAdapterAware {
+ void setScaAdapter(ScaAdapter adapter);
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaAdapterPostProcessor.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaAdapterPostProcessor.java
new file mode 100644
index 0000000000..b07be8f452
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaAdapterPostProcessor.java
@@ -0,0 +1,52 @@
+/*
+ * 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.springframework.sca;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+
+/**
+ * @author Andy Piper
+ * @since 2.1
+ */
+public class ScaAdapterPostProcessor implements BeanPostProcessor {
+ private ScaAdapter scaAdapter;
+
+ public ScaAdapterPostProcessor(ScaAdapter adapter) {
+ this.scaAdapter = adapter;
+ }
+
+ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+ if (bean instanceof ScaAdapterAware) {
+ if (this.scaAdapter == null) {
+ throw new IllegalStateException("Cannot satisfy ScaAdapterAware for bean '"
+ + beanName + "' without ScaAdapater");
+ }
+ ((ScaAdapterAware) bean).setScaAdapter(scaAdapter);
+ }
+ return bean;
+ }
+
+ public Object postProcessAfterInitialization(Object object, String string) throws BeansException {
+ return object;
+ }
+
+ public ScaAdapter getScaAdapter() {
+ return scaAdapter;
+ }
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaComposite.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaComposite.java
new file mode 100644
index 0000000000..e12e763d9f
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaComposite.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ *
+ * Created on 10-Apr-2006 by Adrian Colyer
+ */
+package org.springframework.sca;
+
+import org.springframework.beans.factory.InitializingBean;
+
+/**
+ * Bean that represents an Sca composite component. An instance of this bean is created when the &lt;sca:composite
+ * module-id="xxx"/&gt; element is declared.
+ *
+ * @author Adrian Colyer
+ * @since 2.0
+ */
+public class ScaComposite implements InitializingBean {
+
+ private String component;
+ private ScaAdapter scaAdapter = new DefaultScaAdapter();
+
+ public String getComponent() {
+ return this.component;
+ }
+
+ public void setComponent(String component) {
+ this.component = component;
+ }
+
+ public void setScaAdapter(ScaAdapter scaAdapter) {
+ this.scaAdapter = scaAdapter;
+ }
+
+ public void setScaAdapterClass(Class adapterClass) {
+ if (!ScaAdapter.class.isAssignableFrom(adapterClass)) {
+ throw new IllegalArgumentException(
+ "Adapter class '" + adapterClass + "' specified for ScaComposite bean "
+ + "does not implement the ScaApapter interface"
+ );
+ }
+ try {
+ this.scaAdapter = (ScaAdapter) adapterClass.newInstance();
+ } catch (Exception ex) {
+ // many exceptions may be thrown by the above, we treat them all
+ // the same
+ throw new IllegalStateException("Unable to create instance of ScaAdapter class '"
+ + adapterClass.getName() + "'", ex);
+ }
+ }
+
+ public ScaAdapter getScaAdapter() {
+ return this.scaAdapter;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
+ */
+ public void afterPropertiesSet() throws Exception {
+ if (this.component == null) {
+ throw new IllegalArgumentException("Required property moduleId was not set");
+ }
+ }
+
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaPostProcessor.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaPostProcessor.java
new file mode 100644
index 0000000000..f96af00584
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaPostProcessor.java
@@ -0,0 +1,147 @@
+/*
+ * 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.springframework.sca;
+
+import java.beans.PropertyDescriptor;
+
+import org.springframework.aop.framework.ProxyFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.PropertyValues;
+import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.core.task.TaskExecutor;
+import org.springframework.sca.intercept.OneWayAdvisor;
+import org.springframework.sca.metadata.DeploymentMetadata;
+import org.springframework.sca.metadata.Injection;
+import org.springframework.sca.metadata.NoSuchServiceException;
+import org.springframework.sca.metadata.ServiceMetadata;
+
+/**
+ * Spring bean post processor that looks up service metadata by name for each bean definition and performs SCA
+ * injection.
+ * <p/>
+ * Also performs proxying for OneWay.
+ *
+ * @author Rod Johnson
+ */
+public class ScaPostProcessor implements InstantiationAwareBeanPostProcessor, ApplicationContextAware {
+
+ private DeploymentMetadata deploymentMetadata;
+
+ private ApplicationContext applicationContext;
+
+ private TaskExecutor taskExecutor;
+
+ //private ScaAdapter scaAdapter;
+
+
+ /**
+ * @param taskExecutor The taskExecutor to set.
+ */
+ public void setTaskExecutor(TaskExecutor taskExecutor) {
+ this.taskExecutor = taskExecutor;
+ }
+
+ // TODO would process side files when container starts up
+
+ public void setDeploymentMetadata(DeploymentMetadata deploymentMetadata) {
+ this.deploymentMetadata = deploymentMetadata;
+ }
+
+ /**
+ * @param scaAdapter the ScaAdapter for use to export services if necessary
+ */
+ public void setScaAdapter(ScaAdapter scaAdapter) {
+ //this.scaAdapter = scaAdapter;
+ }
+
+
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ this.applicationContext = applicationContext;
+ }
+
+ public Object postProcessBeforeInstantiation(Class beanClass,
+ String beanName) throws BeansException {
+ return null;
+ }
+
+ public boolean postProcessAfterInstantiation(Object bean, String beanName)
+ throws BeansException {
+ try {
+ ServiceMetadata smd = deploymentMetadata.getServiceMetadata(beanName);
+ doScaInjection(bean, smd);
+ } catch (NoSuchServiceException ex) {
+ //
+ }
+ return true;
+ }
+
+ public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean,
+ String beanName) throws BeansException {
+ return pvs;
+ }
+
+ public PropertyValues postProcessPropertyValues(PropertyValues propertyValues, Object object, String string)
+ throws BeansException {
+ return propertyValues;
+ }
+
+ protected void doScaInjection(Object bean, ServiceMetadata smd) {
+ for (Injection injection : smd.getInjections()) {
+ injection.apply(applicationContext, bean);
+ }
+ }
+
+ public Object postProcessBeforeInitialization(Object bean, String beanName)
+ throws BeansException {
+ return bean;
+ }
+
+ public Object postProcessAfterInitialization(Object bean, String beanName)
+ throws BeansException {
+ try {
+ ServiceMetadata smd = deploymentMetadata.getServiceMetadata(beanName);
+ return createScaProxy(bean, smd);
+ } catch (NoSuchServiceException ex) {
+ return bean;
+ }
+
+ // TODO validate required injections here or earlier
+
+ // TODO publish if necessary, using adapter
+ }
+
+ protected Object createScaProxy(Object bean, ServiceMetadata smd) {
+ ProxyFactory pf = new ProxyFactory(bean);
+ for (Class intf : smd.getServiceInterfaces()) {
+ pf.addInterface(intf);
+ }
+
+//pf.addAdvisor(ExposeInvocationInterceptor.ADVISOR);
+//pf.addAdvisor(new ExposeBeanNameAdvisor(smd.getServiceName()));
+ // TODO enforce call by value
+
+ if (!smd.getOneWayMethods().isEmpty()) {
+ pf.addAdvisor(new OneWayAdvisor(smd, this.taskExecutor));
+ }
+
+ return pf.getProxy();
+ }
+
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaPropertyProxyFactoryBean.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaPropertyProxyFactoryBean.java
new file mode 100644
index 0000000000..e89072466a
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaPropertyProxyFactoryBean.java
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ *
+ * Created on 10-Apr-2006 by Adrian Colyer
+ */
+package org.springframework.sca;
+
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.InitializingBean;
+
+/**
+ * Factory bean that returns a reference to an SCA property obtained by asking the SCA runtime for the property with the
+ * given name for the given component.
+ *
+ * @author Adrian Colyer
+ * @since 2.0
+ */
+public class ScaPropertyProxyFactoryBean implements InitializingBean, FactoryBean {
+
+ /**
+ * the type of the property
+ */
+ private Class propertyType;
+
+ /**
+ * the name of the property to look up
+ */
+ private String propertyName;
+
+ /**
+ * the SCA component we should present ourselves as when asking for a service reference
+ */
+ private ScaComposite scaComposite;
+
+ private Object resolvedPropertyVal;
+
+ public void setPropertyType(Class serviceType) {
+ this.propertyType = serviceType;
+ }
+
+ public Class getPropertyType() {
+ return this.propertyType;
+ }
+
+ public void setPropertyName(String name) {
+ this.propertyName = name;
+ }
+
+ public String getPropertyName() {
+ return this.propertyName;
+ }
+
+ public void setScaComposite(ScaComposite scaComposite) {
+ this.scaComposite = scaComposite;
+ }
+
+ public ScaComposite getScaComposite() {
+ return this.scaComposite;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
+ */
+ public void afterPropertiesSet() throws Exception {
+ if (this.propertyType == null) {
+ throw new IllegalArgumentException("Required property serviceType was not set");
+ }
+ if (this.scaComposite == null) {
+ throw new IllegalArgumentException("Required property scaComposite was not set");
+ }
+ if (this.propertyName == null) {
+ throw new IllegalArgumentException("Required property referenceName was not set");
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.beans.factory.FactoryBean#getObject()
+ */
+ public Object getObject() throws Exception {
+ if (this.resolvedPropertyVal != null) {
+ return this.resolvedPropertyVal;
+ }
+
+ String moduleName = this.scaComposite.getComponent();
+ // TODO: AMC is there any merit in proxying this with a lazy target source?
+ Object propertyVal =
+ this.scaComposite.getScaAdapter().getPropertyReference(this.propertyName, this.propertyType, moduleName);
+ if (!this.propertyType.isAssignableFrom(propertyVal.getClass())) {
+ throw new IllegalStateException("Property value '" + propertyVal.toString() + "'"
+ + " of type '" + propertyVal.getClass().getName() + "' "
+ + " is not of expected type '" + this.propertyType.getName() + "'");
+ }
+ this.resolvedPropertyVal = propertyVal;
+ return this.resolvedPropertyVal;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.beans.factory.FactoryBean#getObjectType()
+ */
+ public Class getObjectType() {
+ return this.propertyType;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.beans.factory.FactoryBean#isSingleton()
+ */
+ public boolean isSingleton() {
+ return true;
+ }
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaServiceExporter.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaServiceExporter.java
new file mode 100644
index 0000000000..0155dd9646
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaServiceExporter.java
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ *
+ * Created on 10-Apr-2006 by Adrian Colyer
+ */
+package org.springframework.sca;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
+import org.springframework.beans.factory.InitializingBean;
+
+/**
+ * Exposes a bean instance to SCA to using the given service name.
+ *
+ * @author Adrian Colyer
+ * @since 2.0
+ */
+public class ScaServiceExporter implements InitializingBean, BeanFactoryAware, ScaAdapterAware {
+
+ /**
+ * the name of the service we want to advertise
+ */
+ private String serviceName;
+
+ /**
+ * the type the service should be published with
+ */
+ private Class serviceType;
+
+ /**
+ * the bean to be published
+ */
+ private Object target;
+
+ /**
+ * for resolving the bean name
+ */
+ private BeanFactory beanFactory;
+ private ScaAdapter scaAdapter;
+
+ public void setServiceName(String serviceName) {
+ this.serviceName = serviceName;
+ }
+
+ public String getServiceName() {
+ return this.serviceName;
+ }
+
+ public void setServiceType(Class serviceType) {
+ this.serviceType = serviceType;
+ }
+
+ public Class getServiceType() {
+ return this.serviceType;
+ }
+
+ public void setTarget(Object targetBean) {
+ this.target = targetBean;
+ }
+
+ public Object getTarget() {
+ return this.target;
+ }
+
+ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
+ this.beanFactory = beanFactory;
+ }
+
+ public void afterPropertiesSet() throws Exception {
+ if (this.serviceType == null) {
+ throw new IllegalArgumentException("Required property serviceType was not set");
+ }
+ if (this.target == null) {
+ throw new IllegalArgumentException("Required property target was not set");
+ }
+ if (this.beanFactory == null) {
+ throw new IllegalArgumentException("Required property beanFactory was not set");
+ }
+ if (this.serviceName == null) {
+ throw new IllegalArgumentException("Required property serviceName was not set");
+ }
+ publishScaService();
+ }
+
+ private void publishScaService() {
+ scaAdapter.publishAsService(target, serviceType, serviceName, null);
+ }
+
+ public void setScaAdapter(ScaAdapter adapter) {
+ this.scaAdapter = adapter;
+ }
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaServiceProxyFactoryBean.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaServiceProxyFactoryBean.java
new file mode 100644
index 0000000000..01ca5671d4
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/ScaServiceProxyFactoryBean.java
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ *
+ * Created on 10-Apr-2006 by Adrian Colyer
+ */
+package org.springframework.sca;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+/**
+ * Factory bean that returns a reference to an SCA service obtained by asking the SCA runtime for the service with the
+ * given name for the given component.
+ *
+ * @author Adrian Colyer
+ * @since 2.0
+ */
+public class ScaServiceProxyFactoryBean
+ implements InitializingBean, FactoryBean, ApplicationContextAware, ScaAdapterAware {
+
+ /**
+ * the public interface type of the service (may be a class...)
+ */
+ private Class serviceType;
+
+ /**
+ * the name of the reference to look up
+ */
+ private String referenceName;
+
+ /**
+ * the default service name to resolve the reference too
+ */
+ private String defaultServiceName;
+
+ private Object resolvedServiceReference;
+ private ApplicationContext applicationContext;
+ //private ScaAdapter scaAdapter;
+
+ public void setServiceType(Class serviceType) {
+ this.serviceType = serviceType;
+ }
+
+ public Class getServiceType() {
+ return this.serviceType;
+ }
+
+ public void setReferenceName(String name) {
+ this.referenceName = name;
+ }
+
+ public String getReferenceName() {
+ return this.referenceName;
+ }
+
+ public void setDefaultServiceName(String defaultService) {
+ this.defaultServiceName = defaultService;
+ }
+
+ public String getDefaultServiceName() {
+ return this.defaultServiceName;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
+ */
+ public void afterPropertiesSet() throws Exception {
+ if (this.serviceType == null) {
+ throw new IllegalArgumentException("Required property serviceType was not set");
+ }
+ if (this.referenceName == null) {
+ throw new IllegalArgumentException("Required property referenceName was not set");
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.beans.factory.FactoryBean#getObject()
+ */
+ public Object getObject() throws Exception {
+ if (this.resolvedServiceReference != null) {
+ return this.resolvedServiceReference;
+ }
+
+ // TODO: AMC is there any merit in proxying this with a lazy target source?
+ // should the returned service ref be proxied? Only seems to add value
+ // if SCA gives us any lifecycle events we can subscribe to and take
+ // meaningful action on...
+ // See OsgiServiceProxyFactoryBean for an example of how to do the
+ // proxying if needed.
+ Object scaServiceRef;
+ if (this.applicationContext.getParent() == null) {
+ return null;
+ }
+
+ if (!this.applicationContext.getParent().containsBean(this.referenceName)) {
+ return new Object();
+ //scaServiceRef = this.applicationContext.getParent().getBean(this.defaultServiceName);
+ } else {
+ scaServiceRef = this.applicationContext.getParent().getBean(this.referenceName);
+ }
+ if (!this.serviceType.isAssignableFrom(scaServiceRef.getClass())) {
+ throw new IllegalStateException("...");
+ }
+ this.resolvedServiceReference = scaServiceRef;
+ return this.resolvedServiceReference;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.beans.factory.FactoryBean#getObjectType()
+ */
+ public Class getObjectType() {
+ return this.serviceType;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.beans.factory.FactoryBean#isSingleton()
+ */
+ public boolean isSingleton() {
+ return false;
+ }
+
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ this.applicationContext = applicationContext;
+ }
+
+ public void setScaAdapter(ScaAdapter adapter) {
+ // this.scaAdapter = adapter;
+ }
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaCompositeBeanDefinitionParser.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaCompositeBeanDefinitionParser.java
new file mode 100644
index 0000000000..9c6ac633f7
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaCompositeBeanDefinitionParser.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ *
+ * Created on 10-Apr-2006 by Adrian Colyer
+ */
+package org.springframework.sca.config;
+
+import org.w3c.dom.Element;
+
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.beans.factory.xml.BeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.sca.ScaComposite;
+
+/**
+ * Parser for &lt;sca:composite&gt; elements
+ *
+ * @author Adrian Colyer
+ * @since 2.0
+ */
+public class ScaCompositeBeanDefinitionParser implements BeanDefinitionParser {
+
+ static final String SCA_COMPOSITE_BEAN_NAME = "scaComposite";
+ private static final String MODULE_ATTRIBUTE_NAME = "component";
+ private static final String MODULE_ID = "component";
+ private static final String ADAPTER_ATTRIBUTE = "sca-adapter-class";
+ private static final String ADAPTER_CLASS_PROPERTY = "scaAdapterClass";
+
+ public BeanDefinition parse(Element element, ParserContext parserContext) {
+ BeanDefinitionRegistry registry = parserContext.getRegistry();
+ if (registry.containsBeanDefinition(SCA_COMPOSITE_BEAN_NAME)) {
+ throw new IllegalArgumentException(
+ "At most one <sca:composite> element can be declared in a bean factory");
+ }
+ BeanDefinition beanDef = createScaCompositeBeanDefinition(element);
+ registry.registerBeanDefinition(SCA_COMPOSITE_BEAN_NAME, beanDef);
+ return beanDef;
+ }
+
+ private BeanDefinition createScaCompositeBeanDefinition(Element element) {
+ RootBeanDefinition beanDefinition = new RootBeanDefinition();
+ beanDefinition.setBeanClass(ScaComposite.class);
+ MutablePropertyValues props = new MutablePropertyValues();
+ props.addPropertyValue(MODULE_ID, element.getAttribute(MODULE_ATTRIBUTE_NAME));
+ if (element.hasAttribute(ADAPTER_ATTRIBUTE)) {
+ props.addPropertyValue(ADAPTER_CLASS_PROPERTY, element.getAttribute(ADAPTER_ATTRIBUTE));
+ }
+ beanDefinition.setPropertyValues(props);
+ return beanDefinition;
+ }
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaContextBuilder.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaContextBuilder.java
new file mode 100644
index 0000000000..3446aaf462
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaContextBuilder.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ *
+ * Created on 10-Apr-2006 by Adrian Colyer
+ */
+package org.springframework.sca.config;
+
+import org.springframework.beans.PropertyValue;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.GenericApplicationContext;
+import org.springframework.sca.ScaAdapter;
+import org.springframework.sca.ScaComposite;
+
+/**
+ * @author Hal Hildebrand Date: Apr 11, 2006 Time: 4:33:33 PM
+ */
+public class ScaContextBuilder {
+ private static final String MODULE_ID = "moduleId";
+
+ private static final String SCA_ADAPTER = "scaAdapter";
+
+ private static final String SCA_COMPOSITE_BEAN_NAME = "scaComposite";
+
+ private String moduleId;
+
+ private ScaAdapter scaAdapter;
+
+ public String getModuleId() {
+ return this.moduleId;
+ }
+
+ public void setModuleId(String moduleId) {
+ this.moduleId = moduleId;
+ }
+
+ public void setScaAdapter(ScaAdapter scaAdapter) {
+ this.scaAdapter = scaAdapter;
+ }
+
+ public ScaAdapter getScaAdapter() {
+ return this.scaAdapter;
+ }
+
+ public ApplicationContext construct() {
+ GenericApplicationContext parent = new GenericApplicationContext();
+ BeanDefinition bd = new RootBeanDefinition(ScaComposite.class, true);
+
+ bd.getPropertyValues().addPropertyValue(new PropertyValue(MODULE_ID, moduleId));
+ bd.getPropertyValues().addPropertyValue(new PropertyValue(SCA_ADAPTER, scaAdapter));
+ parent.registerBeanDefinition(SCA_COMPOSITE_BEAN_NAME, bd);
+ parent.refresh();
+ return parent;
+ }
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaNamespaceHandler.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaNamespaceHandler.java
new file mode 100644
index 0000000000..878267813a
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaNamespaceHandler.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ *
+ * Created on 10-Apr-2006 by Adrian Colyer
+ */
+package org.springframework.sca.config;
+
+import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
+
+/**
+ * Handler for the &lt;sca:&gt; namespace. Handles: <ul> <li>&lt;sca:composite module="xxxxx"/&gt;</li>
+ * <li>&lt;sca:reference name="xxx" type="yyy" default-service="zzz"/&gt;</li> <li>&lt;sca:property name="xxx"
+ * type="yyy"/&gt;</li> <li>&lt;sca:service name="xxx" type="yyyy" target="zzz"/&gt; </ul>
+ *
+ * @author Adrian Colyer
+ * @since 2.0
+ */
+public class ScaNamespaceHandler extends NamespaceHandlerSupport {
+
+ public ScaNamespaceHandler() {
+ // FIXME JFM
+ init();
+ }
+
+ public final void init() {
+ registerBeanDefinitionParser("composite", new ScaCompositeBeanDefinitionParser());
+ registerBeanDefinitionParser("reference", new ScaReferenceBeanDefinitionParser());
+ registerBeanDefinitionParser("property", new ScaPropertyBeanDefinitionParser());
+ registerBeanDefinitionParser("service", new ScaServiceBeanDefinitionParser());
+ }
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaPropertyBeanDefinitionParser.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaPropertyBeanDefinitionParser.java
new file mode 100644
index 0000000000..55413b69da
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaPropertyBeanDefinitionParser.java
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ *
+ * Created on 10-Apr-2006 by Adrian Colyer
+ */
+package org.springframework.sca.config;
+
+import org.w3c.dom.Element;
+
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.beans.factory.xml.BeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.sca.ScaPropertyProxyFactoryBean;
+
+/**
+ * Parser for the &lt;sca:property/&gt; element
+ *
+ * @author Adrian Colyer
+ * @since 2.0
+ */
+public class ScaPropertyBeanDefinitionParser implements BeanDefinitionParser {
+
+ private static final String PROPERTY_NAME_ATTRIBUTE = "name";
+ private static final String PROPERTY_NAME_PROPERTY = "propertyName";
+ private static final String PROPERTY_TYPE_PROPERTY = "propertyType";
+ private static final String TYPE_ATTRIBUTE = "type";
+ private static final String ID_ATTRIBUTE = "id";
+
+ public BeanDefinition parse(Element element, ParserContext parserContext) {
+ // needs service type, reference name, sca component, and optionally default service name
+ BeanDefinitionRegistry registry = parserContext.getRegistry();
+ String beanName = element.getAttribute(ID_ATTRIBUTE);
+ BeanDefinition beanDef = createBeanDefinition(element);
+ registry.registerBeanDefinition(beanName, beanDef);
+ return beanDef;
+ }
+
+ private BeanDefinition createBeanDefinition(Element element) {
+ RootBeanDefinition beanDefinition = new RootBeanDefinition();
+ beanDefinition.setBeanClass(ScaPropertyProxyFactoryBean.class);
+ MutablePropertyValues props = new MutablePropertyValues();
+ props.addPropertyValue(PROPERTY_NAME_PROPERTY, element.getAttribute(PROPERTY_NAME_ATTRIBUTE));
+ props.addPropertyValue(PROPERTY_TYPE_PROPERTY, element.getAttribute(TYPE_ATTRIBUTE));
+ beanDefinition.setPropertyValues(props);
+ return beanDefinition;
+ }
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaReferenceBeanDefinitionParser.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaReferenceBeanDefinitionParser.java
new file mode 100644
index 0000000000..4f4d196571
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaReferenceBeanDefinitionParser.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ *
+ * Created on 10-Apr-2006 by Adrian Colyer
+ */
+package org.springframework.sca.config;
+
+import org.w3c.dom.Element;
+
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.beans.factory.xml.BeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.sca.ScaServiceProxyFactoryBean;
+
+/**
+ * Parser for the &lt;sca:reference&gt; element
+ *
+ * @author Adrian Colyer
+ * @since 2.0
+ */
+public class ScaReferenceBeanDefinitionParser implements BeanDefinitionParser {
+
+ private static final String REFERENCE_NAME_ATTRIBUTE = "name";
+ private static final String REFERENCE_NAME_PROPERTY = "referenceName";
+ private static final String TYPE_ATTRIBUTE = "type";
+ private static final String SERVICE_TYPE_PROPERTY = "serviceType";
+ private static final String DEFAULT_SERVICE_ATTRIBUTE = "default";
+ private static final String DEFAULT_SERVICE_PROPERTY = "defaultServiceName";
+
+ public BeanDefinition parse(Element element, ParserContext parserContext) {
+ // needs service type, reference name, sca component, and optionally default service name
+ BeanDefinitionRegistry registry = parserContext.getRegistry();
+ String referenceName = element.getAttribute(REFERENCE_NAME_ATTRIBUTE);
+ BeanDefinition beanDef = createBeanDefinition(element);
+ registry.registerBeanDefinition(referenceName, beanDef);
+ return beanDef;
+ }
+
+ private BeanDefinition createBeanDefinition(Element element) {
+ RootBeanDefinition beanDefinition = new RootBeanDefinition();
+ beanDefinition.setBeanClass(ScaServiceProxyFactoryBean.class);
+ MutablePropertyValues props = new MutablePropertyValues();
+ props.addPropertyValue(REFERENCE_NAME_PROPERTY, element.getAttribute(REFERENCE_NAME_ATTRIBUTE));
+ props.addPropertyValue(SERVICE_TYPE_PROPERTY, element.getAttribute(TYPE_ATTRIBUTE));
+ if (element.hasAttribute(DEFAULT_SERVICE_ATTRIBUTE)) {
+ props.addPropertyValue(DEFAULT_SERVICE_PROPERTY, element.getAttribute(DEFAULT_SERVICE_ATTRIBUTE));
+ }
+ beanDefinition.setPropertyValues(props);
+ return beanDefinition;
+ }
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaServiceBeanDefinitionParser.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaServiceBeanDefinitionParser.java
new file mode 100644
index 0000000000..5867236faa
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/config/ScaServiceBeanDefinitionParser.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ *
+ * Created on 10-Apr-2006 by Adrian Colyer
+ */
+package org.springframework.sca.config;
+
+import org.w3c.dom.Element;
+
+import org.springframework.beans.MutablePropertyValues;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.beans.factory.xml.BeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.sca.ScaServiceExporter;
+
+/**
+ * Parser for the &lt;sca:service/&gt; element
+ *
+ * @author Adrian Colyer
+ * @since 2.0
+ */
+public class ScaServiceBeanDefinitionParser implements BeanDefinitionParser {
+
+ private static final String SERVICE_NAME_ATTRIBUTE = "name";
+ private static final String TYPE_ATTRIBUTE = "type";
+ private static final String TARGET_ATTRIBUTE = "target";
+ private static final String SERVICE_NAME_PROPERTY = "serviceName";
+ private static final String SERVICE_TYPE_PROPERTY = "serviceType";
+ private static final String TARGET_PROPERTY = "target";
+
+ public BeanDefinition parse(Element element, ParserContext parserContext) {
+ BeanDefinitionRegistry registry = parserContext.getRegistry();
+ String serviceName = element.getAttribute(SERVICE_NAME_ATTRIBUTE);
+ BeanDefinition beanDef = createBeanDefinition(element);
+ registry.registerBeanDefinition(serviceName, beanDef);
+ return beanDef;
+ }
+
+ private BeanDefinition createBeanDefinition(Element element) {
+ RootBeanDefinition beanDefinition = new RootBeanDefinition();
+ beanDefinition.setBeanClass(ScaServiceExporter.class);
+ MutablePropertyValues props = new MutablePropertyValues();
+ props.addPropertyValue(SERVICE_TYPE_PROPERTY, element.getAttribute(TYPE_ATTRIBUTE));
+ props.addPropertyValue(TARGET_PROPERTY, new RuntimeBeanReference(element.getAttribute(TARGET_ATTRIBUTE)));
+ props.addPropertyValue(SERVICE_NAME_PROPERTY, element.getAttribute(SERVICE_NAME_ATTRIBUTE));
+ beanDefinition.setPropertyValues(props);
+ return beanDefinition;
+ }
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/intercept/OneWayAdvisor.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/intercept/OneWayAdvisor.java
new file mode 100644
index 0000000000..60bf2a344d
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/intercept/OneWayAdvisor.java
@@ -0,0 +1,82 @@
+/*
+ * 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.springframework.sca.intercept;
+
+import java.lang.reflect.Method;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+import org.springframework.aop.framework.ReflectiveMethodInvocation;
+import org.springframework.aop.support.DefaultPointcutAdvisor;
+import org.springframework.aop.support.StaticMethodMatcherPointcut;
+import org.springframework.core.task.TaskExecutor;
+import org.springframework.sca.metadata.ServiceMetadata;
+
+/**
+ * An AOP Alliance MethodInterceptor, rather than AspectJ aspect, as there's no value in typed pointcuts. Oh, if it were
+ * only annotations...
+ *
+ * @author Rod Johnson
+ */
+
+public class OneWayAdvisor extends DefaultPointcutAdvisor {
+
+ private TaskExecutor taskExecutor;
+
+ private final ServiceMetadata smd;
+
+ public OneWayAdvisor(final ServiceMetadata aSmd, TaskExecutor taskExecutor) {
+ this.smd = aSmd;
+ setPointcut(new StaticMethodMatcherPointcut() {
+ public boolean matches(Method method, Class targetClass) {
+ for (Method m : smd.getOneWayMethods()) {
+ if (m.getName().equals(method.getName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+ });
+ setAdvice(new OneWayInterceptor());
+ this.taskExecutor = taskExecutor;
+ }
+
+
+ private class OneWayInterceptor implements MethodInterceptor {
+ public Object invoke(MethodInvocation mi) throws Throwable {
+ try {
+ // TODO this is not right
+ ReflectiveMethodInvocation rmi = (ReflectiveMethodInvocation) mi;
+ final MethodInvocation clone = rmi.invocableClone();
+ System.out.println("EXECUTE DEFERRED");
+ taskExecutor.execute(new Runnable() {
+ public void run() {
+ try {
+ clone.proceed();
+ } catch (Throwable ex) {
+ // TODO
+ throw new UnsupportedOperationException();
+ }
+ }
+ });
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+ return null;
+ }
+ }
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/AnnotationServiceMetadata.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/AnnotationServiceMetadata.java
new file mode 100644
index 0000000000..9a04831ab8
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/AnnotationServiceMetadata.java
@@ -0,0 +1,95 @@
+/*
+ * 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.springframework.sca.metadata;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.osoa.sca.annotations.ComponentName;
+import org.osoa.sca.annotations.OneWay;
+import org.osoa.sca.annotations.Property;
+import org.osoa.sca.annotations.Service;
+
+import org.springframework.util.ReflectionUtils;
+
+/**
+ * TODO not the way to get this
+ *
+ * @author Rod Johnson
+ */
+public class AnnotationServiceMetadata implements ServiceMetadata {
+
+ private final String name;
+
+ private final Class<?> serviceClass;
+
+ public AnnotationServiceMetadata(String name, Class<?> serviceClass) throws NoSuchServiceException {
+ if (!serviceClass.isAnnotationPresent(Service.class)) {
+ throw new NoSuchServiceException();
+ }
+ this.name = name;
+ this.serviceClass = serviceClass;
+ }
+
+ public String getServiceName() {
+ return name;
+ }
+
+ public Class<?>[] getServiceInterfaces() {
+ return serviceClass.getAnnotation(Service.class).interfaces();
+ }
+
+ public List<Method> getOneWayMethods() {
+ List<Method> oneWayMethods = new LinkedList<Method>();
+ for (Method m : serviceClass.getMethods()) {
+ if (m.isAnnotationPresent(OneWay.class)) {
+ oneWayMethods.add(m);
+ }
+ }
+
+ // TODO fields
+
+ return oneWayMethods;
+ }
+
+ public List<Injection> getInjections() {
+ final List<Injection> injections = new LinkedList<Injection>();
+ for (Method m : serviceClass.getMethods()) {
+ if (m.isAnnotationPresent(Property.class)) {
+ injections.add(new MethodInjection(m));
+ }
+ }
+
+ // TODO fields propertly
+
+ ReflectionUtils.doWithFields(serviceClass, new ReflectionUtils.FieldCallback() {
+ public void doWith(Field f) throws IllegalArgumentException {
+ if (f.isAnnotationPresent(ComponentName.class)) {
+ Injection componentNameInjection = new FieldInjection(f);
+ componentNameInjection.setLiteralValue(name);
+ injections.add(componentNameInjection);
+ }
+ }
+ });
+
+ return injections;
+ }
+
+ // TODO reference
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/BeanFactoryDeploymentMetadata.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/BeanFactoryDeploymentMetadata.java
new file mode 100644
index 0000000000..b819ad8f8d
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/BeanFactoryDeploymentMetadata.java
@@ -0,0 +1,55 @@
+/*
+ * 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.springframework.sca.metadata;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
+
+/**
+ * DeploymentMetadata implementation backed by Spring BeanFactory metadata
+ *
+ * @author Rod Johnson
+ */
+public class BeanFactoryDeploymentMetadata implements BeanFactoryAware, DeploymentMetadata {
+
+ private BeanFactory beanFactory;
+
+ private Map<String, ServiceMetadata> serviceNameToMetadataMap = new HashMap<String, ServiceMetadata>();
+
+ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
+ this.beanFactory = beanFactory;
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.springframework.sca.metadata.DeploymentMetadata#getServiceMetadata(java.lang.String)
+ */
+ public synchronized ServiceMetadata getServiceMetadata(String serviceName) throws NoSuchServiceException {
+ ServiceMetadata sm = serviceNameToMetadataMap.get(serviceName);
+ if (sm == null) {
+ Class clazz = beanFactory.getType(serviceName);
+ sm = new AnnotationServiceMetadata(serviceName, clazz);
+ serviceNameToMetadataMap.put(serviceName, sm);
+ }
+ return sm;
+ }
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/DeploymentMetadata.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/DeploymentMetadata.java
new file mode 100644
index 0000000000..950e5e3786
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/DeploymentMetadata.java
@@ -0,0 +1,28 @@
+/*
+ * 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.springframework.sca.metadata;
+
+/**
+ * Source of ServiceMetadata by name
+ *
+ * @author Rod Johnson
+ */
+public interface DeploymentMetadata {
+
+ ServiceMetadata getServiceMetadata(String serviceName) throws NoSuchServiceException;
+
+} \ No newline at end of file
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/FieldInjection.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/FieldInjection.java
new file mode 100644
index 0000000000..3d9f1b6e79
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/FieldInjection.java
@@ -0,0 +1,68 @@
+/*
+ * 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.springframework.sca.metadata;
+
+import java.lang.reflect.Field;
+
+import org.osoa.sca.annotations.Reference;
+
+/**
+ * @author Rod Johnson
+ */
+public class FieldInjection extends Injection {
+
+ private final Field field;
+
+ public FieldInjection(Field field, String lookupName) {
+ super(lookupName);
+ this.field = field;
+ }
+
+ public FieldInjection(Field field) {
+ Reference annotation = field.getAnnotation(Reference.class);
+
+ this.field = field;
+
+ if (annotation == null) {
+ //throw new IllegalArgumentException("Field " + field + " not annotated");
+ return;
+ }
+
+ if ("".equals(annotation.name())) {
+ setLookupName(field.getName());
+ } else {
+ setLookupName(annotation.name());
+ }
+ }
+
+ @Override
+ protected void injectValue(Object target, Object value) {
+ try {
+ if (!field.isAccessible()) {
+ field.setAccessible(true);
+ }
+ field.set(target, value);
+ } catch (IllegalArgumentException ex) {
+ // TODO
+ throw new UnsupportedOperationException();
+ } catch (IllegalAccessException ex) {
+ // TODO
+ ex.printStackTrace();
+ throw new UnsupportedOperationException();
+ }
+ }
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/Injection.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/Injection.java
new file mode 100644
index 0000000000..2e81516d56
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/Injection.java
@@ -0,0 +1,76 @@
+/*
+ * 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.springframework.sca.metadata;
+
+import org.springframework.beans.factory.BeanFactory;
+
+/**
+ * @author Rod Johnson
+ */
+public abstract class Injection {
+
+ private String lookupName;
+
+ /**
+ * Is it a literal value?
+ */
+ private boolean literal;
+
+ /**
+ * Literal value if it's a literal
+ */
+ private Object literalValue;
+
+ protected Injection() {
+
+ }
+
+ protected Injection(String lookupName) {
+ this.lookupName = lookupName;
+ }
+
+ public Object getLiteralValue() {
+ return literalValue;
+ }
+
+ public void setLiteralValue(Object literalValue) {
+ this.literal = true;
+ this.literalValue = literalValue;
+ }
+
+ public boolean isLiteral() {
+ return literal;
+ }
+
+ protected void setLookupName(String lookupName) {
+ this.lookupName = lookupName;
+ }
+
+ public String getLookupName() {
+ return lookupName;
+ }
+
+ public void apply(BeanFactory owner, Object target) {
+ Object value = literalValue;
+ if (!isLiteral()) {
+ value = owner.getBean(lookupName);
+ }
+ injectValue(target, value);
+ }
+
+ protected abstract void injectValue(Object target, Object value);
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/MethodInjection.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/MethodInjection.java
new file mode 100644
index 0000000000..df01d1428d
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/MethodInjection.java
@@ -0,0 +1,65 @@
+/*
+ * 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.springframework.sca.metadata;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import org.osoa.sca.annotations.Property;
+
+/**
+ * @author Rod Johnson
+ */
+public class MethodInjection extends Injection {
+
+ private final Method method;
+
+ public MethodInjection(Method method, String lookupName) {
+ super(lookupName);
+ this.method = method;
+ }
+
+ public MethodInjection(Method method) {
+ // TODO reference also
+ Property annotation = method.getAnnotation(Property.class);
+ if (annotation == null) {
+ throw new IllegalArgumentException("Method " + method + " not annotated");
+ }
+ this.method = method;
+ if ("".equals(annotation.name())) {
+ setLookupName(method.getName());
+ } else {
+ setLookupName(annotation.name());
+ }
+ }
+
+ @Override
+ protected void injectValue(Object target, Object value) {
+ try {
+ method.invoke(target, value);
+ } catch (IllegalArgumentException ex) {
+ // TODO
+ throw new UnsupportedOperationException();
+ } catch (IllegalAccessException ex) {
+ // TODO
+ throw new UnsupportedOperationException();
+ } catch (InvocationTargetException ex) {
+ // TODO
+ throw new UnsupportedOperationException();
+ }
+ }
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/NoSuchServiceException.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/NoSuchServiceException.java
new file mode 100644
index 0000000000..b7ffdfeee6
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/NoSuchServiceException.java
@@ -0,0 +1,24 @@
+/*
+ * 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.springframework.sca.metadata;
+
+/**
+ * @author Rod Johnson
+ */
+public class NoSuchServiceException extends Exception {
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/ServiceMetadata.java b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/ServiceMetadata.java
new file mode 100644
index 0000000000..5d23c499e4
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/springframework/sca/metadata/ServiceMetadata.java
@@ -0,0 +1,56 @@
+/*
+ * 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.springframework.sca.metadata;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * Metadata for an SCA component.
+ *
+ * @author Rod Johnson
+ */
+public interface ServiceMetadata {
+
+ /**
+ * Return the service name
+ *
+ * @return the service name of the component
+ */
+ String getServiceName();
+
+ /**
+ * Return the service interfaces implemented by the component
+ *
+ * @return interfaces implemented by the component
+ */
+ Class<?>[] getServiceInterfaces();
+
+ /**
+ * Return a list of OneWay methods
+ *
+ * @return never returns null
+ */
+ List<Method> getOneWayMethods();
+
+ /**
+ * Return a list of SCA injections
+ * @return a list of SCA injections. Never returns null.
+ */
+ List<Injection> getInjections();
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/resources/META-INF/sca/spring.system.scdl b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/resources/META-INF/sca/spring.system.scdl
new file mode 100644
index 0000000000..cbd7138f0d
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/resources/META-INF/sca/spring.system.scdl
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ -->
+<!--
+ Spring implementation extension configuration for the launcher environment.
+-->
+<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
+ xmlns:system="http://incubator.apache.org/tuscany/xmlns/system/1.0-incubator-M2"
+
+ name="org.apache.tuscany.launcher.SpringImplementation">
+
+ <component name="spring.implementationLoader">
+ <system:implementation.system class="org.apache.tuscany.container.spring.impl.SpringImplementationLoader"/>
+ </component>
+
+ <component name="spring.componentTypeLoader">
+ <system:implementation.system class="org.apache.tuscany.container.spring.impl.SpringComponentTypeLoader"/>
+ </component>
+
+ <component name="spring.componentBuilder">
+ <system:implementation.system class="org.apache.tuscany.container.spring.impl.SpringCompositeBuilder"/>
+ </component>
+
+</composite> \ No newline at end of file
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/resources/META-INF/spring.handlers b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/resources/META-INF/spring.handlers
new file mode 100644
index 0000000000..689b49e2ae
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/resources/META-INF/spring.handlers
@@ -0,0 +1,3 @@
+http\://www.springframework.org/schema/sca=org.springframework.sca.config.ScaNamespaceHandler
+
+
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/resources/META-INF/spring.schemas b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/resources/META-INF/spring.schemas
new file mode 100644
index 0000000000..33f7004be9
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/resources/META-INF/spring.schemas
@@ -0,0 +1 @@
+http\://www.springframework.org/schema/sca/spring-sca.xsd=org/springframework/sca/xml/spring-sca.xsd
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/resources/org/springframework/sca/xml/spring-sca.xsd b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/resources/org/springframework/sca/xml/spring-sca.xsd
new file mode 100644
index 0000000000..b4eeadbb74
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-M2/sca/services/containers/container.spring/src/main/resources/org/springframework/sca/xml/spring-sca.xsd
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<xsd:schema xmlns="http://www.springframework.org/schema/sca"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
+ targetNamespace="http://www.springframework.org/schema/sca">
+
+ <xsd:element name="composite">
+ <xsd:complexType>
+ <xsd:attribute name="component" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string"/>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="sca-adapter-class" use="optional">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string"/>
+ </xsd:simpleType>
+ </xsd:attribute>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="reference">
+ <xsd:complexType>
+ <xsd:attribute name="name" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string"/>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="type" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string"/>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="default" use="optional">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string"/>
+ </xsd:simpleType>
+ </xsd:attribute>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="property">
+ <xsd:complexType>
+ <xsd:attribute name="id" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string"/>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="name" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string"/>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="type" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string"/>
+ </xsd:simpleType>
+ </xsd:attribute>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="service">
+ <xsd:complexType>
+ <xsd:attribute name="name" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string"/>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="type" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string"/>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="target" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:string"/>
+ </xsd:simpleType>
+ </xsd:attribute>
+ </xsd:complexType>
+ </xsd:element>
+
+</xsd:schema>