diff options
Diffstat (limited to 'sca-java-1.x/tags/1.2/modules/host-embedded/src')
29 files changed, 3837 insertions, 0 deletions
diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomain.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomain.java new file mode 100644 index 0000000000..c1d80be772 --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomain.java @@ -0,0 +1,272 @@ +/* + * 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.host.embedded; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.Constructor; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import org.apache.tuscany.sca.host.embedded.impl.DefaultSCADomain; +import org.apache.tuscany.sca.host.embedded.management.ComponentManager; +import org.osoa.sca.CallableReference; +import org.osoa.sca.ServiceReference; +import org.osoa.sca.ServiceRuntimeException; + +/** + * A handle to an SCA domain. + * + * @version $Rev$ $Date$ + */ +public abstract class SCADomain { + + final static String LOCAL_DOMAIN_URI = "http://localhost"; + + /** + * Static variable to hold the most recent instance of SCADomain + */ + // TODO: Temporary support for SCADomain.connect() API + protected static SCADomain theDomain; + + + /** + * Returns a new instance of a local SCA domain. + * + * @return + */ + public static SCADomain newInstance() { + return createNewInstance(LOCAL_DOMAIN_URI, null); + } + + /** + * Returns a new instance of a local SCA domain. The specified deployable + * composite will be included in the SCA domain. + * + * @param composite the deployable composite to include in the SCA domain. + * @return + */ + public static SCADomain newInstance(String composite) { + return createNewInstance(LOCAL_DOMAIN_URI, "/", composite); + } + + /** + * Returns a new instance of a local SCA domain. The specified deployable + * composites will be included in the SCA domain. + * + * @param domainURI the URI of the SCA domain + * @param contributionLocation the location of an SCA contribution + * @param composites the deployable composites to include in the SCA domain. + * @return + */ + public static SCADomain newInstance(String domainURI, String contributionLocation, String... composites) { + return createNewInstance(domainURI, contributionLocation, composites); + } + + /** + * Removes the specified local SCA Domain instance + * + * @param domainInstance the instance to be removed + */ + // FIXME: Adding this as temporary support for the "connect" API + public static void removeInstance(SCADomain domainInstance) { + theDomain = null; + } + + /** + * Returns an SCADomain representing a remote SCA domain. + * + * @param domainURI the URI of the SCA domain + * @return + */ + // FIXME : this is a temporary implementation to get the capability working + public static SCADomain connect(String domainURI) { + return theDomain; + } + + /** + * Close the SCA domain. + */ + public void close() { + // TODO: temporary to support initial SCADomain.connect capability + SCADomain.removeInstance(this); + } + + /** + * Returns the URI of the SCA Domain. + * + * @return the URI of the SCA Domain + */ + public abstract String getURI(); + + /** + * Cast a type-safe reference to a CallableReference. Converts a type-safe + * reference to an equivalent CallableReference; if the target refers to a + * service then a ServiceReference will be returned, if the target refers to + * a callback then a CallableReference will be returned. + * + * @param target a reference proxy provided by the SCA runtime + * @param <B> the Java type of the business interface for the reference + * @param <R> the type of reference to be returned + * @return a CallableReference equivalent for the proxy + * @throws IllegalArgumentException if the supplied instance is not a + * reference supplied by the SCA runtime + */ + public abstract <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException; + + /** + * Returns a proxy for a service provided by a component in the SCA domain. + * + * @param businessInterface the interface that will be used to invoke the + * service + * @param serviceName the name of the service + * @param <B> the Java type of the business interface for the service + * @return an object that implements the business interface + */ + public abstract <B> B getService(Class<B> businessInterface, String serviceName); + + /** + * Returns a ServiceReference for a service provided by a component in the + * SCA domain. + * + * @param businessInterface the interface that will be used to invoke the + * service + * @param serviceName the name of the service + * @param <B> the Java type of the business interface for the service + * @return a ServiceReference for the designated service + */ + public abstract <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String referenceName); + + /** + * Read the service name from a configuration file + * + * @param classLoader + * @param name The name of the service class + * @return A class name which extends/implements the service class + * @throws IOException + */ + private static String getServiceName(ClassLoader classLoader, String name) throws IOException { + InputStream is = classLoader.getResourceAsStream("META-INF/services/" + name); + if (is == null) { + return null; + } + BufferedReader reader = null; + try { + reader = new BufferedReader(new InputStreamReader(is)); + while (true) { + String line = reader.readLine(); + if (line == null) { + break; + } else if (!line.startsWith("#")) { + return line.trim(); + } + } + } finally { + if (reader != null) { + reader.close(); + } + } + return null; + } + + /** + * Returns an SCADomain instance. If the system property + * "org.apache.tuscany.sca.host.embedded.SCADomain" is set, its value is used as + * the name of the implementation class. Otherwise, if the resource + * "META-INF/services/org.apache.tuscany.sca.host.embedded.SCADomain" can be + * loaded from the supplied classloader. Otherwise, it will use + * "org.apache.tuscany.sca.host.embedded.impl.DefaultSCADomain" as the default. + * The named class is loaded from the supplied classloader. + * + * @param classLoader + * @param domainURI + * @param contributionLocation + * @param composites + * @return + */ + static SCADomain createNewInstance(String domainURI, String contributionLocation, String... composites) { + + SCADomain domain = null; + + try { + // Determine the runtime and application classloader + final ClassLoader runtimeClassLoader = SCADomain.class.getClassLoader(); + final ClassLoader applicationClassLoader = Thread.currentThread().getContextClassLoader(); + + // Discover the SCADomain implementation + final String name = SCADomain.class.getName(); + String className = AccessController.doPrivileged(new PrivilegedAction<String>() { + public String run() { + return System.getProperty(name); + } + }); + + if (className == null) { + className = getServiceName(runtimeClassLoader, name); + } + + if (className == null) { + + // Create a default SCA domain implementation + domain = + new DefaultSCADomain(runtimeClassLoader, + applicationClassLoader, + domainURI, + contributionLocation, + composites); + } else { + + // Create an instance of the discovered SCA domain implementation + Class cls = Class.forName(className, true, runtimeClassLoader); + Constructor<?> constructor = null; + try { + constructor = cls.getConstructor(ClassLoader.class, ClassLoader.class, + String.class, String.class, String[].class); + } catch (NoSuchMethodException e) {} + if (constructor != null) { + domain = (SCADomain)constructor.newInstance(runtimeClassLoader, + applicationClassLoader, + domainURI, + contributionLocation, + composites); + } else { + + constructor = cls.getConstructor(ClassLoader.class, String.class); + domain = (SCADomain)constructor.newInstance(runtimeClassLoader, domainURI); + } + } + + // FIXME: temporary support for connect() API + theDomain = domain; + + return domain; + + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public ComponentManager getComponentManager() { + return null; + } + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomainBean.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomainBean.java new file mode 100644 index 0000000000..9ee7c274fd --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomainBean.java @@ -0,0 +1,121 @@ +/* + * 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.host.embedded; + +import org.apache.tuscany.sca.host.embedded.management.ComponentManager; +import org.osoa.sca.CallableReference; +import org.osoa.sca.ServiceReference; + +public class SCADomainBean extends SCADomain { + + private SCADomain instance; + + private String uri = LOCAL_DOMAIN_URI; + private String location = "/"; + private String[] composites; + + /** + * Constructs a new SCA domain + */ + public SCADomainBean() { + } + + @Override + public String getURI() { + return uri; + } + + public void setURI(String uri) { + this.uri = uri; + } + + public void setContributionLocation(String contributionLocation) { + this.location = contributionLocation; + } + + public String getContributionLocation() { + return location; + } + + public void setDeployableComposite(String composite) { + setDeployableComposites(composite); + } + + public void setDeployableComposites(String... composites) { + this.composites = composites; + } + + public String[] getDeployableComposites() { + return composites; + } + + @SuppressWarnings("unchecked") + @Override + public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException { + if (instance == null) { + instance = SCADomain.createNewInstance(uri, location, composites); + } + Object result = instance.cast(target); + return (R) result; + } + + @Override + public void close() { + if (instance == null) { + instance = SCADomain.createNewInstance(uri, location, composites); + } + instance.close(); + instance = null; + } + + @Override + public <B> B getService(Class<B> businessInterface, String serviceName) { + if (instance == null) { + instance = SCADomain.createNewInstance(uri, location, composites); + } + return instance.getService(businessInterface, serviceName); + } + + @Override + public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String referenceName) { + if (instance == null) { + instance = SCADomain.createNewInstance(uri, location, composites); + } + return instance.getServiceReference(businessInterface, referenceName); + } + + @Override + protected void finalize() throws Throwable { + + // Make sure that the SCA domain is closed + if (instance != null) { + instance.close(); + instance = null; + } + } + + @Override + public ComponentManager getComponentManager() { + if (instance == null) { + instance = SCADomain.createNewInstance(uri, location, composites); + } + return instance.getComponentManager(); + } +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCATestCaseRunner.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCATestCaseRunner.java new file mode 100644 index 0000000000..c74d0aad87 --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCATestCaseRunner.java @@ -0,0 +1,216 @@ +/* + * 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.host.embedded; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +/** + * A helper class that can be used to run an SCA JUnit test case. The test case will run in an isolated class loader. + * + * @version $Rev$ $Date$ + */ +public class SCATestCaseRunner { + + private ClassLoader classLoader; + private Class<?> testSuiteClass; + private Object testSuite; + private Class<?> testResultClass; + private Class<?> testCaseClass; + private Object testCase; + + private Class<?> beforeAnnotation; + private Class<?> beforeClassAnnotation; + private Class<?> afterAnnotation; + private Class<?> afterClassAnnotation; + private Class<?> junit4AdapterClass; + private Class<?> junit3TestCaseClass; + + /** + * Constructs a new TestCase runner. + * + * @param testClass + */ + public SCATestCaseRunner(Class testClass) { + try { + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + classLoader = testClass.getClassLoader(); + if (classLoader instanceof URLClassLoader) { + URL[] urls = ((URLClassLoader)classLoader).getURLs(); + classLoader = new URLClassLoader(urls, classLoader.getParent()); + } else if (classLoader == tccl || classLoader.getParent() == tccl) { + classLoader = new URLClassLoader(new URL[0], classLoader); + } else { + classLoader = tccl; + } + + try { + Thread.currentThread().setContextClassLoader(classLoader); + + testCaseClass = Class.forName(testClass.getName(), true, classLoader); + testCase = testCaseClass.newInstance(); + ClassLoader testClassLoader = testCaseClass.getClassLoader(); + + junit3TestCaseClass = Class.forName("junit.framework.TestCase", true, testClassLoader); + + testSuiteClass = Class.forName("junit.framework.TestSuite", true, testClassLoader); + Constructor testSuiteConstructor = testSuiteClass.getConstructor(Class.class); + testSuite = testSuiteConstructor.newInstance(testCaseClass); + + testResultClass = Class.forName("junit.framework.TestResult", true, testClassLoader); + + try { + beforeAnnotation = Class.forName("org.junit.Before", true, testClassLoader); + afterAnnotation = Class.forName("org.junit.After", true, testClassLoader); + beforeClassAnnotation = Class.forName("org.junit.BeforeClass", true, testClassLoader); + afterClassAnnotation = Class.forName("org.junit.AfterClass", true, testClassLoader); + junit4AdapterClass = Class.forName("junit.framework.JUnit4TestAdapter", true, testClassLoader); + } catch (Exception e) { + // Unexpected + throw new AssertionError(e); + } + + } finally { + Thread.currentThread().setContextClassLoader(tccl); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Run the test case + */ + public void run() { + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(classLoader); + + if (junit3TestCaseClass.isAssignableFrom(testCaseClass)) { + Object testResult = testResultClass.newInstance(); + Method runMethod = testSuiteClass.getMethod("run", testResultClass); + runMethod.invoke(testSuite, testResult); + } else { + Object junit4Adapter = junit4AdapterClass.getConstructor(Class.class).newInstance(testCaseClass); + Object testResult = testResultClass.newInstance(); + Method runMethod = junit4AdapterClass.getMethod("run", testResultClass); + runMethod.invoke(junit4Adapter, testResult); + } + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + Thread.currentThread().setContextClassLoader(tccl); + } + } + + /** + * Invoke the setUp method + */ + public void setUp() { + execute("setUp"); + } + + /** + * Invoke the before methods + */ + public void before() { + execute(beforeAnnotation); + } + + /** + * Invoke the beforeClass methods + */ + public void beforeClass() { + execute(beforeClassAnnotation); + } + + /** + * Invoke the tearDown method + */ + public void tearDown() { + execute("tearDown"); + } + + /** + * Invoke the after methods + */ + public void after() { + execute(afterAnnotation); + } + + /** + * Invoke the afterClass methods + */ + public void afterClass() { + execute(afterClassAnnotation); + } + + /** + * Invoke the specified test method. + */ + public void run(String methodName) { + execute(methodName); + } + + /** + * Invoke the methods annotated with the specified annotation. + */ + private void execute(Class<?> annotationClass) { + if (annotationClass == null) { + throw new RuntimeException(new NoSuchMethodException()); + } + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(classLoader); + + for (Method method : testCaseClass.getDeclaredMethods()) { + for (Annotation annotation : method.getAnnotations()) { + if (annotation.annotationType() == annotationClass) { + method.invoke(testCase); + } + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + Thread.currentThread().setContextClassLoader(tccl); + } + } + + /** + * Invoke the specified method + */ + private void execute(String methodName) { + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(classLoader); + Method setUpMethod = testCaseClass.getDeclaredMethod(methodName); + setUpMethod.setAccessible(true); + setUpMethod.invoke(testCase); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + Thread.currentThread().setContextClassLoader(tccl); + } + } + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ComponentManagerImpl.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ComponentManagerImpl.java new file mode 100644 index 0000000000..8a512de5f8 --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ComponentManagerImpl.java @@ -0,0 +1,115 @@ +/* + * 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.host.embedded.impl; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.core.assembly.ActivationException; +import org.apache.tuscany.sca.core.assembly.RuntimeComponentImpl; +import org.apache.tuscany.sca.host.embedded.management.ComponentListener; +import org.apache.tuscany.sca.host.embedded.management.ComponentManager; + +public class ComponentManagerImpl implements ComponentManager { + + protected List<ComponentListener> listeners = new CopyOnWriteArrayList<ComponentListener>(); + protected EmbeddedSCADomain domain; + + public ComponentManagerImpl(EmbeddedSCADomain domain) { + this.domain = domain; + } + + public void addComponentListener(ComponentListener listener) { + this.listeners.add(listener); + } + + public void removeComponentListener(ComponentListener listener) { + this.listeners.remove(listener); + } + + public Set<String> getComponentNames() { + Set<String> names = new HashSet<String>(); + for (Composite composite: domain.getDomainComposite().getIncludes()) { + for (Component component: composite.getComponents()) { + names.add(component.getName()); + } + } + return names; + } + + public Component getComponent(String componentName) { + for (Composite composite: domain.getDomainComposite().getIncludes()) { + for (Component component: composite.getComponents()) { + if (component.getName().equals(componentName)) { + return component; + } + } + } + return null; + } + + public void startComponent(String componentName) throws ActivationException { + Component component = getComponent(componentName); + if (component == null) { + throw new IllegalArgumentException("no component: " + componentName); + } + domain.getCompositeActivator().start(component); + notifyComponentStarted(componentName); + } + + public void stopComponent(String componentName) throws ActivationException { + Component component = getComponent(componentName); + if (component == null) { + throw new IllegalArgumentException("no component: " + componentName); + } + domain.getCompositeActivator().stop(component); + notifyComponentStopped(componentName); + } + + public void notifyComponentStarted(String componentName) { + for (ComponentListener listener : listeners) { + try { + listener.componentStarted(componentName); + } catch (Exception e) { + e.printStackTrace(); // TODO: log + } + } + } + + public void notifyComponentStopped(String componentName) { + for (ComponentListener listener : listeners) { + try { + listener.componentStopped(componentName); + } catch (Exception e) { + e.printStackTrace(); // TODO: log + } + } + } + + public boolean isComponentStarted(String componentName) { + RuntimeComponentImpl runtimeComponent = (RuntimeComponentImpl)getComponent(componentName); + return runtimeComponent.isStarted(); + } + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomain.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomain.java new file mode 100644 index 0000000000..40f2069379 --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomain.java @@ -0,0 +1,627 @@ +/* + * 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.host.embedded.impl; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.SCABinding; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.assembly.xml.Constants; +import org.apache.tuscany.sca.contribution.Artifact; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.service.ContributionException; +import org.apache.tuscany.sca.contribution.service.ContributionService; +import org.apache.tuscany.sca.contribution.service.util.FileHelper; +import org.apache.tuscany.sca.core.assembly.ActivationException; +import org.apache.tuscany.sca.core.assembly.CompositeActivator; +import org.apache.tuscany.sca.core.assembly.RuntimeComponentImpl; +import org.apache.tuscany.sca.core.context.ServiceReferenceImpl; +import org.apache.tuscany.sca.host.embedded.SCADomain; +import org.apache.tuscany.sca.host.embedded.management.ComponentListener; +import org.apache.tuscany.sca.host.embedded.management.ComponentManager; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentContext; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.osoa.sca.CallableReference; +import org.osoa.sca.ServiceReference; +import org.osoa.sca.ServiceRuntimeException; + +/** + * A default SCA domain facade implementation. + * + * @version $Rev$ $Date$ + */ +public class DefaultSCADomain extends SCADomain { + + private String uri; + private String[] composites; + private Composite domainComposite; + private List<Contribution> contributions; + private Map<String, Component> components; + private ReallySmallRuntime runtime; + private ComponentManager componentManager; + private ClassLoader runtimeClassLoader; + private ClassLoader applicationClassLoader; + private String domainURI; + private String contributionLocation; + + /** + * Constructs a new domain facade. + * + * @param domainURI + * @param contributionLocation + * @param composites + */ + public DefaultSCADomain(ClassLoader runtimeClassLoader, + ClassLoader applicationClassLoader, + String domainURI, + String contributionLocation, + String... composites) { + this.uri = domainURI; + this.composites = composites; + this.runtimeClassLoader = runtimeClassLoader; + this.applicationClassLoader = applicationClassLoader; + this.domainURI = domainURI; + this.contributionLocation = contributionLocation; + this.composites = composites; + + init(); + + } + + public void init() { + contributions = new ArrayList<Contribution>(); + components = new HashMap<String, Component>(); + runtime = new ReallySmallRuntime(runtimeClassLoader); + try { + runtime.start(); + + } catch (ActivationException e) { + throw new ServiceRuntimeException(e); + } + + // Contribute the given contribution to an in-memory repository + ContributionService contributionService = runtime.getContributionService(); + URL contributionURL; + try { + contributionURL = getContributionLocation(applicationClassLoader, contributionLocation, this.composites); + if (contributionURL != null) { + // Make sure the URL is correctly encoded (for example, escape the space characters) + contributionURL = contributionURL.toURI().toURL(); + } + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + + try { + String scheme = contributionURL.toURI().getScheme(); + if (scheme == null || scheme.equalsIgnoreCase("file")) { + File contributionFile = new File(contributionURL.toURI()); + if (contributionFile.isDirectory()) { + String[] contributions = contributionFile.list(new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.endsWith(".jar"); + } + }); + if (contributions != null && contributions.length > 0 && contributions.length == contributionFile.list().length) { + for (String contribution : contributions) { + addContribution(contributionService, new File(contributionFile, contribution).toURI().toURL()); + } + } else { + addContribution(contributionService, contributionURL); + } + } else { + addContribution(contributionService, contributionURL); + } + } else { + addContribution(contributionService, contributionURL); + } + } catch (IOException e) { + throw new ServiceRuntimeException(e); + } catch (URISyntaxException e) { + throw new ServiceRuntimeException(e); + } + + // Create an in-memory domain level composite + AssemblyFactory assemblyFactory = runtime.getAssemblyFactory(); + domainComposite = assemblyFactory.createComposite(); + domainComposite.setName(new QName(Constants.SCA10_NS, "domain")); + domainComposite.setURI(domainURI); + + //when the deployable composites were specified when initializing the runtime + if (composites != null && composites.length > 0 && composites[0].length() > 0) { + // Include all specified deployable composites in the SCA domain + Map<String, Composite> compositeArtifacts = new HashMap<String, Composite>(); + for (Contribution contribution : contributions) { + for (Artifact artifact : contribution.getArtifacts()) { + if (artifact.getModel() instanceof Composite) { + compositeArtifacts.put(artifact.getURI(), (Composite)artifact.getModel()); + } + } + } + for (String compositePath : composites) { + Composite composite = compositeArtifacts.get(compositePath); + if (composite == null) { + throw new ServiceRuntimeException("Composite not found: " + compositePath); + } + domainComposite.getIncludes().add(composite); + } + } else { + // in this case, a sca-contribution.xml should have been specified + for (Contribution contribution : contributions) { + for (Composite composite : contribution.getDeployables()) { + domainComposite.getIncludes().add(composite); + } + } + } + + //update the runtime for all SCA Definitions processed from the contribution.. + //so that the policyset determination done during 'build' has the all the defined + //intents and policysets + //runtime.updateSCADefinitions(null); + + // Build the SCA composites + for (Composite composite : domainComposite.getIncludes()) { + try { + runtime.buildComposite(composite); + } catch (CompositeBuilderException e) { + throw new ServiceRuntimeException(e); + } + } + + // Activate and start composites + CompositeActivator compositeActivator = runtime.getCompositeActivator(); + compositeActivator.setDomainComposite(domainComposite); + for (Composite composite : domainComposite.getIncludes()) { + try { + compositeActivator.activate(composite); + } catch (ActivationException e) { + throw new ServiceRuntimeException(e); + } + } + for (Composite composite : domainComposite.getIncludes()) { + try { + for (Component component : composite.getComponents()) { + compositeActivator.start(component); + } + } catch (ActivationException e) { + throw new ServiceRuntimeException(e); + } + } + + // Index the top level components + for (Composite composite : domainComposite.getIncludes()) { + for (Component component : composite.getComponents()) { + components.put(component.getName(), component); + } + } + + this.componentManager = new DefaultSCADomainComponentManager(this); + + // For debugging purposes, print the composites +// ExtensionPointRegistry extensionPoints = runtime.getExtensionPointRegistry(); +// StAXArtifactProcessorExtensionPoint artifactProcessors = extensionPoints.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); +// StAXArtifactProcessor processor = artifactProcessors.getProcessor(Composite.class); +// for (Composite composite : domainComposite.getIncludes()) { +// try { +// ByteArrayOutputStream bos = new ByteArrayOutputStream(); +// XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); +// outputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE); +// processor.write(composite, outputFactory.createXMLStreamWriter(bos)); +// Document document = +// DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(bos +// .toByteArray())); +// OutputFormat format = new OutputFormat(); +// format.setIndenting(true); +// format.setIndent(2); +// XMLSerializer serializer = new XMLSerializer(System.out, format); +// serializer.serialize(document); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } + } + + protected void addContribution(ContributionService contributionService, URL contributionURL) throws IOException { + try { + String contributionURI = FileHelper.getName(contributionURL.getPath()); + if (contributionURI == null || contributionURI.length() == 0) { + contributionURI = contributionURL.toString(); + } + contributions.add(contributionService.contribute(contributionURI, contributionURL, false)); + } catch (ContributionException e) { + throw new ServiceRuntimeException(e); + } + } + + @Override + public void close() { + + super.close(); + + // Stop and deactivate composites + CompositeActivator compositeActivator = runtime.getCompositeActivator(); + for (Composite composite : domainComposite.getIncludes()) { + try { + for (Component component : composite.getComponents()) { + compositeActivator.stop(component); + } + } catch (ActivationException e) { + throw new ServiceRuntimeException(e); + } + } + for (Composite composite : domainComposite.getIncludes()) { + try { + compositeActivator.deactivate(composite); + } catch (ActivationException e) { + throw new ServiceRuntimeException(e); + } + } + + // Remove the contribution from the in-memory repository + ContributionService contributionService = runtime.getContributionService(); + for (Contribution contribution : contributions) { + try { + contributionService.remove(contribution.getURI()); + } catch (ContributionException e) { + throw new ServiceRuntimeException(e); + } + } + + // Stop the runtime + try { + runtime.stop(); + } catch (ActivationException e) { + throw new ServiceRuntimeException(e); + } + } + + /** + * Determine the location of a contribution, given a contribution path and a + * list of composites. + * + * @param contributionPath + * @param composites + * @param classLoader + * @return + * @throws MalformedURLException + */ + protected URL getContributionLocation(ClassLoader classLoader, String contributionPath, String[] composites) + throws MalformedURLException { + if (contributionPath != null && contributionPath.length() > 0) { + //encode spaces as they would cause URISyntaxException + contributionPath = contributionPath.replace(" ", "%20"); + URI contributionURI = URI.create(contributionPath); + if (contributionURI.isAbsolute() || composites.length == 0) { + return new URL(contributionPath); + } + } + + String contributionArtifactPath = null; + URL contributionArtifactURL = null; + if (composites != null && composites.length > 0 && composites[0].length() > 0) { + + // Here the SCADomain was started with a reference to a composite file + contributionArtifactPath = composites[0]; + contributionArtifactURL = classLoader.getResource(contributionArtifactPath); + if (contributionArtifactURL == null) { + throw new IllegalArgumentException("Composite not found: " + contributionArtifactPath); + } + } else { + + // Here the SCADomain was started without any reference to a composite file + // We are going to look for an sca-contribution.xml or sca-contribution-generated.xml + + // Look for META-INF/sca-contribution.xml + contributionArtifactPath = Contribution.SCA_CONTRIBUTION_META; + contributionArtifactURL = classLoader.getResource(contributionArtifactPath); + + // Look for META-INF/sca-contribution-generated.xml + if (contributionArtifactURL == null) { + contributionArtifactPath = Contribution.SCA_CONTRIBUTION_GENERATED_META; + contributionArtifactURL = classLoader.getResource(contributionArtifactPath); + } + + // Look for META-INF/sca-deployables directory + if (contributionArtifactURL == null) { + contributionArtifactPath = Contribution.SCA_CONTRIBUTION_DEPLOYABLES; + contributionArtifactURL = classLoader.getResource(contributionArtifactPath); + } + } + + if (contributionArtifactURL == null) { + throw new IllegalArgumentException( + "Can't determine contribution deployables. Either specify a composite file, or use an sca-contribution.xml file to specify the deployables."); + } + + URL contributionURL = null; + // "jar:file://....../something.jar!/a/b/c/app.composite" + try { + String url = contributionArtifactURL.toExternalForm(); + String protocol = contributionArtifactURL.getProtocol(); + if ("file".equals(protocol)) { + // directory contribution + if (url.endsWith(contributionArtifactPath)) { + String location = url.substring(0, url.lastIndexOf(contributionArtifactPath)); + // workaround from evil url/uri form maven + contributionURL = FileHelper.toFile(new URL(location)).toURI().toURL(); + } + + } else if ("jar".equals(protocol)) { + // jar contribution + String location = url.substring(4, url.lastIndexOf("!/")); + // workaround for evil url/uri from maven + contributionURL = FileHelper.toFile(new URL(location)).toURI().toURL(); + + } else if (protocol != null && (protocol.equals("bundle")||protocol.equals("bundleresource"))){ + contributionURL = new URL(contributionArtifactURL.getProtocol(), + contributionArtifactURL.getHost(), + contributionArtifactURL.getPort(), + "/"); + } + } catch (MalformedURLException mfe) { + throw new IllegalArgumentException(mfe); + } + + return contributionURL; + } + + @Override + @SuppressWarnings("unchecked") + public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException { + return (R)runtime.getProxyFactory().cast(target); + } + + @Override + public <B> B getService(Class<B> businessInterface, String serviceName) { + ServiceReference<B> serviceReference = getServiceReference(businessInterface, serviceName); + if (serviceReference == null) { + throw new ServiceRuntimeException("Service not found: " + serviceName); + } + return serviceReference.getService(); + } + + private <B> ServiceReference<B> createServiceReference(Class<B> businessInterface, String targetURI) { + try { + AssemblyFactory assemblyFactory = runtime.getAssemblyFactory(); + Composite composite = assemblyFactory.createComposite(); + composite.setName(new QName(Constants.SCA10_TUSCANY_NS, "default")); + RuntimeComponent component = (RuntimeComponent)assemblyFactory.createComponent(); + component.setName("default"); + component.setURI("default"); + runtime.getCompositeActivator().configureComponentContext(component); + composite.getComponents().add(component); + RuntimeComponentReference reference = (RuntimeComponentReference)assemblyFactory.createComponentReference(); + reference.setName("default"); + ModelFactoryExtensionPoint factories = + runtime.getExtensionPointRegistry().getExtensionPoint(ModelFactoryExtensionPoint.class); + JavaInterfaceFactory javaInterfaceFactory = factories.getFactory(JavaInterfaceFactory.class); + InterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract(); + interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(businessInterface)); + reference.setInterfaceContract(interfaceContract); + component.getReferences().add(reference); + reference.setComponent(component); + SCABindingFactory scaBindingFactory = factories.getFactory(SCABindingFactory.class); + SCABinding binding = scaBindingFactory.createSCABinding(); + binding.setURI(targetURI); + reference.getBindings().add(binding); + return new ServiceReferenceImpl<B>(businessInterface, component, reference, binding, runtime + .getProxyFactory(), runtime.getCompositeActivator()); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + @Override + public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String name) { + + // Extract the component name + String componentName; + String serviceName; + int i = name.indexOf('/'); + if (i != -1) { + componentName = name.substring(0, i); + serviceName = name.substring(i + 1); + + } else { + componentName = name; + serviceName = null; + } + + // Lookup the component in the domain + Component component = components.get(componentName); + if (component == null) { + // The component is not local in the partition, try to create a remote service ref + return createServiceReference(businessInterface, name); + } + RuntimeComponentContext componentContext = null; + + // If the component is a composite, then we need to find the + // non-composite component that provides the requested service + if (component.getImplementation() instanceof Composite) { + for (ComponentService componentService : component.getServices()) { + if (serviceName == null || serviceName.equals(componentService.getName())) { + CompositeService compositeService = (CompositeService)componentService.getService(); + if (compositeService != null) { + if (serviceName != null) { + serviceName = "$promoted$." + serviceName; + } + componentContext = + ((RuntimeComponent)compositeService.getPromotedComponent()).getComponentContext(); + return componentContext.createSelfReference(businessInterface, compositeService + .getPromotedService()); + } + break; + } + } + // No matching service is found + throw new ServiceRuntimeException("Composite service not found: " + name); + } else { + componentContext = ((RuntimeComponent)component).getComponentContext(); + if (serviceName != null) { + return componentContext.createSelfReference(businessInterface, serviceName); + } else { + return componentContext.createSelfReference(businessInterface); + } + } + + } + + @Override + public String getURI() { + return uri; + } + + @Override + public ComponentManager getComponentManager() { + return componentManager; + } + + public Set<String> getComponentNames() { + Set<String> componentNames = new HashSet<String>(); + for (Contribution contribution : contributions) { + for (Artifact artifact : contribution.getArtifacts()) { + if (artifact.getModel() instanceof Composite) { + for (Component component : ((Composite)artifact.getModel()).getComponents()) { + componentNames.add(component.getName()); + } + } + } + } + return componentNames; + } + + public Component getComponent(String componentName) { + for (Contribution contribution : contributions) { + for (Artifact artifact : contribution.getArtifacts()) { + if (artifact.getModel() instanceof Composite) { + for (Component component : ((Composite)artifact.getModel()).getComponents()) { + if (component.getName().equals(componentName)) { + return component; + } + } + } + } + } + return null; + } + + public void startComponent(String componentName) throws ActivationException { + Component component = getComponent(componentName); + if (component == null) { + throw new IllegalArgumentException("no component: " + componentName); + } + CompositeActivator compositeActivator = runtime.getCompositeActivator(); + compositeActivator.start(component); + } + + public void stopComponent(String componentName) throws ActivationException { + Component component = getComponent(componentName); + if (component == null) { + throw new IllegalArgumentException("no component: " + componentName); + } + CompositeActivator compositeActivator = runtime.getCompositeActivator(); + compositeActivator.stop(component); + } +} + +class DefaultSCADomainComponentManager implements ComponentManager { + + protected DefaultSCADomain scaDomain; + protected List<ComponentListener> listeners = new CopyOnWriteArrayList<ComponentListener>(); + + public DefaultSCADomainComponentManager(DefaultSCADomain scaDomain) { + this.scaDomain = scaDomain; + } + + public void addComponentListener(ComponentListener listener) { + this.listeners.add(listener); + } + + public void removeComponentListener(ComponentListener listener) { + this.listeners.remove(listener); + } + + public Set<String> getComponentNames() { + return scaDomain.getComponentNames(); + } + + public Component getComponent(String componentName) { + return scaDomain.getComponent(componentName); + } + + public void startComponent(String componentName) throws ActivationException { + scaDomain.startComponent(componentName); + } + + public void stopComponent(String componentName) throws ActivationException { + scaDomain.stopComponent(componentName); + } + + public void notifyComponentStarted(String componentName) { + for (ComponentListener listener : listeners) { + try { + listener.componentStarted(componentName); + } catch (Exception e) { + e.printStackTrace(); // TODO: log + } + } + } + + public void notifyComponentStopped(String componentName) { + for (ComponentListener listener : listeners) { + try { + listener.componentStopped(componentName); + } catch (Exception e) { + e.printStackTrace(); // TODO: log + } + } + } + + public boolean isComponentStarted(String componentName) { + RuntimeComponentImpl runtimeComponent = (RuntimeComponentImpl)getComponent(componentName); + return runtimeComponent.isStarted(); + } + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomain.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomain.java new file mode 100644 index 0000000000..8827a92387 --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomain.java @@ -0,0 +1,237 @@ +/* + * 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.host.embedded.impl; + +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.SCABinding; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.assembly.xml.Constants; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.service.ContributionService; +import org.apache.tuscany.sca.core.assembly.ActivationException; +import org.apache.tuscany.sca.core.assembly.CompositeActivator; +import org.apache.tuscany.sca.core.context.ServiceReferenceImpl; +import org.apache.tuscany.sca.definitions.SCADefinitions; +import org.apache.tuscany.sca.host.embedded.SCADomain; +import org.apache.tuscany.sca.host.embedded.management.ComponentManager; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentContext; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.osoa.sca.CallableReference; +import org.osoa.sca.ServiceReference; +import org.osoa.sca.ServiceRuntimeException; + +/** + * An SCA domain facade implementation. + * + * @version $Rev$ $Date$ + */ +public class EmbeddedSCADomain extends SCADomain { + + private String uri; + private Composite domainComposite; + private ReallySmallRuntime runtime; + private ComponentManagerImpl componentManager = new ComponentManagerImpl(this); + + /** + * Constructs a new domain facade. + * + * @param runtimeClassLoader + * @param domainURI + */ + public EmbeddedSCADomain(ClassLoader runtimeClassLoader, + String domainURI) { + this.uri = domainURI; + + // Create a runtime + runtime = new ReallySmallRuntime(runtimeClassLoader); + } + + public void start() throws ActivationException { + + // Start the runtime + runtime.start(); + + // Create an in-memory domain level composite + AssemblyFactory assemblyFactory = runtime.getAssemblyFactory(); + domainComposite = assemblyFactory.createComposite(); + domainComposite.setName(new QName(Constants.SCA10_NS, "domain")); + domainComposite.setURI(uri); + + getCompositeActivator().setDomainComposite(domainComposite); + + } + + public void stop() throws ActivationException { + + // Stop the runtime + runtime.stop(); + + // Cleanup + domainComposite = null; + } + + public void buildComposite(Composite composite) throws CompositeBuilderException { + runtime.buildComposite(composite); + } + + public ContributionService getContributionService() { + return runtime.getContributionService(); + } + + public CompositeBuilder getCompositeBuilder() { + return runtime.getCompositeBuilder(); + } + + public CompositeActivator getCompositeActivator() { + return runtime.getCompositeActivator(); + } + + public Composite getDomainComposite() { + return domainComposite; + } + + @Override + public ComponentManager getComponentManager() { + return componentManager; + } + + @Override + public void close() { + super.close(); + } + + @Override + public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException { + return (R)runtime.getProxyFactory().cast(target); + } + + @Override + public <B> B getService(Class<B> businessInterface, String serviceName) { + ServiceReference<B> serviceReference = getServiceReference(businessInterface, serviceName); + if (serviceReference == null) { + throw new ServiceRuntimeException("Service not found: " + serviceName); + } + return serviceReference.getService(); + } + + private <B> ServiceReference<B> createServiceReference(Class<B> businessInterface, String targetURI) { + try { + AssemblyFactory assemblyFactory = runtime.getAssemblyFactory(); + Composite composite = assemblyFactory.createComposite(); + composite.setName(new QName(Constants.SCA10_TUSCANY_NS, "default")); + RuntimeComponent component = (RuntimeComponent)assemblyFactory.createComponent(); + component.setName("default"); + component.setURI("default"); + runtime.getCompositeActivator().configureComponentContext(component); + composite.getComponents().add(component); + RuntimeComponentReference reference = (RuntimeComponentReference)assemblyFactory.createComponentReference(); + reference.setName("default"); + ModelFactoryExtensionPoint factories = + runtime.getExtensionPointRegistry().getExtensionPoint(ModelFactoryExtensionPoint.class); + JavaInterfaceFactory javaInterfaceFactory = factories.getFactory(JavaInterfaceFactory.class); + InterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract(); + interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(businessInterface)); + reference.setInterfaceContract(interfaceContract); + component.getReferences().add(reference); + reference.setComponent(component); + SCABindingFactory scaBindingFactory = factories.getFactory(SCABindingFactory.class); + SCABinding binding = scaBindingFactory.createSCABinding(); + binding.setURI(targetURI); + reference.getBindings().add(binding); + return new ServiceReferenceImpl<B>(businessInterface, component, reference, binding, runtime + .getProxyFactory(), runtime.getCompositeActivator()); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + @Override + public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String name) { + + // Extract the component name + String componentName; + String serviceName; + int i = name.indexOf('/'); + if (i != -1) { + componentName = name.substring(0, i); + serviceName = name.substring(i + 1); + + } else { + componentName = name; + serviceName = null; + } + + // Lookup the component in the domain + Component component = componentManager.getComponent(componentName); + if (component == null) { + // The component is not local in the partition, try to create a remote service ref + return createServiceReference(businessInterface, name); + } + RuntimeComponentContext componentContext = null; + + // If the component is a composite, then we need to find the + // non-composite component that provides the requested service + if (component.getImplementation() instanceof Composite) { + for (ComponentService componentService : component.getServices()) { + if (serviceName == null || serviceName.equals(componentService.getName())) { + CompositeService compositeService = (CompositeService)componentService.getService(); + if (compositeService != null) { + if (serviceName != null) { + serviceName = "$promoted$." + serviceName; + } + componentContext = + ((RuntimeComponent)compositeService.getPromotedComponent()).getComponentContext(); + return componentContext.createSelfReference(businessInterface, compositeService + .getPromotedService()); + } + break; + } + } + // No matching service is found + throw new ServiceRuntimeException("Composite service not found: " + name); + } else { + componentContext = ((RuntimeComponent)component).getComponentContext(); + if (serviceName != null) { + return componentContext.createSelfReference(businessInterface, serviceName); + } else { + return componentContext.createSelfReference(businessInterface); + } + } + + } + + @Override + public String getURI() { + return uri; + } + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/HotUpdatableSCADomain.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/HotUpdatableSCADomain.java new file mode 100644 index 0000000000..e6ced00e1d --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/HotUpdatableSCADomain.java @@ -0,0 +1,387 @@ +/* + * 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.host.embedded.impl; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.service.ContributionService; +import org.apache.tuscany.sca.contribution.service.util.FileHelper; +import org.apache.tuscany.sca.core.assembly.ActivationException; +import org.apache.tuscany.sca.host.embedded.SCADomain; +import org.apache.tuscany.sca.host.embedded.management.ComponentManager; +import org.osoa.sca.CallableReference; +import org.osoa.sca.ServiceReference; +import org.osoa.sca.ServiceRuntimeException; + +/** + * An SCADomain that starts a Tuscany runtime supporting multiple + * SCA contribution jars. All contribution jars found in a repository + * directory will be contributed to the SCA domain. Any changes to the + * contributions in that repository will be automatically detected and + * the sca domain updated accordingly. + * + * TODO: find how to properly add/remove contributions and start/activate the doamain + * TODO: support contributions that are folders as well as jar's + * TODO: needs to restart the entire scadomain when a contribution changes + * as the domain classpath includes all the contribution jar's, would + * be nice to find a way to avoid this + * TODO: hot update requires copying contribution jars to a temp location + * to avoid the classpath lock preventing updating the contribution + * jars, would be nice to find a way to avoid that + */ +public class HotUpdatableSCADomain extends SCADomain { + private static final Logger logger = Logger.getLogger(HotUpdatableSCADomain.class.getName()); + protected String domainURI; + protected File contributionRepository; + + protected EmbeddedSCADomain scaDomain; + + protected boolean hotUpdateActive; + protected Thread hotUpdateThread; + protected int hotUpdateInterval; // milliseconds, 0 = hotupdate disabled + + protected HashMap<URL, Long> existingContributions; // value is last modified time + protected ClassLoader originalCCL; + + protected static final String REPOSITORY_FOLDER = "sca-contributions"; + + public HotUpdatableSCADomain(String domainURI, File contributionRepository, int hotupdateInterval) { + this.domainURI = domainURI; + this.contributionRepository = contributionRepository; + this.hotUpdateInterval = hotupdateInterval; + this.originalCCL = Thread.currentThread().getContextClassLoader(); + start(); + } + + protected void start() { + try { + initEmbeddedSCADomain(); + activateHotUpdate(); + for (URL url : existingContributions.keySet()) { + File f = new File(url.toURI()); + logger.info("added contribution: " + f.getName()); + } + } catch (ActivationException e) { + throw new ServiceRuntimeException(e); + } catch (URISyntaxException e) { + throw new ServiceRuntimeException(e); + } + } + + @Override + public void close() { + try { + hotUpdateActive = false; + scaDomain.stop(); + } catch (ActivationException e) { + throw new ServiceRuntimeException(e); + } + Thread.currentThread().setContextClassLoader(originalCCL); + super.close(); + } + + + protected SCADomain initEmbeddedSCADomain() throws ActivationException { + + URL[] contributionJars = getContributionJarURLs(contributionRepository); + + this.existingContributions = getLastModified(contributionJars); + + if (hotUpdateInterval > 0) { + contributionJars = copyContributionsToTemp(contributionJars); + } + + // Using the CCL as the parent exposes Tuscany to the contributions, want to do this? + URLClassLoader cl = new URLClassLoader(contributionJars, originalCCL); + Thread.currentThread().setContextClassLoader(cl); + + scaDomain = new EmbeddedSCADomain(cl, domainURI); + + scaDomain.start(); + + initContributions(scaDomain, cl, contributionJars); + + return scaDomain; + } + + protected URL[] getContributionJarURLs(File repositoryDir) { + + String[] jars = repositoryDir.list(new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.endsWith(".jar"); + }}); + + List<URL> contributionJars = new ArrayList<URL>(); + if (jars != null) { + for (String jar : jars) { + try { + contributionJars.add(new File(repositoryDir, jar).toURL()); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + } + + return contributionJars.toArray(new URL[contributionJars.size()]); + } + + /** + * TODO: No idea what the 'correct' way to add/contribute and activate/start things to an scaDomain is + * but this seems to work. Doesn't seem to start <service>s or <reference>s which are outside of + * a <component> so something is missing/wrong. Also this doesn't seem to be picking up composites + * located in META-INF/deployables or specified in the sca-deployables.xml. Maybe the EmbeddedSCADomain + * and ContributionService APIs should make all this easier? + */ + protected void initContributions(EmbeddedSCADomain scaDomain, ClassLoader cl, URL[] contributionJars) { + Contribution contribution = null; + ContributionService contributionService = scaDomain.getContributionService(); + for (URL jar : contributionJars) { + InputStream is = null; + try { + is = jar.openStream(); + contribution = contributionService.contribute(jar.toString(), jar, is); + } catch (Exception e) { + System.err.println("exception adding contribution: " + jar); + e.printStackTrace(); + } + if (is != null) { + try { + is.close(); + } catch (IOException e) { + // ignore + } + } + } + + if (contribution != null ) { + try { + + for (Composite composite : contribution.getDeployables()) { + scaDomain.getDomainComposite().getIncludes().add(composite); + scaDomain.getCompositeBuilder().build(composite); + scaDomain.getCompositeActivator().activate(composite); + } + + for (Composite composite : contribution.getDeployables()) { + scaDomain.getCompositeActivator().start(composite); + } + + } catch (ActivationException e) { + throw new RuntimeException(e); + } catch (CompositeBuilderException e) { + throw new RuntimeException(e); + } + } + + } + + /** + * Copies Files to a temp location returning the URLs of the new temp files. + * For hot update to work need to be able to delete/update the contribution jar's + * but as they're in the classpath the URLClassLoader has an open lock on the jar's + * so you can't update them. This solution copies each contribution to a temp + * location for use on the classpath, nicer would be a ClassLoder impl that doesn't + * lock the jar's. + */ + protected URL[] copyContributionsToTemp(URL[] contributionJars) { + try { + + URL[] newURLs = new URL[contributionJars.length]; + File tempDir = new File(System.getProperty("java.io.tmpdir")); + for (int i=0; i<contributionJars.length; i++) { + File fin = new File(contributionJars[i].toURI()); + File fout = File.createTempFile("tuscany", fin.getName(), tempDir); + fout.deleteOnExit(); + FileHelper.copyFile(fin, fout); + fout.setLastModified(System.currentTimeMillis()); + newURLs[i] = fout.toURL(); + } + return newURLs; + + } catch (IOException e) { + throw new RuntimeException(e); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + /** + * Returns the last modified times of the files pointed to by the URLs + */ + protected HashMap<URL, Long> getLastModified(URL[] contrabutions) { + try { + + HashMap<URL, Long> contributionLastUpdates = new HashMap<URL, Long>(); + for (URL url: contrabutions) { + File f = new File(url.toURI()); + contributionLastUpdates.put(url, new Long(f.lastModified())); + } + return contributionLastUpdates; + + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + protected void activateHotUpdate() { + if (hotUpdateInterval == 0) { + return; // hotUpdateInterval of 0 disables hotupdate + } + + Runnable runable = new Runnable() { + public void run() { + logger.info("Tuscany contribution hotupdate running"); + while (hotUpdateActive) { + try { + Thread.sleep(hotUpdateInterval); + } catch (InterruptedException e) { + } + if (hotUpdateActive) { + checkForUpdates(); + } + } + logger.info("Tuscany contribution hotupdate stopped"); + } + }; + hotUpdateThread = new Thread(runable, "TuscanyHotUpdate"); + hotUpdateActive = true; + hotUpdateThread.start(); + } + + + /** + * Checks if any of the contributions have been updated and if so restarts the sca domain + * TODO: Ideally just the altered contribution would be restarted but thats not possible + * as the classloader used by the SCADomain includes the old contribution so need + * to restart the entire domain to use a new ClassLoader. Should there be seperate + * ClassLoader per contribution? But then have all the issues with sharing classes + * across contributions. + */ + protected void checkForUpdates() { + URL[] currentContributions = getContributionJarURLs(contributionRepository); + + if (areContributionsAltered(currentContributions)) { + try { + scaDomain.stop(); + } catch (Exception e) { + e.printStackTrace(); + } + try { + initEmbeddedSCADomain(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + protected boolean areContributionsAltered(URL[] currentContrabutions) { + try { + + List addedContributions = getAddedContributions(currentContrabutions); + List removedContributions = getRemovedContributions(currentContrabutions); + List updatedContributions = getUpdatedContributions(currentContrabutions); + + return (addedContributions.size() > 0 || removedContributions.size() > 0 || updatedContributions.size() > 0); + + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + protected List<URL> getUpdatedContributions(URL[] currentContrabutions) throws URISyntaxException { + List<URL> urls = new ArrayList<URL>(); + for (URL url : currentContrabutions) { + if (existingContributions.containsKey(url)) { + File curentFile = new File(url.toURI()); + if (curentFile.lastModified() != existingContributions.get(url)) { + urls.add(url); + logger.info("updated contribution: " + curentFile.getName()); + } + } + } + return urls; + } + + protected List getRemovedContributions(URL[] currentContrabutions) throws URISyntaxException { + List<URL> currentUrls = Arrays.asList(currentContrabutions); + List<URL> urls = new ArrayList<URL>(); + for (URL url : existingContributions.keySet()) { + if (!currentUrls.contains(url)) { + urls.add(url); + } + } + for (URL url : urls) { + logger.info("removed contributions: " + new File(url.toURI()).getName()); + } + return urls; + } + + protected List getAddedContributions(URL[] currentContrabutions) throws URISyntaxException { + List<URL> urls = new ArrayList<URL>(); + for (URL url : currentContrabutions) { + if (!existingContributions.containsKey(url)) { + urls.add(url); + logger.info("added contribution: " + new File(url.toURI()).getName()); + } + } + return urls; + } + + @Override + public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException { + throw new UnsupportedOperationException("not implemented"); + } + + @Override + public <B> B getService(Class<B> businessInterface, String serviceName) { + return scaDomain.getService(businessInterface, serviceName); + } + + @Override + public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String referenceName) { + return scaDomain.getServiceReference(businessInterface, referenceName); + } + + @Override + public String getURI() { + return domainURI; + } + + @Override + public ComponentManager getComponentManager(){ + return scaDomain.getComponentManager(); + } + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntime.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntime.java new file mode 100644 index 0000000000..60fc6dae2b --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntime.java @@ -0,0 +1,384 @@ +/* + * 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.host.embedded.impl; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.assembly.builder.DomainBuilder; +import org.apache.tuscany.sca.context.ContextFactoryExtensionPoint; +import org.apache.tuscany.sca.context.DefaultContextFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionService; +import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.ModuleActivator; +import org.apache.tuscany.sca.core.assembly.ActivationException; +import org.apache.tuscany.sca.core.assembly.CompositeActivator; +import org.apache.tuscany.sca.core.assembly.RuntimeAssemblyFactory; +import org.apache.tuscany.sca.core.invocation.MessageFactoryImpl; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.scope.ScopeRegistry; +import org.apache.tuscany.sca.definitions.SCADefinitions; +import org.apache.tuscany.sca.definitions.SCADefinitionsProvider; +import org.apache.tuscany.sca.definitions.SCADefinitionsProviderExtensionPoint; +import org.apache.tuscany.sca.definitions.impl.SCADefinitionsImpl; +import org.apache.tuscany.sca.definitions.util.SCADefinitionsUtil; +import org.apache.tuscany.sca.definitions.xml.SCADefinitionsDocumentProcessor; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.impl.InterfaceContractMapperImpl; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.policy.DefaultIntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.DefaultPolicyFactory; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.work.WorkScheduler; + +public class ReallySmallRuntime { + private final static Logger logger = Logger.getLogger(ReallySmallRuntime.class.getName()); + private List<ModuleActivator> modules; + private ExtensionPointRegistry registry; + + private ClassLoader classLoader; + private AssemblyFactory assemblyFactory; + private ContributionService contributionService; + private CompositeActivator compositeActivator; + private CompositeBuilder compositeBuilder; + private DomainBuilder domainBuilder; + private WorkScheduler workScheduler; + private ScopeRegistry scopeRegistry; + private ProxyFactory proxyFactory; + private List scaDefnsSink = new ArrayList(); + + public ReallySmallRuntime(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + public void start() throws ActivationException { + long start = System.currentTimeMillis(); + + // Create our extension point registry + registry = new DefaultExtensionPointRegistry(); + + //Get work scheduler + workScheduler = registry.getExtensionPoint(WorkScheduler.class); + + // Create an interface contract mapper + InterfaceContractMapper mapper = new InterfaceContractMapperImpl(); + + // Get factory extension point + ModelFactoryExtensionPoint factories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + + // Create context factory extension point + ContextFactoryExtensionPoint contextFactories = new DefaultContextFactoryExtensionPoint(); + registry.addExtensionPoint(contextFactories); + + // Create Message factory + MessageFactory messageFactory = new MessageFactoryImpl(); + factories.addFactory(messageFactory); + + // Create a proxy factory + proxyFactory = ReallySmallRuntimeBuilder.createProxyFactory(registry, mapper, messageFactory); + + // Create model factories + assemblyFactory = new RuntimeAssemblyFactory(); + factories.addFactory(assemblyFactory); + PolicyFactory policyFactory = new DefaultPolicyFactory(); + factories.addFactory(policyFactory); + + // Load the runtime modules + modules = loadModules(registry); + + // Start the runtime modules + startModules(registry, modules); + + SCABindingFactory scaBindingFactory = factories.getFactory(SCABindingFactory.class); + IntentAttachPointTypeFactory intentAttachPointTypeFactory = new DefaultIntentAttachPointTypeFactory(); + factories.addFactory(intentAttachPointTypeFactory); + ContributionFactory contributionFactory = factories.getFactory(ContributionFactory.class); + + // Create a contribution service + contributionService = ReallySmallRuntimeBuilder.createContributionService(classLoader, + registry, + contributionFactory, + assemblyFactory, + policyFactory, + mapper, + scaDefnsSink); + + // Create the ScopeRegistry + scopeRegistry = ReallySmallRuntimeBuilder.createScopeRegistry(registry); + + // Create a composite activator + compositeActivator = ReallySmallRuntimeBuilder.createCompositeActivator(registry, + assemblyFactory, + messageFactory, + scaBindingFactory, + mapper, + proxyFactory, + scopeRegistry, + workScheduler); + + // Load the definitions.xml + loadSCADefinitions(registry); + + if (logger.isLoggable(Level.FINE)) { + long end = System.currentTimeMillis(); + logger.fine("The tuscany runtime is started in " + (end - start) + " ms."); + } + } + + public void stop() throws ActivationException { + long start = System.currentTimeMillis(); + + // Stop the runtime modules + stopModules(registry, modules); + + // Stop and destroy the work manager + workScheduler.destroy(); + + // Cleanup + modules = null; + registry = null; + assemblyFactory = null; + contributionService = null; + compositeActivator = null; + workScheduler = null; + scopeRegistry = null; + + if (logger.isLoggable(Level.FINE)) { + long end = System.currentTimeMillis(); + logger.fine("The tuscany runtime is stopped in " + (end - start) + " ms."); + } + } + + public void buildComposite(Composite composite) throws CompositeBuilderException { + //Get factory extension point + ModelFactoryExtensionPoint factories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + SCABindingFactory scaBindingFactory = factories.getFactory(SCABindingFactory.class); + IntentAttachPointTypeFactory intentAttachPointTypeFactory = factories.getFactory(IntentAttachPointTypeFactory.class); + InterfaceContractMapper mapper = new InterfaceContractMapperImpl(); + + //Create a composite builder + compositeBuilder = ReallySmallRuntimeBuilder.createCompositeBuilder(assemblyFactory, + scaBindingFactory, + intentAttachPointTypeFactory, + mapper); + compositeBuilder.build(composite); + + } + + public ContributionService getContributionService() { + return contributionService; + } + + public CompositeActivator getCompositeActivator() { + return compositeActivator; + } + + public CompositeBuilder getCompositeBuilder() { + return compositeBuilder; + } + + public AssemblyFactory getAssemblyFactory() { + return assemblyFactory; + } + + public DomainBuilder getDomainBuilder() { + if ( domainBuilder == null ) { + //Create a domain builder + //Get factory extension point + ModelFactoryExtensionPoint factories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + SCABindingFactory scaBindingFactory = factories.getFactory(SCABindingFactory.class); + IntentAttachPointTypeFactory intentAttachPointTypeFactory = factories.getFactory(IntentAttachPointTypeFactory.class); + InterfaceContractMapper mapper = new InterfaceContractMapperImpl(); + domainBuilder = ReallySmallRuntimeBuilder.createDomainBuilder(assemblyFactory, + scaBindingFactory, + intentAttachPointTypeFactory, + mapper); + } + return domainBuilder; + } + + private void loadSCADefinitions(ExtensionPointRegistry registry) throws ActivationException { + try { + URLArtifactProcessorExtensionPoint documentProcessors = registry.getExtensionPoint(URLArtifactProcessorExtensionPoint.class); + SCADefinitionsDocumentProcessor definitionsProcessor = (SCADefinitionsDocumentProcessor)documentProcessors.getProcessor(SCADefinitions.class); + SCADefinitionsProviderExtensionPoint scaDefnProviders = registry.getExtensionPoint(SCADefinitionsProviderExtensionPoint.class); + + SCADefinitions systemSCADefinitions = new SCADefinitionsImpl(); + SCADefinitions aSCADefn = null; + for ( SCADefinitionsProvider aProvider : scaDefnProviders.getSCADefinitionsProviders() ) { + aSCADefn = aProvider.getSCADefinition(); + SCADefinitionsUtil.aggregateSCADefinitions(aSCADefn, systemSCADefinitions); + } + + //we cannot expect that providers will add the intents and policysets into the resolver + //so we do this here explicitly + for ( Intent intent : systemSCADefinitions.getPolicyIntents() ) { + definitionsProcessor.getSCADefinitionsResolver().addModel(intent); + } + + for ( PolicySet policySet : systemSCADefinitions.getPolicySets() ) { + definitionsProcessor.getSCADefinitionsResolver().addModel(policySet); + } + + for ( IntentAttachPointType attachPoinType : systemSCADefinitions.getBindingTypes() ) { + definitionsProcessor.getSCADefinitionsResolver().addModel(attachPoinType); + } + + for ( IntentAttachPointType attachPoinType : systemSCADefinitions.getImplementationTypes() ) { + definitionsProcessor.getSCADefinitionsResolver().addModel(attachPoinType); + } + + //now that all system sca definitions have been read, lets resolve them rightaway + definitionsProcessor.resolve(systemSCADefinitions, + definitionsProcessor.getSCADefinitionsResolver()); + } catch ( Exception e ) { + throw new ActivationException(e); + } + + /*URLArtifactProcessorExtensionPoint documentProcessors = registry.getExtensionPoint(URLArtifactProcessorExtensionPoint.class); + SCADefinitionsDocumentProcessor definitionsProcessor = (SCADefinitionsDocumentProcessor)documentProcessors.getProcessor(SCADefinitions.class); + + try { + Map<ClassLoader, Set<URL>> scaDefinitionFiles = + ServiceDiscovery.getInstance().getServiceResources("definitions.xml"); + + SCADefinitions systemSCADefinitions = new SCADefinitionsImpl(); + for ( ClassLoader cl : scaDefinitionFiles.keySet() ) { + for ( URL scaDefnUrl : scaDefinitionFiles.get(cl) ) { + SCADefinitions defnSubset = definitionsProcessor.read(null, null, scaDefnUrl); + SCADefinitionsUtil.aggregateSCADefinitions(defnSubset, systemSCADefinitions); + } + } + + definitionsProcessor.resolve(systemSCADefinitions, definitionsProcessor.getSCADefinitionsResolver()); + scaDefnsSink.add(systemSCADefinitions); + } catch ( ContributionReadException e ) { + throw new ActivationException(e); + } catch ( ContributionResolveException e ) { + throw new ActivationException(e); + } catch ( IOException e ) { + throw new ActivationException(e); + }*/ + } + + @SuppressWarnings("unchecked") + private List<ModuleActivator> loadModules(ExtensionPointRegistry registry) throws ActivationException { + + // Load and instantiate the modules found on the classpath (or any registered classloaders) + modules = new ArrayList<ModuleActivator>(); + try { + Set<ServiceDeclaration> moduleActivators = + ServiceDiscovery.getInstance().getServiceDeclarations(ModuleActivator.class); + Set<String> moduleClasses = new HashSet<String>(); + for (ServiceDeclaration moduleDeclarator : moduleActivators) { + if (moduleClasses.contains(moduleDeclarator.getClassName())) { + continue; + } + moduleClasses.add(moduleDeclarator.getClassName()); + Class<?> moduleClass = moduleDeclarator.loadClass(); + ModuleActivator module = (ModuleActivator)moduleClass.newInstance(); + modules.add(module); + } + } catch (IOException e) { + throw new ActivationException(e); + } catch (ClassNotFoundException e) { + throw new ActivationException(e); + } catch (InstantiationException e) { + throw new ActivationException(e); + } catch (IllegalAccessException e) { + throw new ActivationException(e); + } + + return modules; + } + + private void startModules(ExtensionPointRegistry registry, List<ModuleActivator> modules) + throws ActivationException { + boolean debug = logger.isLoggable(Level.FINE); + // Start all the extension modules + for (ModuleActivator module : modules) { + long start = 0L; + if (debug) { + logger.fine(module.getClass().getName() + " is starting."); + start = System.currentTimeMillis(); + } + module.start(registry); + if (debug) { + long end = System.currentTimeMillis(); + logger.fine(module.getClass().getName() + " is started in " + (end - start) + " ms."); + } + } + } + + private void stopModules(ExtensionPointRegistry registry, List<ModuleActivator> modules) { + boolean debug = logger.isLoggable(Level.FINE); + for (ModuleActivator module : modules) { + long start = 0L; + if (debug) { + logger.fine(module.getClass().getName() + " is stopping."); + start = System.currentTimeMillis(); + } + module.stop(registry); + if (debug) { + long end = System.currentTimeMillis(); + logger.fine(module.getClass().getName() + " is stopped in " + (end - start) + " ms."); + } + } + } + + /** + * @return the proxyFactory + */ + public ProxyFactory getProxyFactory() { + return proxyFactory; + } + + /** + * @return the registry + */ + public ExtensionPointRegistry getExtensionPointRegistry() { + return registry; + } + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntimeBuilder.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntimeBuilder.java new file mode 100644 index 0000000000..ab6f4680e6 --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntimeBuilder.java @@ -0,0 +1,269 @@ +/* + * 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.host.embedded.impl; + +import java.io.IOException; +import java.util.List; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.DomainBuilder; +import org.apache.tuscany.sca.assembly.builder.impl.CompositeBuilderImpl; +import org.apache.tuscany.sca.assembly.builder.impl.DomainWireBuilderImpl; +import org.apache.tuscany.sca.assembly.xml.ComponentTypeDocumentProcessor; +import org.apache.tuscany.sca.assembly.xml.ComponentTypeProcessor; +import org.apache.tuscany.sca.assembly.xml.CompositeDocumentProcessor; +import org.apache.tuscany.sca.assembly.xml.CompositeProcessor; +import org.apache.tuscany.sca.assembly.xml.ConstrainingTypeDocumentProcessor; +import org.apache.tuscany.sca.assembly.xml.ConstrainingTypeProcessor; +import org.apache.tuscany.sca.context.ContextFactoryExtensionPoint; +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultValidatingXMLInputFactory; +import org.apache.tuscany.sca.contribution.processor.ExtensiblePackageProcessor; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.ExtensibleURLArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.PackageProcessor; +import org.apache.tuscany.sca.contribution.processor.PackageProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ValidationSchemaExtensionPoint; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint; +import org.apache.tuscany.sca.contribution.service.ContributionListenerExtensionPoint; +import org.apache.tuscany.sca.contribution.service.ContributionRepository; +import org.apache.tuscany.sca.contribution.service.ContributionService; +import org.apache.tuscany.sca.contribution.service.ExtensibleContributionListener; +import org.apache.tuscany.sca.contribution.service.TypeDescriber; +import org.apache.tuscany.sca.contribution.service.impl.ContributionRepositoryImpl; +import org.apache.tuscany.sca.contribution.service.impl.ContributionServiceImpl; +import org.apache.tuscany.sca.contribution.service.impl.PackageTypeDescriberImpl; +import org.apache.tuscany.sca.contribution.xml.ContributionMetadataProcessor; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.assembly.ActivationException; +import org.apache.tuscany.sca.core.assembly.CompositeActivator; +import org.apache.tuscany.sca.core.assembly.CompositeActivatorImpl; +import org.apache.tuscany.sca.core.conversation.ConversationManager; +import org.apache.tuscany.sca.core.conversation.ConversationManagerImpl; +import org.apache.tuscany.sca.core.invocation.DefaultProxyFactoryExtensionPoint; +import org.apache.tuscany.sca.core.invocation.ExtensibleWireProcessor; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.scope.CompositeScopeContainerFactory; +import org.apache.tuscany.sca.core.scope.ConversationalScopeContainerFactory; +import org.apache.tuscany.sca.core.scope.RequestScopeContainerFactory; +import org.apache.tuscany.sca.core.scope.ScopeContainerFactory; +import org.apache.tuscany.sca.core.scope.ScopeRegistry; +import org.apache.tuscany.sca.core.scope.ScopeRegistryImpl; +import org.apache.tuscany.sca.core.scope.StatelessScopeContainerFactory; +import org.apache.tuscany.sca.definitions.SCADefinitions; +import org.apache.tuscany.sca.definitions.xml.SCADefinitionsDocumentProcessor; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessor; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint; +import org.apache.tuscany.sca.work.WorkScheduler; + +public class ReallySmallRuntimeBuilder { + + public static ProxyFactory createProxyFactory(ExtensionPointRegistry registry, + InterfaceContractMapper mapper, + MessageFactory messageFactory) { + + ProxyFactory proxyFactory = new DefaultProxyFactoryExtensionPoint(messageFactory, mapper); + + // FIXME Pass these around differently as they are not extension points + registry.addExtensionPoint(proxyFactory); + registry.addExtensionPoint(mapper); + + return proxyFactory; + } + + public static CompositeActivator createCompositeActivator(ExtensionPointRegistry registry, + AssemblyFactory assemblyFactory, + MessageFactory messageFactory, + SCABindingFactory scaBindingFactory, + InterfaceContractMapper mapper, + ProxyFactory proxyFactory, + ScopeRegistry scopeRegistry, + WorkScheduler workScheduler) { + + // Create a wire post processor extension point + RuntimeWireProcessorExtensionPoint wireProcessors = + registry.getExtensionPoint(RuntimeWireProcessorExtensionPoint.class); + RuntimeWireProcessor wireProcessor = new ExtensibleWireProcessor(wireProcessors); + + // Retireve the processors extension point + StAXArtifactProcessorExtensionPoint processors = + registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + + // Create a provider factory extension point + ProviderFactoryExtensionPoint providerFactories = + registry.getExtensionPoint(ProviderFactoryExtensionPoint.class); + + JavaInterfaceFactory javaInterfaceFactory = + registry.getExtensionPoint(ModelFactoryExtensionPoint.class).getFactory(JavaInterfaceFactory.class); + RequestContextFactory requestContextFactory = + registry.getExtensionPoint(ContextFactoryExtensionPoint.class).getFactory(RequestContextFactory.class); + + ConversationManager conversationManager = new ConversationManagerImpl(); + registry.addExtensionPoint(conversationManager); + + // Create the composite activator + CompositeActivator compositeActivator = + new CompositeActivatorImpl(assemblyFactory, messageFactory, javaInterfaceFactory, scaBindingFactory, + mapper, scopeRegistry, workScheduler, wireProcessor, requestContextFactory, + proxyFactory, providerFactories, processors, conversationManager); + + return compositeActivator; + } + + public static CompositeBuilder createCompositeBuilder(AssemblyFactory assemblyFactory, + SCABindingFactory scaBindingFactory, + IntentAttachPointTypeFactory intentAttachPointTypeFactory, + InterfaceContractMapper interfaceContractMapper) { + return new CompositeBuilderImpl(assemblyFactory, scaBindingFactory, intentAttachPointTypeFactory, interfaceContractMapper, null); + } + + public static DomainBuilder createDomainBuilder(AssemblyFactory assemblyFactory, + SCABindingFactory scaBindingFactory, + IntentAttachPointTypeFactory intentAttachPointTypeFactory, + InterfaceContractMapper interfaceContractMapper) { + return new DomainWireBuilderImpl(assemblyFactory, scaBindingFactory, intentAttachPointTypeFactory, interfaceContractMapper, null); + } + + /** + * Create the contribution service used by this domain. + * + * @throws ActivationException + */ + public static ContributionService createContributionService(ClassLoader classLoader, + ExtensionPointRegistry registry, + ContributionFactory contributionFactory, + AssemblyFactory assemblyFactory, + PolicyFactory policyFactory, + InterfaceContractMapper mapper, + List scaDefinitionsSink) + throws ActivationException { + + // Create a new XML input factory + XMLInputFactory inputFactory = XMLInputFactory.newInstance(); + + // Create a validation XML schema extension point + ValidationSchemaExtensionPoint schemas = registry.getExtensionPoint(ValidationSchemaExtensionPoint.class); + schemas.addSchema(ReallySmallRuntimeBuilder.class.getClassLoader().getResource("tuscany-sca.xsd").toString()); + + // Create a validating XML input factory + XMLInputFactory validatingInputFactory = new DefaultValidatingXMLInputFactory(inputFactory, schemas); + + // Create STAX artifact processor extension point + StAXArtifactProcessorExtensionPoint staxProcessors = + registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + + // Create and register STAX processors for SCA assembly XML + ExtensibleStAXArtifactProcessor staxProcessor = + new ExtensibleStAXArtifactProcessor(staxProcessors, inputFactory, XMLOutputFactory.newInstance()); + staxProcessors.addArtifactProcessor(new CompositeProcessor(contributionFactory, assemblyFactory, policyFactory, staxProcessor)); + staxProcessors.addArtifactProcessor(new ComponentTypeProcessor(assemblyFactory, policyFactory, staxProcessor)); + staxProcessors + .addArtifactProcessor(new ConstrainingTypeProcessor(assemblyFactory, policyFactory, staxProcessor)); + + // Register STAX processors for Contribution Metadata + staxProcessors.addArtifactProcessor(new ContributionMetadataProcessor(assemblyFactory, contributionFactory, + staxProcessor)); + + // Create URL artifact processor extension point + URLArtifactProcessorExtensionPoint documentProcessors = + registry.getExtensionPoint(URLArtifactProcessorExtensionPoint.class); + + // Create and register document processors for SCA assembly XML + documentProcessors.addArtifactProcessor(new CompositeDocumentProcessor(staxProcessor, validatingInputFactory, scaDefinitionsSink)); + documentProcessors.addArtifactProcessor(new ComponentTypeDocumentProcessor(staxProcessor, validatingInputFactory)); + documentProcessors.addArtifactProcessor(new ConstrainingTypeDocumentProcessor(staxProcessor, validatingInputFactory)); + + // Create and register document processor for definitions.xml + //TODO No XMLSchema validation for definitions.xml for now + // as the XSD for it is not quite right yet + SCADefinitionsDocumentProcessor definitionsDocumentProcessor = + new SCADefinitionsDocumentProcessor(staxProcessors, staxProcessor, inputFactory, policyFactory); + documentProcessors.addArtifactProcessor(definitionsDocumentProcessor); + ModelResolver domainModelResolver = definitionsDocumentProcessor.getSCADefinitionsResolver(); + + // Create Model Resolver extension point + ModelResolverExtensionPoint modelResolvers = registry.getExtensionPoint(ModelResolverExtensionPoint.class); + + // Create contribution package processor extension point + TypeDescriber describer = new PackageTypeDescriberImpl(); + PackageProcessor packageProcessor = + new ExtensiblePackageProcessor(registry.getExtensionPoint(PackageProcessorExtensionPoint.class), describer); + + // Get the model factory extension point + ModelFactoryExtensionPoint modelFactories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + + // Create contribution listener + ExtensibleContributionListener contributionListener = + new ExtensibleContributionListener(registry.getExtensionPoint(ContributionListenerExtensionPoint.class)); + + // Create a contribution repository + ContributionRepository repository; + try { + repository = new ContributionRepositoryImpl("target", inputFactory); + } catch (IOException e) { + throw new ActivationException(e); + } + + ExtensibleURLArtifactProcessor documentProcessor = new ExtensibleURLArtifactProcessor(documentProcessors); + + // Create the contribution service + ContributionService contributionService = + new ContributionServiceImpl(repository, packageProcessor, documentProcessor, staxProcessor, + contributionListener, domainModelResolver, modelResolvers, modelFactories, + assemblyFactory, contributionFactory, inputFactory, scaDefinitionsSink); + return contributionService; + } + + public static ScopeRegistry createScopeRegistry(ExtensionPointRegistry registry) { + ScopeRegistry scopeRegistry = new ScopeRegistryImpl(); + ScopeContainerFactory[] factories = + new ScopeContainerFactory[] {new CompositeScopeContainerFactory(), new StatelessScopeContainerFactory(), + new RequestScopeContainerFactory(), + new ConversationalScopeContainerFactory(null), + // new HttpSessionScopeContainer(monitor) + }; + for (ScopeContainerFactory f : factories) { + scopeRegistry.register(f); + } + + //FIXME Pass the scope container differently as it's not an extension point + registry.addExtensionPoint(scopeRegistry); + + return scopeRegistry; + } + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentListener.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentListener.java new file mode 100644 index 0000000000..452f1a1ab1 --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentListener.java @@ -0,0 +1,29 @@ +/* + * 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.host.embedded.management; + +import java.util.EventListener; + +public interface ComponentListener extends EventListener { + + void componentStarted(String componentName); + void componentStopped(String componentName); + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentManager.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentManager.java new file mode 100644 index 0000000000..57b6a6d746 --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentManager.java @@ -0,0 +1,43 @@ +/* + * 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.host.embedded.management; + +import java.util.Set; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.core.assembly.ActivationException; + +public interface ComponentManager { + + Set<String> getComponentNames(); + + Component getComponent(String componentName); + + boolean isComponentStarted(String componentName); + + void startComponent(String componentName) throws ActivationException; + + void stopComponent(String componentName) throws ActivationException; + + void addComponentListener(ComponentListener listener); + + void removeComponentListener(ComponentListener listener); + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainBeanTestCase.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainBeanTestCase.java new file mode 100644 index 0000000000..9252b114a1 --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainBeanTestCase.java @@ -0,0 +1,57 @@ +/* + * 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.host.embedded; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.host.embedded.test.extension.TestService; +import org.osoa.sca.ServiceReference; + + + +/** + * Test creation of an SCADomainBean and invocation of a service. + * + * @version $Rev$ $Date$ + */ +public class SCADomainBeanTestCase extends TestCase { + + private SCADomainBean domain; + + @Override + protected void setUp() throws Exception { + domain = new SCADomainBean(); + domain.setDeployableComposites("test.composite"); + } + + public void testInvoke() throws Exception { + ServiceReference<TestService> serviceReference = domain.getServiceReference(TestService.class, "TestServiceComponent"); + assertNotNull(serviceReference); + TestService service = serviceReference.getService(); + String result = service.ping("Bob"); + assertEquals("Hello Bob", result); + } + + @Override + protected void tearDown() throws Exception { + domain.close(); + } + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainTestCase.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainTestCase.java new file mode 100644 index 0000000000..c52c16d8e1 --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainTestCase.java @@ -0,0 +1,56 @@ +/* + * 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.host.embedded; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.host.embedded.test.extension.TestService; +import org.osoa.sca.ServiceReference; + + + +/** + * Test SCADomain.newInstance and invocation of a service. + * + * @version $Rev$ $Date$ + */ +public class SCADomainTestCase extends TestCase { + + private SCADomain domain; + + @Override + protected void setUp() throws Exception { + domain = SCADomain.newInstance("test.composite"); + } + + public void testInvoke() throws Exception { + ServiceReference<TestService> serviceReference = domain.getServiceReference(TestService.class, "TestServiceComponent"); + assertNotNull(serviceReference); + TestService service = serviceReference.getService(); + String result = service.ping("Bob"); + assertEquals("Hello Bob", result); + } + + @Override + protected void tearDown() throws Exception { + domain.close(); + } + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomainTestCase.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomainTestCase.java new file mode 100644 index 0000000000..087a75426b --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomainTestCase.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.sca.host.embedded.impl; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.host.embedded.management.ComponentManager; +import org.apache.tuscany.sca.host.embedded.test.extension.TestService; + + +/** + * Test creation of DefaultSCADomain. + * + * @version $Rev$ $Date$ + */ +public class DefaultSCADomainTestCase extends TestCase { + private DefaultSCADomain domain; + + @Override + protected void setUp() throws Exception { + domain = new DefaultSCADomain(getClass().getClassLoader(), getClass().getClassLoader(), + "http://localhost", ".", "test.composite"); + } + + public void testStart() throws Exception { + TestService service = domain.getService(TestService.class, "TestServiceComponent"); + assertNotNull(service); + } + + public void testComponentManager() throws Exception { + ComponentManager componentManager = domain.getComponentManager(); + assertEquals(1, componentManager.getComponentNames().size()); + assertEquals("TestServiceComponent", componentManager.getComponentNames().iterator().next()); + assertNotNull(componentManager.getComponent("TestServiceComponent")); + + assertTrue(componentManager.isComponentStarted("TestServiceComponent")); + componentManager.stopComponent("TestServiceComponent"); + assertFalse(componentManager.isComponentStarted("TestServiceComponent")); + } + + @Override + protected void tearDown() throws Exception { + domain.close(); + } + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomainTestCase.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomainTestCase.java new file mode 100644 index 0000000000..2a59635a19 --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomainTestCase.java @@ -0,0 +1,189 @@ +/* + * 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.host.embedded.impl; + +import java.net.URL; + +import javax.xml.namespace.QName; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.service.ContributionService; +import org.apache.tuscany.sca.host.embedded.management.ComponentListener; +import org.apache.tuscany.sca.host.embedded.management.ComponentManager; +import org.apache.tuscany.sca.host.embedded.test.extension.TestService; + +/** + * Test creation of an EmbeddedSCADomain and invocation of a service. + * + * @version $Rev$ $Date$ + */ +public class EmbeddedSCADomainTestCase extends TestCase { + private EmbeddedSCADomain domain; + + @Override + protected void setUp() throws Exception { + + // Create a test embedded SCA domain + domain = new EmbeddedSCADomain(getClass().getClassLoader(), "http://localhost"); + } + + public void testDomain() throws Exception { + // Start the domain + domain.start(); + + // Determine my class loader and my test SCA contribution location + ClassLoader myClassLoader = getClass().getClassLoader(); + String url = myClassLoader.getResource("test.txt").toString(); + url = url.substring(0, url.length()-8); + + // Contribute the SCA contribution + TestModelResolver myResolver = new TestModelResolver(myClassLoader); + ContributionService contributionService = domain.getContributionService(); + Contribution contribution = contributionService.contribute("http://test/contribution", new URL(url), myResolver, false); + assertNotNull(contribution); + + // Decide which SCA composite I want to deploy + Composite myComposite = myResolver.getComposite(new QName("http://test", "test")); + + // Add the deployable composite to the domain + domain.getDomainComposite().getIncludes().add(myComposite); + + + domain.buildComposite(myComposite); + + // Start the composite + domain.getCompositeActivator().activate(myComposite); + domain.getCompositeActivator().start(myComposite); + + // At this point the domain contains my contribution, my composite and + // it's started, my application code can start using it + + // Get the TestServiceComponent service + TestService service = domain.getService(TestService.class, "TestServiceComponent"); + + // Invoke the service + String result = service.ping("Bob"); + assertEquals("Hello Bob", result); + + // Stop my composite + domain.getCompositeActivator().stop(myComposite); + domain.getCompositeActivator().deactivate(myComposite); + + // Remove my composite + domain.getDomainComposite().getIncludes().remove(myComposite); + + // Remove my contribution + contributionService.remove("http://test/contribution"); + + // Stop the domain + domain.stop(); + } + + public void testComponentManager() throws Exception { + // Start the domain + domain.start(); + + // Determine my class loader and my test SCA contribution location + ClassLoader myClassLoader = getClass().getClassLoader(); + String url = myClassLoader.getResource("test.txt").toString(); + url = url.substring(0, url.length()-8); + + // Contribute the SCA contribution + TestModelResolver myResolver = new TestModelResolver(myClassLoader); + ContributionService contributionService = domain.getContributionService(); + Contribution contribution = contributionService.contribute("http://test/contribution", new URL(url), myResolver, false); + assertNotNull(contribution); + + // Decide which SCA composite I want to deploy + Composite myComposite = myResolver.getComposite(new QName("http://test", "test")); + + // Add the deployable composite to the domain + domain.getDomainComposite().getIncludes().add(myComposite); + + domain.buildComposite(myComposite); + + // Start the composite + domain.getCompositeActivator().activate(myComposite); + domain.getCompositeActivator().start(myComposite); + + // At this point the domain contains my contribution, my composite and + // it's started, my application code can start using it + + ComponentManager componentManager = domain.getComponentManager(); + assertEquals(1, componentManager.getComponentNames().size()); + assertEquals("TestServiceComponent", componentManager.getComponentNames().iterator().next()); + + Component component = componentManager.getComponent("TestServiceComponent"); + assertNotNull(component); + assertEquals("TestServiceComponent", component.getName()); + + MyComponentListener cl = new MyComponentListener(); + componentManager.addComponentListener(cl); + + assertTrue(componentManager.isComponentStarted("TestServiceComponent")); + + assertFalse(cl.stopCalled); + componentManager.stopComponent("TestServiceComponent"); + assertTrue(cl.stopCalled); + assertFalse(componentManager.isComponentStarted("TestServiceComponent")); + + assertFalse(cl.startCalled); + componentManager.startComponent("TestServiceComponent"); + assertTrue(cl.startCalled); + assertTrue(componentManager.isComponentStarted("TestServiceComponent")); + + // Stop my composite + domain.getCompositeActivator().stop(myComposite); + domain.getCompositeActivator().deactivate(myComposite); + + // Remove my composite + domain.getDomainComposite().getIncludes().remove(myComposite); + + // Remove my contribution + contributionService.remove("http://test/contribution"); + + // Stop the domain + domain.stop(); + } + + class MyComponentListener implements ComponentListener { + boolean startCalled; + boolean stopCalled; + + public void componentStarted(String componentName) { + startCalled = true; + } + + public void componentStopped(String componentName) { + stopCalled = true; + } + + } + + @Override + protected void tearDown() throws Exception { + domain.close(); + } + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/impl/TestModelResolver.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/impl/TestModelResolver.java new file mode 100644 index 0000000000..9b099cd419 --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/impl/TestModelResolver.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.sca.host.embedded.impl; + +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.contribution.resolver.ClassReference; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + + +/** + * A test model resolver, based on a map. + * + * @version $Rev$ $Date$ + */ +public class TestModelResolver implements ModelResolver { + private static final long serialVersionUID = -7826976465762296634L; + + private Map<Object, Object> map = new HashMap<Object, Object>(); + private WeakReference<ClassLoader> classLoader; + + private Map<QName, Composite> composites = new HashMap<QName, Composite>(); + + public TestModelResolver(ClassLoader classLoader) { + this.classLoader = new WeakReference<ClassLoader>(classLoader); + } + + public <T> T resolveModel(Class<T> modelClass, T unresolved) { + Object resolved = map.get(unresolved); + if (resolved != null) { + + // Return the resolved object + return modelClass.cast(resolved); + + } else if (unresolved instanceof ClassReference) { + + // Load a class on demand + ClassReference classReference = (ClassReference)unresolved; + Class<?> clazz; + try { + clazz = Class.forName(classReference.getClassName(), true, classLoader.get()); + } catch (ClassNotFoundException e) { + + // Return the unresolved object + return unresolved; + } + + // Store a new ClassReference wrappering the loaded class + resolved = new ClassReference(clazz); + map.put(resolved, resolved); + + // Return the resolved ClassReference + return modelClass.cast(resolved); + + } else { + + // Return the unresolved object + return unresolved; + } + } + + public void addModel(Object resolved) { + map.put(resolved, resolved); + if (resolved instanceof Composite) { + Composite composite = (Composite)resolved; + composites.put(composite.getName(), composite); + } + } + + public Object removeModel(Object resolved) { + if (resolved instanceof Composite) { + Composite composite = (Composite)resolved; + composites.remove(composite.getName()); + } + return map.remove(resolved); + } + + public Composite getComposite(QName qname) { + return composites.get(qname); + } + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/DefaultTestImplementationFactory.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/DefaultTestImplementationFactory.java new file mode 100644 index 0000000000..86e0cb6a8a --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/DefaultTestImplementationFactory.java @@ -0,0 +1,47 @@ +/* + * 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.host.embedded.test.extension; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.host.embedded.test.extension.impl.TestImplementationImpl; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; + + +/** + * Default factory for the test implementation model. + * + * @version $Rev$ $Date$ + */ +public class DefaultTestImplementationFactory implements TestImplementationFactory { + + private AssemblyFactory assemblyFactory; + private JavaInterfaceFactory javaFactory; + + public DefaultTestImplementationFactory(AssemblyFactory assemblyFactory, + JavaInterfaceFactory javaFactory) { + this.assemblyFactory = assemblyFactory; + this.javaFactory = javaFactory; + } + + public TestImplementation createTestImplementation() { + return new TestImplementationImpl(assemblyFactory, javaFactory); + } + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementation.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementation.java new file mode 100644 index 0000000000..46fcdaf5e1 --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementation.java @@ -0,0 +1,45 @@ +/* + * 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.host.embedded.test.extension; + +import org.apache.tuscany.sca.assembly.Implementation; + +/** + * The model representing a test implementation in an SCA assembly model. + * + * @version $$Rev$$ $$Date: 2007-04-23 19:18:54 -0700 (Mon, 23 Apr + * 2007) $$ + */ +public interface TestImplementation extends Implementation { + + /** + * Returns the greeting string that can be configured on test implementations. + * + * @return the greeting string that can be configured on test implementations + */ + public String getGreeting(); + + /** + * Sets the greeting string that can be configured on test implementations. + * + * @param greeting the greeting string that can be configured on test implementations + */ + public void setGreeting(String greeting); + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementationFactory.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementationFactory.java new file mode 100644 index 0000000000..9200d850bb --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementationFactory.java @@ -0,0 +1,37 @@ +/* + * 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.host.embedded.test.extension; + + +/** + * A factory for the test implementation model. + * + * @version $Rev$ $Date$ + */ +public interface TestImplementationFactory { + + /** + * Creates a new test implementation. + * + * @return + */ + TestImplementation createTestImplementation(); + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestService.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestService.java new file mode 100644 index 0000000000..4adec91151 --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestService.java @@ -0,0 +1,30 @@ +/* + * 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.host.embedded.test.extension; + +/** + * Service interface for test component implementations. + * + * @version $Rev$ $Date$ + */ +public interface TestService { + + String ping(String name); + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationImpl.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationImpl.java new file mode 100644 index 0000000000..78f9654f1b --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationImpl.java @@ -0,0 +1,118 @@ +/* + * 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.host.embedded.test.extension.impl; + +import java.util.Collections; +import java.util.List; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.ConstrainingType; +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.host.embedded.test.extension.TestService; +import org.apache.tuscany.sca.host.embedded.test.extension.TestImplementation; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; + + +/** + * The model representing a test implementation in an SCA assembly model. + * + * @version $$Rev$$ $$Date: 2007-04-23 19:18:54 -0700 (Mon, 23 Apr + * 2007) $$ + */ +public class TestImplementationImpl implements TestImplementation { + + private Service testService; + private String greeting; + + /** + * Constructs a new test implementation. + */ + public TestImplementationImpl(AssemblyFactory assemblyFactory, + JavaInterfaceFactory javaFactory) { + + // Test implementations always provide a single service exposing + // the TestService interface, and have no references and properties + testService = assemblyFactory.createService(); + testService.setName("Test"); + JavaInterface javaInterface; + try { + javaInterface = javaFactory.createJavaInterface(TestService.class); + } catch (InvalidInterfaceException e) { + throw new IllegalArgumentException(e); + } + JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract(); + interfaceContract.setInterface(javaInterface); + testService.setInterfaceContract(interfaceContract); + } + + public String getGreeting() { + return greeting; + } + + public void setGreeting(String greeting) { + this.greeting = greeting; + } + + public ConstrainingType getConstrainingType() { + // The test implementation does not support constrainingTypes + return null; + } + + public List<Property> getProperties() { + // The test implementation does not support properties + return Collections.emptyList(); + } + + public List<Service> getServices() { + // The test implementation provides a single fixed Test service + return Collections.singletonList(testService); + } + + public List<Reference> getReferences() { + // The test implementation does not support properties + return Collections.emptyList(); + } + + public String getURI() { + // The test implementation does not have a URI + return null; + } + + public void setConstrainingType(ConstrainingType constrainingType) { + // The test implementation does not support constrainingTypes + } + + public void setURI(String uri) { + // The test implementation does not have a URI + } + + public boolean isUnresolved() { + // The test implementation is always resolved + return false; + } + + public void setUnresolved(boolean unresolved) { + // The test implementation is always resolved + } +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationProcessor.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationProcessor.java new file mode 100644 index 0000000000..9388bc48cf --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationProcessor.java @@ -0,0 +1,96 @@ +/* + * 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.host.embedded.test.extension.impl; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; + +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.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.host.embedded.test.extension.TestImplementation; +import org.apache.tuscany.sca.host.embedded.test.extension.TestImplementationFactory; + + + +/** + * Implements a STAX artifact processor for test implementations. + * + * @version $Rev$ $Date$ + */ +public class TestImplementationProcessor implements StAXArtifactProcessor<TestImplementation> { + private static final QName IMPLEMENTATION_TEST = new QName("http://test/extension", "implementation.test"); + + private TestImplementationFactory testFactory; + + public TestImplementationProcessor(TestImplementationFactory testFactory) { + this.testFactory = testFactory; + } + + public QName getArtifactType() { + // Returns the qname of the XML element processed by this processor + return IMPLEMENTATION_TEST; + } + + public Class<TestImplementation> getModelType() { + // Returns the type of model processed by this processor + return TestImplementation.class; + } + + public TestImplementation read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException { + + // Read an <implementation.test> element + + // Read the message attribute. + String message = reader.getAttributeValue(null, "greeting"); + + // Create and initialize the test implementation model + TestImplementation implementation = testFactory.createTestImplementation(); + implementation.setGreeting(message); + + // Skip to end element + while (reader.hasNext()) { + if (reader.next() == END_ELEMENT && IMPLEMENTATION_TEST.equals(reader.getName())) { + break; + } + } + + return implementation; + } + + public void resolve(TestImplementation impl, ModelResolver resolver) throws ContributionResolveException { + } + + public void write(TestImplementation implementation, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException { + + writer.writeStartElement(IMPLEMENTATION_TEST.getNamespaceURI(), IMPLEMENTATION_TEST.getLocalPart()); + + if (implementation.getGreeting() != null) { + writer.writeAttribute("greeting", implementation.getGreeting()); + } + + writer.writeEndElement(); + } +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/module/TestModuleActivator.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/module/TestModuleActivator.java new file mode 100644 index 0000000000..35554f907a --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/module/TestModuleActivator.java @@ -0,0 +1,66 @@ +/* + * 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.host.embedded.test.extension.module; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +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.host.embedded.test.extension.TestImplementationFactory; +import org.apache.tuscany.sca.host.embedded.test.extension.DefaultTestImplementationFactory; +import org.apache.tuscany.sca.host.embedded.test.extension.impl.TestImplementationProcessor; +import org.apache.tuscany.sca.host.embedded.test.extension.provider.TestImplementationProviderFactory; +import org.apache.tuscany.sca.interfacedef.java.DefaultJavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint; + + + +/** + * Implements a module activator for the test implementation extension module. + * + * @version $Rev$ $Date$ + */ +public class TestModuleActivator implements ModuleActivator { + + public void start(ExtensionPointRegistry registry) { + + // Create the test implementation factory + ModelFactoryExtensionPoint factories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + AssemblyFactory assemblyFactory = factories.getFactory(AssemblyFactory.class); + JavaInterfaceFactory javaFactory = new DefaultJavaInterfaceFactory(); + TestImplementationFactory testFactory = new DefaultTestImplementationFactory(assemblyFactory, javaFactory); + factories.addFactory(testFactory); + + // Add the test implementation extension to the StAXArtifactProcessor + // extension point + StAXArtifactProcessorExtensionPoint processors = registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + TestImplementationProcessor implementationArtifactProcessor = new TestImplementationProcessor(testFactory); + processors.addArtifactProcessor(implementationArtifactProcessor); + + // Add the test provider factory to the ProviderFactory extension point + ProviderFactoryExtensionPoint providerFactories = registry.getExtensionPoint(ProviderFactoryExtensionPoint.class); + providerFactories.addProviderFactory(new TestImplementationProviderFactory()); + } + + public void stop(ExtensionPointRegistry registry) { + } +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProvider.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProvider.java new file mode 100644 index 0000000000..20957a352e --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProvider.java @@ -0,0 +1,65 @@ +/* + * 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.host.embedded.test.extension.provider; + +import org.apache.tuscany.sca.host.embedded.test.extension.TestImplementation; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + + +/** + * Implementation provider for test implementations. + * + * @version $$Rev$$ $$Date: 2007-04-23 19:18:54 -0700 (Mon, 23 Apr + * 2007) $$ + */ +public class TestImplementationProvider implements ImplementationProvider { + + private RuntimeComponent component; + private TestImplementation implementation; + + /** + * Constructs a new test implementation provider. + */ + public TestImplementationProvider(RuntimeComponent component, TestImplementation implementation) { + this.component = component; + this.implementation = implementation; + } + + public Invoker createInvoker(RuntimeComponentService service, Operation operation) { + TestInvoker invoker = new TestInvoker(operation, implementation.getGreeting()); + return invoker; + } + + public boolean supportsOneWayInvocation() { + return false; + } + + public void start() { + System.out.println("Starting " + component.getName()); + } + + public void stop() { + System.out.println("Stopping " + component.getName()); + } + +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProviderFactory.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProviderFactory.java new file mode 100644 index 0000000000..352cf192df --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProviderFactory.java @@ -0,0 +1,48 @@ +/* + * 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.host.embedded.test.extension.provider; + +import org.apache.tuscany.sca.host.embedded.test.extension.TestImplementation; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.ImplementationProviderFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + + +/** + * The model representing a test implementation in an SCA assembly model. + * + * @version $$Rev$$ $$Date: 2007-04-23 19:18:54 -0700 (Mon, 23 Apr + * 2007) $$ + */ +public class TestImplementationProviderFactory implements ImplementationProviderFactory<TestImplementation> { + + /** + * Constructs a new test implementation provider factory. + */ + public TestImplementationProviderFactory() { + } + + public ImplementationProvider createImplementationProvider(RuntimeComponent component, TestImplementation implementation) { + return new TestImplementationProvider(component, implementation); + } + + public Class<TestImplementation> getModelType() { + return TestImplementation.class; + } +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestInvoker.java b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestInvoker.java new file mode 100644 index 0000000000..d49179dec0 --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestInvoker.java @@ -0,0 +1,52 @@ +/* + * 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.host.embedded.test.extension.provider; + +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; + + +/** + * Implements an invoker for test component implementations. + * + * The target invoker is responsible for handling operation invocations. + * + * @version $Rev$ $Date$ + */ +public class TestInvoker implements Invoker { + private Operation operation; + private String greeting; + + public TestInvoker(Operation operation, String greeting) { + this.operation = operation; + this.greeting = greeting; + } + + public Message invoke(Message msg) { + Object[] args = msg.getBody(); + if (operation.getName().equals("ping")) { + msg.setBody(greeting + " " + args[0]); + } else { + msg.setFaultBody(new Exception("Operation " + operation.getName() + " is not supported")); + } + return msg; + } +} diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/resources/META-INF/services/org.apache.tuscany.sca.core.ModuleActivator b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/resources/META-INF/services/org.apache.tuscany.sca.core.ModuleActivator new file mode 100644 index 0000000000..7e2e11e4cc --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/resources/META-INF/services/org.apache.tuscany.sca.core.ModuleActivator @@ -0,0 +1,18 @@ +# 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.
+# Implementation class for the ExtensionActivator
+org.apache.tuscany.sca.host.embedded.test.extension.module.TestModuleActivator
diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/resources/test.composite b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/resources/test.composite new file mode 100644 index 0000000000..bd7c5fab79 --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/resources/test.composite @@ -0,0 +1,30 @@ +<?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. +--> +<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" + targetNamespace="http://test" + xmlns:se="http://test" + xmlns:e="http://test/extension" + name="test"> + + <component name="TestServiceComponent"> + <e:implementation.test greeting="Hello" /> + </component> + +</composite> diff --git a/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/resources/test.txt b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/resources/test.txt new file mode 100644 index 0000000000..287f9b1f65 --- /dev/null +++ b/sca-java-1.x/tags/1.2/modules/host-embedded/src/test/resources/test.txt @@ -0,0 +1,16 @@ +# 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.
\ No newline at end of file |