From bdd0a41aed7edf21ec2a65cfa17a86af2ef8c48a Mon Sep 17 00:00:00 2001 From: dims Date: Tue, 17 Jun 2008 00:23:01 +0000 Subject: Move Tuscany from Incubator to top level. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@668359 13f79535-47bb-0310-9956-ffa450edef68 --- .../spring/impl/SpringComponentTypeLoader.java | 109 +++++++++ .../spring/impl/SpringCompositeBuilder.java | 88 +++++++ .../spring/impl/SpringCompositeComponent.java | 252 +++++++++++++++++++++ .../spring/impl/SpringImplementationLoader.java | 196 ++++++++++++++++ .../container/spring/impl/SpringInterceptor.java | 53 +++++ .../container/spring/impl/SpringInvoker.java | 104 +++++++++ .../container/spring/impl/SpringRuntimeInfo.java | 63 ++++++ .../container/spring/impl/SpringScaAdapter.java | 54 +++++ 8 files changed, 919 insertions(+) create mode 100644 branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringComponentTypeLoader.java create mode 100644 branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeBuilder.java create mode 100644 branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeComponent.java create mode 100644 branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringImplementationLoader.java create mode 100644 branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInterceptor.java create mode 100644 branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInvoker.java create mode 100644 branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringRuntimeInfo.java create mode 100644 branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringScaAdapter.java (limited to 'branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl') diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringComponentTypeLoader.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringComponentTypeLoader.java new file mode 100644 index 0000000000..fa815eee78 --- /dev/null +++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringComponentTypeLoader.java @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.container.spring.impl; + +import org.springframework.context.support.AbstractRefreshableApplicationContext; +import org.springframework.core.io.Resource; +import org.springframework.sca.ScaServiceExporter; + +import org.apache.tuscany.container.spring.config.ScaApplicationContext; +import org.apache.tuscany.container.spring.model.SpringComponentType; +import org.apache.tuscany.container.spring.model.SpringImplementation; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.ComponentTypeLoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.host.RuntimeInfo; + +/** + * Loads a component type for a Spring ApplicationContext. 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 { + 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 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 elements, they define (and limit) the services exposed + // in the componentType. + String [] serviceBeanNames = ctx.getBeanNamesForType(ScaServiceExporter.class); + for (String serviceBeanName : serviceBeanNames) { + int nSuffix = serviceBeanName.indexOf(SERVICE_BEAN_SUFFIX); + if (nSuffix == -1) { + continue; + } + + String serviceName = serviceBeanName.substring(0, nSuffix); + ScaServiceExporter serviceBean = (ScaServiceExporter) ctx.getBean(serviceName); + // REVIEW andyp -- use the class directly? + String serviceTypeName = serviceBean.getServiceType().getName(); + try { + Class serviceInterface = Class.forName(serviceTypeName, true, deploymentContext.getClassLoader()); + componentType.addServiceType(serviceName, serviceInterface); + //ServiceDefinition service = createService(serviceInterface); + //componentType.getServices().put(serviceName, service); + } catch (ClassNotFoundException e) { + throw new LoaderException(e); + } + } + // if no service tags are specified, expose all beans + componentType.setExposeAllBeans(componentType.getServiceTypes().isEmpty()); + implementation.setComponentType(componentType); + } +} diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeBuilder.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeBuilder.java new file mode 100644 index 0000000000..6ec5d8fdd7 --- /dev/null +++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeBuilder.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.container.spring.impl; + +import org.apache.tuscany.spi.QualifiedName; +import org.apache.tuscany.spi.builder.BuilderConfigException; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.Reference; +import org.apache.tuscany.spi.component.Service; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.ComponentBuilderExtension; +import org.apache.tuscany.spi.model.Binding; +import org.apache.tuscany.spi.model.BoundReferenceDefinition; +import org.apache.tuscany.spi.model.BoundServiceDefinition; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; + +import org.apache.tuscany.container.spring.model.SpringImplementation; +import org.springframework.context.support.AbstractApplicationContext; + +/** + * Creates a {@link org.apache.tuscany.container.spring.impl.SpringCompositeComponent} from an assembly model + * + * @version $$Rev$$ $$Date$$ + */ +public class SpringCompositeBuilder extends ComponentBuilderExtension { + + public Component build(CompositeComponent parent, + ComponentDefinition 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, + BoundReferenceDefinition, + ? 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 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 getImplementationType() { + return SpringImplementation.class; + } +} diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeComponent.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeComponent.java new file mode 100644 index 0000000000..b30202cb96 --- /dev/null +++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringCompositeComponent.java @@ -0,0 +1,252 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.container.spring.impl; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.Locale; +import java.util.Map; + +import org.w3c.dom.Document; + +import org.apache.tuscany.spi.builder.Connector; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.Reference; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.component.Service; +import org.apache.tuscany.spi.extension.CompositeComponentExtension; +import static org.apache.tuscany.spi.idl.java.JavaIDLUtils.findMethod; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.TargetInvoker; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanNotOfRequiredTypeException; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.MessageSourceResolvable; +import org.springframework.context.NoSuchMessageException; +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.core.io.Resource; + +/** + * A composite implementation responsible for managing Spring application contexts. + * + * @version $$Rev$$ $$Date$$ + */ +public class SpringCompositeComponent extends CompositeComponentExtension { + private static final String[] EMPTY_ARRAY = new String[0]; + private AbstractApplicationContext springContext; + + /** + * Creates a new composite + * + * @param name the name of the SCA composite + * @param springContext the pre-instantiated Spring applicaiton context + * @param parent the SCA composite parent + * @param connector the connector to use for wiring children + * @param propertyValues the values of this composite's Properties + */ + public SpringCompositeComponent(String name, + AbstractApplicationContext springContext, + CompositeComponent parent, + Connector connector, + Map 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 locateService(Class serviceInterface, String name) { + return serviceInterface.cast(springContext.getBean(name)); + } + + /** + * An inner class is required to act as the Spring application context parent as opposed to implementing the + * interface since the return types for {@link org.springframework.context.ApplicationContext#getParent()} and + * {@link org.apache.tuscany.spi.component.CompositeComponent#getParent()} clash + */ + private class SCAApplicationContext implements ApplicationContext { + + public Object getBean(String name) throws BeansException { + return getBean(name, null); + } + + public Object getBean(String name, Class requiredType) throws BeansException { + SCAObject object = children.get(name); // keep cast due to compiler error + if (object == null) { + return null; + } + Class type; + if (object instanceof Reference) { + type = ((Reference) object).getInterface(); + } else if (object instanceof Service) { + type = ((Service) object).getInterface(); + } else { + throw new AssertionError("Illegal object type [" + name + "]"); + } + if (requiredType != null && requiredType.isAssignableFrom(type)) { + // need null check since Spring may pass in a null + throw new BeanNotOfRequiredTypeException(name, requiredType, type); + } + return object.getServiceInstance(); + } + + public boolean containsBean(String name) { + return children.get(name) != null; + } + + public boolean isSingleton(String name) throws NoSuchBeanDefinitionException { + return children.get(name) != null; + } + + public Class getType(String name) throws NoSuchBeanDefinitionException { + return null; + } + + public String[] getAliases(String name) throws NoSuchBeanDefinitionException { + return EMPTY_ARRAY; + } + + public ApplicationContext getParent() { + return null; + } + + public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException { + return null; + } + + public String getDisplayName() { + return getName(); + } + + public long getStartupDate() { + return 0; + } + + public boolean containsBeanDefinition(String beanName) { + return false; + } + + public int getBeanDefinitionCount() { + return 0; + } + + public String[] getBeanDefinitionNames() { + return new String[0]; + } + + public String[] getBeanNamesForType(Class type) { + return new String[0]; + } + + public String[] getBeanNamesForType(Class type, boolean includePrototypes, boolean includeFactoryBeans) { + return new String[0]; + } + + public Map getBeansOfType(Class type) throws BeansException { + return null; + } + + public Map getBeansOfType(Class type, boolean includePrototypes, boolean includeFactoryBeans) + throws BeansException { + return null; + } + + public BeanFactory getParentBeanFactory() { + return null; + } + + public boolean containsLocalBean(String name) { + return false; + } + + public String getMessage(String code, Object[] args, String defaultMessage, Locale locale) { + return null; + } + + public String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException { + return null; + } + + public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException { + return null; + } + + public void publishEvent(ApplicationEvent event) { + + } + + public Resource[] getResources(String locationPattern) throws IOException { + return new Resource[0]; + } + + public Resource getResource(String location) { + return null; + } + + public ClassLoader getClassLoader() { + // REVIEW: this is almost certainly flawed, but it's not clear how the SCA runtime's + // resource loading mechanism is exposed right now. + return this.getClass().getClassLoader(); + } + } +} diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringImplementationLoader.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringImplementationLoader.java new file mode 100644 index 0000000000..c95375cad2 --- /dev/null +++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringImplementationLoader.java @@ -0,0 +1,196 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.container.spring.impl; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URL; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.Manifest; +import javax.xml.namespace.QName; +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import static org.osoa.sca.Version.XML_NAMESPACE_1_0; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.MissingResourceException; +import org.apache.tuscany.spi.model.BoundReferenceDefinition; +import org.apache.tuscany.spi.model.BoundServiceDefinition; + +import org.apache.tuscany.container.spring.model.SpringComponentType; +import org.apache.tuscany.container.spring.model.SpringImplementation; +import org.apache.tuscany.host.RuntimeInfo; +import org.springframework.core.io.Resource; +import org.springframework.core.io.UrlResource; + +/** + * Loader for handling Spring elements. + */ +public class SpringImplementationLoader extends LoaderExtension { + private static final QName IMPLEMENTATION_SPRING = new QName("http://www.osoa.org/xmlns/sca/1.0", + "implementation.spring"); + + private static final String APPLICATION_CONTEXT = "application-context.xml"; + + private static final QName SERVICE_ELEMENT = new QName(XML_NAMESPACE_1_0, "service"); + private static final QName REFERENCE_ELEMENT = new QName(XML_NAMESPACE_1_0, "reference"); + + private final RuntimeInfo runtimeInfo; + + public SpringImplementationLoader(@Autowire LoaderRegistry registry, @Autowire RuntimeInfo runtimeInfo) { + super(registry); + this.runtimeInfo = runtimeInfo; + } + + public QName getXMLType() { + return IMPLEMENTATION_SPRING; + } + + @SuppressWarnings("unchecked") + public SpringImplementation load(CompositeComponent parent, + XMLStreamReader reader, + DeploymentContext deploymentContext) + throws XMLStreamException, LoaderException { + + String locationAttr = reader.getAttributeValue(null, "location"); + if (locationAttr == null && !contextProvided()) { + throw new MissingResourceException("No location supplied"); + } + + SpringImplementation implementation = new SpringImplementation(); + ClassLoader classLoader = deploymentContext.getClassLoader(); + if (!contextProvided()) { + implementation.setApplicationResource(getApplicationContextResource(locationAttr, classLoader)); + } + registry.loadComponentType(parent, implementation, deploymentContext); + SpringComponentType type = implementation.getComponentType(); + while (true) { + switch (reader.next()) { + case START_ELEMENT: + QName qname = reader.getName(); + if (SERVICE_ELEMENT.equals(qname)) { + BoundServiceDefinition service = + (BoundServiceDefinition) registry.load(parent, reader, deploymentContext); + if (!type.isExposeAllBeans()) { + String name = service.getName(); + if (!type.getServiceTypes().containsKey(name)) { + LoaderException e = new LoaderException("No service defined in Spring context for "); + e.setIdentifier(name); + throw e; + } + } + type.getDeclaredServices().put(service.getName(), service); + } else if (REFERENCE_ELEMENT.equals(qname)) { + BoundReferenceDefinition reference = + (BoundReferenceDefinition) registry.load(parent, reader, deploymentContext); + type.getDeclaredReferences().put(reference.getName(), reference); + } + break; + case END_ELEMENT: + if (IMPLEMENTATION_SPRING.equals(reader.getName())) { + return implementation; + } + } + } + } + + protected Resource getApplicationContextResource(String locationAttr, ClassLoader cl) throws LoaderException { + assert runtimeInfo != null; + File manifestFile = null; + File appXmlFile; + File locationFile = new File(locationAttr); + + if (!locationFile.isAbsolute()) { + locationFile = new File(runtimeInfo.getApplicationRootDirectory(), locationAttr); + } + if (!locationFile.exists()) { + // FIXME hack + URL url = cl.getResource(locationAttr); + if (url != null) { + return new UrlResource(url); + } + throw new MissingResourceException(locationFile.toString()); + } + + if (locationFile.isDirectory()) { + try { + manifestFile = new File(locationFile, "META-INF/MANIFEST.MF"); + if (manifestFile.exists()) { + Manifest mf = new Manifest(new FileInputStream(manifestFile)); + Attributes mainAttrs = mf.getMainAttributes(); + String appCtxPath = mainAttrs.getValue("Spring-Context"); + if (appCtxPath != null) { + appXmlFile = new File(locationFile, appCtxPath); + if (appXmlFile.exists()) { + return new UrlResource(appXmlFile.toURL()); + } + } + } + // no manifest-specified Spring context, use default + appXmlFile = new File(locationFile, APPLICATION_CONTEXT); + if (appXmlFile.exists()) { + return new UrlResource(appXmlFile.toURL()); + } + } catch (IOException e) { + throw new LoaderException("Error reading manifest " + manifestFile); + } + } else { + try { + JarFile jf = new JarFile(locationFile); + JarEntry je; + Manifest mf = jf.getManifest(); + if (mf != null) { + Attributes mainAttrs = mf.getMainAttributes(); + String appCtxPath = mainAttrs.getValue("Spring-Context"); + if (appCtxPath != null) { + je = jf.getJarEntry(appCtxPath); + if (je != null) { + // TODO return a Spring specific Resouce type for jars + return new UrlResource(new URL("jar:" + locationFile.toURL() + "!/" + appCtxPath)); + } + } + } + je = jf.getJarEntry(APPLICATION_CONTEXT); + if (je != null) { + return new UrlResource(new URL("jar:" + locationFile.toURI().toURL() + "!" + APPLICATION_CONTEXT)); + } + } catch (IOException e) { + // bad archive + // TODO: create a more appropriate exception type + throw new MissingResourceException(locationAttr, e); + } + } + throw new MissingResourceException(APPLICATION_CONTEXT); + } + + private boolean contextProvided() { + return runtimeInfo instanceof SpringRuntimeInfo; + } +} diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInterceptor.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInterceptor.java new file mode 100644 index 0000000000..fb7f0bd99c --- /dev/null +++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInterceptor.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.container.spring.impl; + +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.InvocationRuntimeException; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.TargetInvoker; + +/** + * A temporary interceptor until the connector is updated + * + * @version $Rev$ $Date$ + */ +public class SpringInterceptor implements Interceptor { + + public Message invoke(Message msg) throws InvocationRuntimeException { + TargetInvoker invoker = msg.getTargetInvoker(); + if (invoker == null) { + throw new InvocationRuntimeException("No target invoker specified on message"); + } + return invoker.invoke(msg); + } + + public void setNext(Interceptor next) { + throw new IllegalStateException("This interceptor must be the last one in an target interceptor chain"); + } + + public Interceptor getNext() { + return null; + } + + public boolean isOptimizable() { + return true; + } + +} diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInvoker.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInvoker.java new file mode 100644 index 0000000000..6e05c888ae --- /dev/null +++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringInvoker.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.container.spring.impl; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.wire.InvocationRuntimeException; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.TargetInvoker; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; + +/** + * Dispatches to an operation on a Spring bean. Since Spring manages bean lifecycle and scope through resolution in the + * target proxy, the invoker can safely cache the target proxy. + * + * @version $$Rev$$ $$Date$$ + */ +public class SpringInvoker implements TargetInvoker { + private ApplicationContext springContext; + // default to true since Spring handles resolution + private boolean cacheable = true; + private String beanName; + private Method method; + // caching is thread-safe since Spring handles resolution + private Object bean; + + public SpringInvoker(String beanName, Method method, ApplicationContext context) { + this.beanName = beanName; + this.method = method; + springContext = context; + } + + public Object invokeTarget(final Object object) throws InvocationTargetException { + if (bean == null) { + try { + bean = springContext.getBean(beanName); + } catch (BeansException e) { + throw new TargetException(e); + } + } + try { + if (object != null && !object.getClass().isArray()) { + return method.invoke(bean, object); + } else { + return method.invoke(bean, (Object[]) object); + } + } catch (IllegalAccessException e) { + throw new InvocationTargetException(e); + } + } + + public Message invoke(Message msg) throws InvocationRuntimeException { + try { + Object resp = invokeTarget(msg.getBody()); + msg.setBody(resp); + } catch (InvocationTargetException e) { + msg.setBodyWithFault(e.getCause()); + } catch (Throwable e) { + msg.setBodyWithFault(e); + } + return msg; + } + + public boolean isCacheable() { + return cacheable; + } + + public void setCacheable(boolean cacheable) { + this.cacheable = cacheable; + } + + public boolean isOptimizable() { + return false; + } + + + public SpringInvoker clone() throws CloneNotSupportedException { + SpringInvoker invoker = (SpringInvoker) super.clone(); + invoker.bean = null; + return invoker; + } + + +} diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringRuntimeInfo.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringRuntimeInfo.java new file mode 100644 index 0000000000..8b4f0ac905 --- /dev/null +++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringRuntimeInfo.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.container.spring.impl; + +import java.io.File; +import java.net.URL; + +import org.apache.tuscany.host.RuntimeInfo; +import org.springframework.context.support.AbstractRefreshableApplicationContext; + +/** + * @author Andy Piper + * @since 2.1 + */ +public class SpringRuntimeInfo implements RuntimeInfo { + private AbstractRefreshableApplicationContext applicationContext; + private File appRootDir; + + public SpringRuntimeInfo(File appRootDir, AbstractRefreshableApplicationContext applicationContext) { + this.appRootDir = appRootDir; + this.applicationContext = applicationContext; + } + + public AbstractRefreshableApplicationContext getApplicationContext() { + return applicationContext; + } + + public void setApplicationContext(AbstractRefreshableApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + + public File getInstallDirectory() { + return null; + } + + public File getApplicationRootDirectory() { + return appRootDir; + } + + public URL getBaseURL() { + return null; + } + + public boolean isOnline() { + return true; + } +} diff --git a/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringScaAdapter.java b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringScaAdapter.java new file mode 100644 index 0000000000..ca645db823 --- /dev/null +++ b/branches/sca-java-M2/sca/services/containers/container.spring/src/main/java/org/apache/tuscany/container/spring/impl/SpringScaAdapter.java @@ -0,0 +1,54 @@ +/* + * Copyright 2002-2006 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tuscany.container.spring.impl; + +import org.apache.tuscany.container.spring.model.SpringComponentType; +import org.springframework.sca.ScaAdapter; + +/** + * @author Andy Piper + * @since 2.1 + */ +public class SpringScaAdapter implements ScaAdapter { + //private final SpringComponentType componentType; + + public SpringScaAdapter(SpringComponentType componentType) { + //this.componentType = componentType; + } + + public Object getServiceReference(String referenceName, Class referenceType, String moduleName, + String defaultServiceName) { + /* + ReferenceDefinition reference = null; + componentType.getReferences().put(referenceName, reference); + */ + return null; + } + + public Object getPropertyReference(String propertyName, Class propertyType, String moduleName) { + return null; + } + + public void publishAsService(Object serviceImplementation, Class serviceInterface, String serviceName, + String moduleName) { + /* + componentType.addServiceType(serviceName, serviceInterface); + ServiceDefinition service = null; + componentType.getServices().put(serviceName, service); + */ + } +} -- cgit v1.2.3