diff options
Diffstat (limited to 'sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl')
8 files changed, 1152 insertions, 0 deletions
diff --git a/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/BindingSCDLProcessor.java b/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/BindingSCDLProcessor.java new file mode 100644 index 0000000000..8a83f630e9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/BindingSCDLProcessor.java @@ -0,0 +1,194 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.extension.helper.impl; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.extension.helper.utils.AbstractBinding; + +/** + * An SCDL ArtifactProcessor which uses the Binding class getters/setters + * to define the SCDL attributes. + * + * TODO: merge this with SCDLProcessor + * + * @version $Rev$ $Date$ + */ +public class BindingSCDLProcessor implements StAXArtifactProcessor { + + protected QName scdlQName; + protected Class<Binding> bindingClass; + + protected Map<String, Method> attributeSetters; + protected Method elementTextSetter; + + public BindingSCDLProcessor(QName scdlQName, Class<Binding> implementationClass) { + this.scdlQName = scdlQName; + this.bindingClass = implementationClass; + initAttributes(); + } + + protected void initAttributes() { + attributeSetters = new HashMap<String, Method>(); + Set<Method> methods = new HashSet<Method>(Arrays.asList(bindingClass.getMethods())); + methods.removeAll(Arrays.asList(AbstractBinding.class.getMethods())); + for (Method m : methods) { + if ("setElementText".equals(m.getName())) { + elementTextSetter = m; + } else if ((m.getName().startsWith("set"))) { + attributeSetters.put(getFieldName(m), m); + } + } + } + + /** + * Remove get/set from method name, set 1st char to lowercase and + * remove any trailing underscore character + */ + protected String getFieldName(Method m) { + StringBuilder sb = new StringBuilder(m.getName().substring(3)); + sb.setCharAt(0, Character.toLowerCase(sb.charAt(0))); + String name = sb.toString(); + if (name.endsWith("_")) { + name = name.substring(0,name.length()-1); + } + return name; + } + + public QName getArtifactType() { + return scdlQName; + } + + public Class getModelType() { + //FIXME Having two different bindings, PojoBinding wrapping + // the real binding is pretty confusing, looks like if you don't return + // PojoBinding here, the write and resolve methods will never be + // called, returning PojoBinding.class seems to fix that issue without + // breaking anything else + return PojoBinding.class; + } + + public Binding read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException { + Object impl; + try { + impl = bindingClass.newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + for (String attribute : attributeSetters.keySet()) { + String value = reader.getAttributeValue(null, attribute); + if (value != null && value.length() > 0) { + try { + attributeSetters.get(attribute).invoke(impl, new Object[] {value}); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + //FIXME: none of the attributes of Binding seem to be working with PojoBinding + // For now at least read the binding URI + String uri = reader.getAttributeValue(null, "uri"); + + if (elementTextSetter != null) { + try { + String value = reader.getElementText(); + if (value != null && value.length() > 0) { + elementTextSetter.invoke(impl, value); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + while (!(reader.getEventType() == END_ELEMENT && scdlQName.equals(reader.getName())) && reader.hasNext()) { + reader.next(); + } + + if (!(impl instanceof Binding)) { + impl = new PojoBinding(impl); + + //FIXME: none of the attributes of Binding seem to be working with PojoBinding + // For now at least read the binding URI + if (uri != null) { + ((PojoBinding)impl).setURI(uri); + } + } + return (Binding)impl; + } + + public void resolve(Object model, ModelResolver resolver) throws ContributionResolveException { + } + + public void write(Object model, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException { + + //FIXME: none of the attributes of Binding seem to be working with PojoBinding + // For now at least write the binding URI + + // Find a namespace prefix and write the element + String prefix = writer.getPrefix(scdlQName.getNamespaceURI()); + if (prefix == null) { + NamespaceContext nsc = writer.getNamespaceContext(); + for (int i=1; ; i++) { + prefix = "ns" + i; + if (nsc.getNamespaceURI(prefix) == null) { + break; + } + } + writer.setPrefix(prefix, scdlQName.getNamespaceURI()); + } + writer.writeStartElement(scdlQName.getNamespaceURI(), scdlQName.getLocalPart()); + + // Write the binding URI attribute + String uri; + try { + uri = (String)model.getClass().getMethod("getURI").invoke(model); + } catch (Exception e) { + uri = null; + } + if (uri != null) { + writer.writeAttribute("uri", uri); + } + + writer.writeEndElement(); + + } + +} diff --git a/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/BindingsActivator.java b/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/BindingsActivator.java new file mode 100644 index 0000000000..bca1dac0ed --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/BindingsActivator.java @@ -0,0 +1,262 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.extension.helper.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.xml.Constants; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.ModuleActivator; +import org.apache.tuscany.sca.extension.helper.BindingActivator; +import org.apache.tuscany.sca.extension.helper.ComponentLifecycle; +import org.apache.tuscany.sca.extension.helper.InvokerFactory; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.provider.BindingProviderFactory; +import org.apache.tuscany.sca.provider.ProviderFactory; +import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint; +import org.apache.tuscany.sca.provider.ReferenceBindingProvider; +import org.apache.tuscany.sca.provider.ServiceBindingProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +/** + * + * @version $Rev$ $Date$ + */ +public class BindingsActivator implements ModuleActivator { + + protected List<BindingActivator> bindingActivators; + protected AssemblyFactory assemblyFactory; + protected Map<Class, BindingActivator> bindingActivatorMap = new HashMap<Class, BindingActivator>(); + + public void start(ExtensionPointRegistry registry) { + + ModelFactoryExtensionPoint factories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + this.assemblyFactory = factories.getFactory(AssemblyFactory.class); + + + this.bindingActivators = + DiscoveryUtils.discoverActivators(BindingActivator.class, registry); + + StAXArtifactProcessorExtensionPoint staxProcessors = + registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + + ProviderFactoryExtensionPoint providerFactories = + registry.getExtensionPoint(ProviderFactoryExtensionPoint.class); + + for (final BindingActivator bindingActivator : bindingActivators) { + Class bindingClass = bindingActivator.getBindingClass(); + bindingActivatorMap.put(bindingClass, bindingActivator); + QName scdlQName = getBindingQName(bindingClass); + staxProcessors.addArtifactProcessor(new BindingSCDLProcessor(scdlQName, bindingClass)); + + // Check if the binding extends from Binding interface + if (Binding.class.isAssignableFrom(bindingClass)) { + // Add provider factory against the binding class + providerFactories.addProviderFactory(new DelegatingBindingProviderFactory(bindingClass)); + } + + } + + // Add a generic provider factory against PojoBinding.class + providerFactories.addProviderFactory(new DelegatingBindingProviderFactory(PojoBinding.class)); + } + + public void stop(ExtensionPointRegistry registry) { + StAXArtifactProcessorExtensionPoint staxProcessors = + registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + ProviderFactoryExtensionPoint providerFactories = + registry.getExtensionPoint(ProviderFactoryExtensionPoint.class); + + for (final BindingActivator bindingActivator : bindingActivators) { + + // Remove the binding SCDL processor from the runtime + if (staxProcessors != null) { + StAXArtifactProcessor processor = + staxProcessors.getProcessor(getBindingQName(bindingActivator.getBindingClass())); + if (processor != null) { + staxProcessors.removeArtifactProcessor(processor); + } + } + + // Remove the ProviderFactory from the runtime + if (providerFactories != null && bindingActivator.getBindingClass() != null) { + ProviderFactory factory = providerFactories.getProviderFactory(bindingActivator.getBindingClass()); + if (factory != null) { + providerFactories.removeProviderFactory(factory); + } + } + } + if (providerFactories != null) { + ProviderFactory factory = providerFactories.getProviderFactory(PojoBinding.class); + if (factory != null) { + providerFactories.removeProviderFactory(factory); + } + } + } + + protected QName getBindingQName(Class bindingClass) { + String localName = bindingClass.getName(); + if (localName.lastIndexOf('.') > -1) { + localName = localName.substring(localName.lastIndexOf('.') + 1); + } + if (localName.endsWith("Binding")) { + localName = localName.substring(0, localName.length() - 7); + } + StringBuilder sb = new StringBuilder(localName); + for (int i = 0; i < sb.length(); i++) { + if (Character.isUpperCase(sb.charAt(i))) { + sb.setCharAt(i, Character.toLowerCase(sb.charAt(i))); + } else { + break; + } + } + return new QName(Constants.SCA10_TUSCANY_NS, "binding." + sb.toString()); + } + + private final class DelegatingBindingProviderFactory implements BindingProviderFactory { + private Class modelType; + + public DelegatingBindingProviderFactory(Class modelType) { + super(); + this.modelType = modelType; + } + + public ReferenceBindingProvider createReferenceBindingProvider(final RuntimeComponent rc, + final RuntimeComponentReference rcr, + final Binding b) { + final Object realBinding; + if (b instanceof PojoBinding) { + realBinding = ((PojoBinding)b).getUserBinding(); + } else { + realBinding = b; + } + final BindingActivator bindingActivator = bindingActivatorMap.get(realBinding.getClass()); + return new ReferenceBindingProvider() { + List<InvokerProxy> invokers = new ArrayList<InvokerProxy>(); + private InvokerFactory factory; + + public Invoker createInvoker(Operation operation) { + InvokerProxy invoker = new InvokerProxy(factory, operation); + invokers.add(invoker); + return invoker; + } + + public boolean supportsOneWayInvocation() { + return false; + } + + public InterfaceContract getBindingInterfaceContract() { + return null; + } + + public void start() { + if (b instanceof PojoBinding) { + factory = bindingActivator.createInvokerFactory(rc, rcr, b, ((PojoBinding)b).getUserBinding()); + } else { + factory = bindingActivator.createInvokerFactory(rc, rcr, b, b); + } + if ( (factory != null) && (factory instanceof ComponentLifecycle)) { + ((ComponentLifecycle)factory).start(); + } +// for (InvokerProxy invoker : invokers) { +// invoker.start(factory); +// } + } + + public void stop() { + if (factory instanceof ComponentLifecycle) { + ((ComponentLifecycle)factory).stop(); + } + } + }; + } + + public ServiceBindingProvider createServiceBindingProvider(final RuntimeComponent rc, + final RuntimeComponentService rcs, + final Binding b) { + final Object realBinding; + if (b instanceof PojoBinding) { + realBinding = ((PojoBinding)b).getUserBinding(); + } else { + realBinding = b; + } + final BindingActivator bindingActivator = bindingActivatorMap.get(realBinding.getClass()); + return new ServiceBindingProvider() { + ComponentLifecycle listener = bindingActivator.createService(rc, rcs, b, realBinding); + + public InterfaceContract getBindingInterfaceContract() { + return null; + } + + public boolean supportsOneWayInvocation() { + return false; + } + + public void start() { + listener.start(); + } + + public void stop() { + listener.stop(); + } + }; + } + + public Class getModelType() { + return modelType; + } + } + +} + +class InvokerProxy implements Invoker { + InvokerFactory factory; + Invoker invoker; + Operation op; + + InvokerProxy(InvokerFactory factory, Operation op) { + this.factory = factory; + this.op = op; + this.invoker = factory.createInvoker(op); + } + + public Message invoke(Message arg0) { + return invoker.invoke(arg0); + } + +// public void start(InvokerFactory factory) { +// invoker = factory.createInvoker(op); +// } +} diff --git a/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/DiscoveryUtils.java b/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/DiscoveryUtils.java new file mode 100644 index 0000000000..9d772c8ae8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/DiscoveryUtils.java @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.extension.helper.impl; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; + +/** + * Discovers Activators in the classpath using the J2SE + * jar file extensions for Service Provider discovery + * + * @version $Rev$ $Date$ + */ +public class DiscoveryUtils { + + @SuppressWarnings("unchecked") + public static <T> List<T> discoverActivators(Class<T> activatorClass, ExtensionPointRegistry registry) { + List<T> activators; + try { + Set<ServiceDeclaration> activatorClasses = ServiceDiscovery.getInstance().getServiceDeclarations(activatorClass); + activators = new ArrayList<T>(); + for (ServiceDeclaration declaration : activatorClasses) { + try { + Class<T> c = (Class<T>)declaration.loadClass(); + activators.add(c.cast(instantiateActivator(c, registry))); + } catch (Throwable e) { + e.printStackTrace(); // TODO: log + } + } + } catch (IOException e) { + throw new RuntimeException(e); + } + return activators; + } + + static Object instantiateActivator(Class activator, ExtensionPointRegistry registry) { + Constructor[] cs = activator.getConstructors(); + if (cs.length != 1) { + throw new RuntimeException("Activator must have only one constructors"); + } + + Class<?>[] paramTypes = cs[0].getParameterTypes(); + Object[] extensions = new Object[paramTypes.length]; + + for (int i=0; i< paramTypes.length; i++) { + if ("org.apache.tuscany.sca.host.http.ServletHost".equals(paramTypes[i].getName())) { + extensions[i] = getServletHost(registry); + } else { + extensions[i] = registry.getExtensionPoint(paramTypes[i]); + } + } + + try { + + return cs[0].newInstance(extensions); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static Object getServletHost(ExtensionPointRegistry registry) { + try { + + Class<?> servletHostEPClass = Class.forName("org.apache.tuscany.sca.host.http.ServletHostExtensionPoint"); + Object servletHostEP = registry.getExtensionPoint(servletHostEPClass); + Class<?> extensibleServletHost = Class.forName("org.apache.tuscany.sca.host.http.ExtensibleServletHost"); + return extensibleServletHost.getConstructor(new Class[] {servletHostEPClass}).newInstance(servletHostEP); + + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } catch (IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + +} diff --git a/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/ImplementationImplementationProvider.java b/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/ImplementationImplementationProvider.java new file mode 100644 index 0000000000..f7c65acb3d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/ImplementationImplementationProvider.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.extension.helper.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.extension.helper.ImplementationActivator; +import org.apache.tuscany.sca.extension.helper.InvokerFactory; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +/** + * The ImplementationProvider createInvoker method is called before the start method + * but the runtime isn't properly setup until the start method is called. This means + * that Invoker's can't initialize things like the services, references and properties + * until start is called. This class tries to get around that by using an Invoker + * proxy that delays creating the real Invoker till start is called. + * + * @version $Rev$ $Date$ + */ +public class ImplementationImplementationProvider implements ImplementationProvider { + + ImplementationActivator implementationActivator; + RuntimeComponent runtimeComponent; + Implementation impl; + Object userImpl; + InvokerFactory factory; + + List<InvokerProxy> invokers = new ArrayList<InvokerProxy>(); + + public ImplementationImplementationProvider(ImplementationActivator implementationActivator, + RuntimeComponent rc, + Implementation impl, + Object userImpl) { + this.implementationActivator = implementationActivator; + this.runtimeComponent = rc; + this.impl = impl; + this.userImpl = userImpl; + } + + public Invoker createInvoker(RuntimeComponentService arg0, final Operation op) { + InvokerProxy invoker = new InvokerProxy(op); + return invoker; + } + + public boolean supportsOneWayInvocation() { + return false; + } + + public void start() { + factory = implementationActivator.createInvokerFactory(runtimeComponent, impl, userImpl); + } + + public void stop() { + } + + class InvokerProxy implements Invoker { + Invoker invoker; + Operation op; + + InvokerProxy(Operation op) { + this.op = op; + } + + public Message invoke(Message msg) { + init(); + return invoker.invoke(msg); + } + + public synchronized void init() { + if (invoker == null) { + invoker = factory.createInvoker(op); + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/ImplementationsActivator.java b/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/ImplementationsActivator.java new file mode 100644 index 0000000000..d156d835ad --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/ImplementationsActivator.java @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.extension.helper.impl; + +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.xml.Constants; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.ModuleActivator; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.TransformerExtensionPoint; +import org.apache.tuscany.sca.databinding.impl.MediatorImpl; +import org.apache.tuscany.sca.extension.helper.ImplementationActivator; +import org.apache.tuscany.sca.extension.helper.utils.DefaultPropertyValueObjectFactory; +import org.apache.tuscany.sca.extension.helper.utils.PropertyValueObjectFactory; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.ImplementationProviderFactory; +import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * A Tuscany ModuleActivator which activates all the ImplementationActivators + * + * @version $Rev$ $Date$ + */ +public class ImplementationsActivator implements ModuleActivator { + + protected List<ImplementationActivator> implementationActivators; + + public void start(ExtensionPointRegistry registry) { + + ModelFactoryExtensionPoint factories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + AssemblyFactory assemblyFactory = factories.getFactory(AssemblyFactory.class); + + DataBindingExtensionPoint dataBindings = registry.getExtensionPoint(DataBindingExtensionPoint.class); + TransformerExtensionPoint transformers = registry.getExtensionPoint(TransformerExtensionPoint.class); + MediatorImpl mediator = new MediatorImpl(dataBindings, transformers); + + //FIXME Pass this factory differently as it's not an extension point + PropertyValueObjectFactory propertyFactory = new DefaultPropertyValueObjectFactory(mediator); + registry.addExtensionPoint(propertyFactory); + + this.implementationActivators = DiscoveryUtils.discoverActivators(ImplementationActivator.class, registry); + + StAXArtifactProcessorExtensionPoint staxProcessors = registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + ProviderFactoryExtensionPoint providerFactories = registry.getExtensionPoint(ProviderFactoryExtensionPoint.class); + + for (final ImplementationActivator implementationActivator : implementationActivators) { + + Class<Implementation> implClass = implementationActivator.getImplementationClass(); + QName scdlQName = getSCDLQName(implClass); + staxProcessors.addArtifactProcessor(new SCDLProcessor(assemblyFactory, scdlQName, implClass, registry, factories)); + + if (implementationActivator.getImplementationClass() != null && providerFactories != null) { + addImplementationProvider(implementationActivator, providerFactories); + } + } + } + + public void stop(ExtensionPointRegistry registry) { + StAXArtifactProcessorExtensionPoint staxProcessors = registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + + for (final ImplementationActivator implementationActivator : implementationActivators) { + if (staxProcessors != null) { + StAXArtifactProcessor processor = staxProcessors.getProcessor(getSCDLQName(implementationActivator.getImplementationClass())); + if (processor != null) { + staxProcessors.removeArtifactProcessor(processor); + } + } + } + } + + private void addImplementationProvider(final ImplementationActivator implementationActivator, ProviderFactoryExtensionPoint providerFactories) { + + providerFactories.addProviderFactory(new ImplementationProviderFactory() { + public ImplementationProvider createImplementationProvider(final RuntimeComponent rc, final Implementation impl) { + if (impl instanceof PojoImplementation) { + return new ImplementationImplementationProvider(implementationActivator, rc, impl, ((PojoImplementation)impl).getUserImpl()); + } else { + return new ImplementationImplementationProvider(implementationActivator, rc, impl, impl); + } + } + public Class getModelType() { + Class c = implementationActivator.getImplementationClass(); + + if (Implementation.class.isAssignableFrom(c)) { + return c; + } else { + return PojoImplementation.class; + } + } + }); + } + + protected QName getSCDLQName(Class implementationClass) { + String localName = implementationClass.getName(); + if (localName.lastIndexOf('.') > -1) { + localName = localName.substring(localName.lastIndexOf('.') + 1); + } + if (localName.endsWith("Implementation")) { + localName = localName.substring(0, localName.length() - 14); + } + StringBuilder sb = new StringBuilder(localName); + for (int i=0; i<sb.length(); i++) { + if (Character.isUpperCase(sb.charAt(i))) { + sb.setCharAt(i, Character.toLowerCase(sb.charAt(i))); + } else { + break; + } + } + return new QName(Constants.SCA10_TUSCANY_NS, "implementation." + sb.toString()); + } + +} diff --git a/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/PojoBinding.java b/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/PojoBinding.java new file mode 100644 index 0000000000..de9a5bfbb1 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/PojoBinding.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.extension.helper.impl; + +import org.apache.tuscany.sca.extension.helper.utils.AbstractBinding; + +/** + * + * @version $Rev$ $Date$ + */ +public class PojoBinding extends AbstractBinding { + + Object userBinding; + + public PojoBinding(Object userImpl) { + this.userBinding = userImpl; + } + + public Object getUserBinding() { + return userBinding; + } + +} diff --git a/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/PojoImplementation.java b/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/PojoImplementation.java new file mode 100644 index 0000000000..a59733aced --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/PojoImplementation.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.extension.helper.impl; + +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.extension.helper.utils.DynamicImplementation; + +/** + * Enables Implementation extensions to use a simple POJO + * for the implementation object instead of requiring + * implementing the Implementation interface. + * + * @version $Rev$ $Date$ + */ +public class PojoImplementation<Implementation> extends DynamicImplementation { + + Object userImpl; + + public PojoImplementation(Object userImpl) { + this.userImpl = userImpl; + } + + public Object getUserImpl() { + return userImpl; + } + + public void resolve(ModelResolver resolver) { + + try { + Method resolveMethod; + if (userImpl != null && + (resolveMethod = userImpl.getClass().getMethod("resolve", ModelResolver.class)) != null) { + resolveMethod.invoke(userImpl, resolver); + } + } catch (Exception e) { + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/SCDLProcessor.java b/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/SCDLProcessor.java new file mode 100644 index 0000000000..c91618c24d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.3.1/modules/extension-helper/src/main/java/org/apache/tuscany/sca/extension/helper/impl/SCDLProcessor.java @@ -0,0 +1,248 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.extension.helper.impl; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.ComponentType; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.extension.helper.utils.AbstractStAXArtifactProcessor; +import org.apache.tuscany.sca.extension.helper.utils.DynamicImplementation; +import org.osoa.sca.ServiceRuntimeException; + +/** + * An SCDL ArtifactProcessor which uses the Implementation class getters/setters + * to define the SCDL attributes. + * + * @version $Rev$ $Date$ + */ +public class SCDLProcessor extends AbstractStAXArtifactProcessor<Implementation> { + + protected QName scdlQName; + protected Class<Implementation> implementationClass; + protected ExtensionPointRegistry registry; + protected ModelFactoryExtensionPoint factories; + + protected Map<String, Method> attributeSetters; + protected Method elementTextSetter; + + public SCDLProcessor(AssemblyFactory assemblyFactory, QName scdlQName, Class<Implementation> implementationClass, ExtensionPointRegistry registry, ModelFactoryExtensionPoint factories) { + super(assemblyFactory); + this.scdlQName = scdlQName; + this.implementationClass = implementationClass; + this.registry = registry; + this.factories = factories; + initAttributes(); + } + + protected void initAttributes() { + attributeSetters = new HashMap<String, Method>(); + Set<Method> methods = new HashSet<Method>(Arrays.asList(implementationClass.getMethods())); + methods.removeAll(Arrays.asList(DynamicImplementation.class.getMethods())); + for (Method m : methods) { + if ("setElementText".equals(m.getName())) { + elementTextSetter = m; + } else if ((m.getName().startsWith("set"))) { + attributeSetters.put(getFieldName(m), m); + } + } + } + + /** + * Remove get/set from method name, set 1st char to lowercase and + * remove any trailing underscore character + */ + protected String getFieldName(Method m) { + StringBuilder sb = new StringBuilder(m.getName().substring(3)); + sb.setCharAt(0, Character.toLowerCase(sb.charAt(0))); + String name = sb.toString(); + if (name.endsWith("_")) { + name = name.substring(0,name.length()-1); + } + return name; + } + + private Object[] getImplConstrArgs() { + Constructor[] cs = implementationClass.getConstructors(); + if (cs.length != 1) { + throw new IllegalArgumentException("Implementation class must have a single constructor: "+ implementationClass.getName()); + } + List args = new ArrayList(); + for (Class c : cs[0].getParameterTypes()) { + Object o = factories.getFactory(c); + if (o == null) { + o = registry.getExtensionPoint(c); + } + args.add(o); + } + return args.toArray(); + } + + + public QName getArtifactType() { + return scdlQName; + } + + public Class<Implementation> getModelType() { + Class clazz; + if (Implementation.class.isAssignableFrom(implementationClass)) { + clazz = implementationClass; + } else { + clazz = PojoImplementation.class; + } + return clazz; + } + + public Implementation read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException { + Object impl; + try { + impl = implementationClass.getConstructors()[0].newInstance(getImplConstrArgs()); + } catch (Exception e) { + throw new RuntimeException(e); + } + + for (String attribute : attributeSetters.keySet()) { + String value = reader.getAttributeValue(null, attribute); + if (value != null && value.length() > 0) { + try { + attributeSetters.get(attribute).invoke(impl, new Object[] {value}); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + if (elementTextSetter != null) { + try { + String value = reader.getElementText(); + if (value != null && value.length() > 0) { + elementTextSetter.invoke(impl, value); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + while (!(reader.getEventType() == END_ELEMENT && scdlQName.equals(reader.getName())) && reader.hasNext()) { + reader.next(); + } + + if (!(impl instanceof Implementation)) { + impl = new PojoImplementation(impl); + } + + return (Implementation)impl; + } + + public void write(Implementation arg0, XMLStreamWriter arg1) throws ContributionWriteException, XMLStreamException { + } + + @Override + protected void addSideFileComponentType(String name, Implementation impl, ModelResolver resolver) { +// protected void addSideFileComponentType(Implementation impl, ModelResolver resolver) { + + ComponentType componentType; + try { + componentType = getComponentType(resolver, impl); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + + if (componentType != null && !componentType.isUnresolved()) { + for (Reference reference : componentType.getReferences()) { + impl.getReferences().add(reference); + } + for (Service service : componentType.getServices()) { + impl.getServices().add(service); + } + for (Property property : componentType.getProperties()) { + impl.getProperties().add(property); + } + if (componentType.getConstrainingType() != null) { + impl.setConstrainingType(componentType.getConstrainingType()); + } + } + } + + ComponentType getComponentType(ModelResolver resolver, Implementation impl) throws IllegalArgumentException, IllegalAccessException, + InvocationTargetException { + for (Method m : getGetters()) { + Object io; + if (impl instanceof PojoImplementation) { + io = ((PojoImplementation) impl).getUserImpl(); + } else { + io = impl; + } + String value = (String) m.invoke(io, new Object[] {}); + if (value != null) { + value = value.substring(0, value.lastIndexOf('.')); + ComponentType componentType = assemblyFactory.createComponentType(); + componentType.setUnresolved(true); + componentType.setURI(value + ".componentType"); + componentType = resolver.resolveModel(ComponentType.class, componentType); + if (!componentType.isUnresolved()) { + return componentType; + } + } + } + return null; + } + + private List<Method> getGetters() { + List<Method> ms = new ArrayList<Method>(); + for (Method setter : attributeSetters.values()) { + String s = getFieldName(setter); + for (Method m : implementationClass.getMethods()) { + String name = m.getName(); + if (name.length() > 3 && name.startsWith("get")) { + if (s.endsWith(name.substring(4))) { + ms.add(m); + } + } + } + } + return ms; + } +} |