From 5559ef5edbf8d3616f7a4b497b2a459b0ee4082b Mon Sep 17 00:00:00 2001 From: lresende Date: Wed, 11 Nov 2009 23:07:07 +0000 Subject: Moving 1.x branches git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@835122 13f79535-47bb-0310-9956-ffa450edef68 --- .../tuscany/sca/host/embedded/SCADomain.java | 272 ++++++++++ .../tuscany/sca/host/embedded/SCADomainBean.java | 121 +++++ .../sca/host/embedded/SCATestCaseRunner.java | 213 ++++++++ .../host/embedded/impl/ComponentManagerImpl.java | 115 +++++ .../sca/host/embedded/impl/DefaultSCADomain.java | 563 +++++++++++++++++++++ .../sca/host/embedded/impl/EmbeddedSCADomain.java | 230 +++++++++ .../host/embedded/impl/HotUpdatableSCADomain.java | 391 ++++++++++++++ .../sca/host/embedded/impl/ReallySmallRuntime.java | 296 +++++++++++ .../embedded/impl/ReallySmallRuntimeBuilder.java | 270 ++++++++++ .../embedded/management/ComponentListener.java | 29 ++ .../host/embedded/management/ComponentManager.java | 43 ++ 11 files changed, 2543 insertions(+) create mode 100644 sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomain.java create mode 100644 sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomainBean.java create mode 100644 sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCATestCaseRunner.java create mode 100644 sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ComponentManagerImpl.java create mode 100644 sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomain.java create mode 100644 sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomain.java create mode 100644 sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/HotUpdatableSCADomain.java create mode 100644 sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntime.java create mode 100644 sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntimeBuilder.java create mode 100644 sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentListener.java create mode 100644 sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentManager.java (limited to 'sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host') diff --git a/sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomain.java b/sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomain.java new file mode 100644 index 0000000000..6954110bc5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.0/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 + private 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 the Java type of the business interface for the reference + * @param 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 > 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 the Java type of the business interface for the service + * @return an object that implements the business interface + */ + public abstract B getService(Class 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 the Java type of the business interface for the service + * @return a ServiceReference for the designated service + */ + public abstract ServiceReference getServiceReference(Class 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() { + 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/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomainBean.java b/sca-java-1.x/branches/sca-java-1.0/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/branches/sca-java-1.0/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 > 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 getService(Class businessInterface, String serviceName) { + if (instance == null) { + instance = SCADomain.createNewInstance(uri, location, composites); + } + return instance.getService(businessInterface, serviceName); + } + + @Override + public ServiceReference getServiceReference(Class 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/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCATestCaseRunner.java b/sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCATestCaseRunner.java new file mode 100644 index 0000000000..3aa334a3d5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCATestCaseRunner.java @@ -0,0 +1,213 @@ +/* + * 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 = testClass.getClassLoader(); + if (classLoader instanceof URLClassLoader) { + URL[] urls = ((URLClassLoader)classLoader).getURLs(); + classLoader = new URLClassLoader(urls, classLoader.getParent()); + } else { + classLoader = new URLClassLoader(new URL[0], classLoader); + } + + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(classLoader); + + testCaseClass = Class.forName(testClass.getName(), true, classLoader); + testCase = testCaseClass.newInstance(); + + junit3TestCaseClass = Class.forName("junit.framework.TestCase", true, classLoader); + + testSuiteClass = Class.forName("junit.framework.TestSuite", true, classLoader); + Constructor testSuiteConstructor = testSuiteClass.getConstructor(Class.class); + testSuite = testSuiteConstructor.newInstance(testCaseClass); + + testResultClass = Class.forName("junit.framework.TestResult", true, classLoader); + + try { + beforeAnnotation = Class.forName("org.junit.Before", true, classLoader); + afterAnnotation = Class.forName("org.junit.After", true, classLoader); + beforeClassAnnotation = Class.forName("org.junit.BeforeClass", true, classLoader); + afterClassAnnotation = Class.forName("org.junit.AfterClass", true, classLoader); + junit4AdapterClass = Class.forName("junit.framework.JUnit4TestAdapter", true, classLoader); + } 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/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ComponentManagerImpl.java b/sca-java-1.x/branches/sca-java-1.0/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/branches/sca-java-1.0/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 listeners = new CopyOnWriteArrayList(); + 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 getComponentNames() { + Set names = new HashSet(); + 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/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomain.java b/sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomain.java new file mode 100644 index 0000000000..facc7b8cf6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomain.java @@ -0,0 +1,563 @@ +/* + * 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.MalformedURLException; +import java.net.URI; +import java.net.URL; +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.OptimizableBinding; +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.Contribution; +import org.apache.tuscany.sca.contribution.DeployedArtifact; +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 Contribution contribution; + private Map components = new HashMap(); + private ReallySmallRuntime runtime; + private ComponentManager componentManager; + + /** + * 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; + + // Create and start the runtime + 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 contributionURI = FileHelper.getName(contributionURL.getPath()); + if (contributionURI == null || contributionURI.length() == 0) { + contributionURI = contributionURL.toString(); + } + contribution = contributionService.contribute(contributionURI, contributionURL, false); + } catch (ContributionException e) { + throw new ServiceRuntimeException(e); + } catch (IOException 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 compositeArtifacts = new HashMap(); + for (DeployedArtifact 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 (Composite composite : contribution.getDeployables()) { + domainComposite.getIncludes().add(composite); + } + + } + + // Build the SCA composites + CompositeBuilder compositeBuilder = runtime.getCompositeBuilder(); + + for (Composite composite : domainComposite.getIncludes()) { + try { + compositeBuilder.build(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(); +// } +// } + + } + + @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(); + 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 + */ + private 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(); + } + } catch (MalformedURLException mfe) { + throw new IllegalArgumentException(mfe); + } + + return contributionURL; + } + + @Override + public > R cast(B target) throws IllegalArgumentException { + return (R)runtime.getProxyFactory().cast(target); + } + + @Override + public B getService(Class businessInterface, String serviceName) { + ServiceReference serviceReference = getServiceReference(businessInterface, serviceName); + if (serviceReference == null) { + throw new ServiceRuntimeException("Service not found: " + serviceName); + } + return serviceReference.getService(); + } + + private ServiceReference createServiceReference(Class 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(businessInterface, component, reference, binding, runtime + .getProxyFactory(), runtime.getCompositeActivator()); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + @Override + public ServiceReference getServiceReference(Class 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 getComponentNames() { + Set componentNames = new HashSet(); + for (DeployedArtifact 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 (DeployedArtifact 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 listeners = new CopyOnWriteArrayList(); + + 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 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/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomain.java b/sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomain.java new file mode 100644 index 0000000000..ffdc3b1a05 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomain.java @@ -0,0 +1,230 @@ +/* + * 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 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.OptimizableBinding; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +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.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 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 > R cast(B target) throws IllegalArgumentException { + return (R)runtime.getProxyFactory().cast(target); + } + + @Override + public B getService(Class businessInterface, String serviceName) { + ServiceReference serviceReference = getServiceReference(businessInterface, serviceName); + if (serviceReference == null) { + throw new ServiceRuntimeException("Service not found: " + serviceName); + } + return serviceReference.getService(); + } + + private ServiceReference createServiceReference(Class 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(businessInterface, component, reference, binding, runtime + .getProxyFactory(), runtime.getCompositeActivator()); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + @Override + public ServiceReference getServiceReference(Class 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/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/HotUpdatableSCADomain.java b/sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/HotUpdatableSCADomain.java new file mode 100644 index 0000000000..2942e61db2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/HotUpdatableSCADomain.java @@ -0,0 +1,391 @@ +/* + * 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.resolver.impl.ModelResolverImpl; +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 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 contributionJars = new ArrayList(); + 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 s or s which are outside of + * a 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) { + ModelResolverImpl modelResolver = new ModelResolverImpl(cl); + ContributionService contributionService = scaDomain.getContributionService(); + for (URL jar : contributionJars) { + InputStream is = null; + try { + is = jar.openStream(); + contributionService.contribute(jar.toString(), jar, is , modelResolver); + } catch (Exception e) { + System.err.println("exception adding contribution: " + jar); + e.printStackTrace(); + } + if (is != null) { + try { + is.close(); + } catch (IOException e) { + // ignore + } + } + } + + try { + + for (Object m : modelResolver.getModels()) { + if (m instanceof Composite) { + Composite composite = (Composite)m; + scaDomain.getDomainComposite().getIncludes().add(composite); + scaDomain.getCompositeBuilder().build(composite); + scaDomain.getCompositeActivator().activate(composite); + } + } + + for (Object m : modelResolver.getModels()) { + if (m instanceof Composite) { + Composite composite = (Composite)m; + 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 getLastModified(URL[] contrabutions) { + try { + + HashMap contributionLastUpdates = new HashMap(); + 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 getUpdatedContributions(URL[] currentContrabutions) throws URISyntaxException { + List urls = new ArrayList(); + 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 currentUrls = Arrays.asList(currentContrabutions); + List urls = new ArrayList(); + 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 urls = new ArrayList(); + for (URL url : currentContrabutions) { + if (!existingContributions.containsKey(url)) { + urls.add(url); + logger.info("added contribution: " + new File(url.toURI()).getName()); + } + } + return urls; + } + + @Override + public > R cast(B target) throws IllegalArgumentException { + throw new UnsupportedOperationException("not implemented"); + } + + @Override + public B getService(Class businessInterface, String serviceName) { + return scaDomain.getService(businessInterface, serviceName); + } + + @Override + public ServiceReference getServiceReference(Class 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/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntime.java b/sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntime.java new file mode 100644 index 0000000000..0c6f1fc4de --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntime.java @@ -0,0 +1,296 @@ +/* + * 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.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +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.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.contribution.util.ServiceConfigurationUtil; +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.SCADefinitionsDocumentProcessor; +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.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 modules; + private ExtensionPointRegistry registry; + + private ClassLoader classLoader; + private AssemblyFactory assemblyFactory; + private ContributionService contributionService; + private CompositeActivator compositeActivator; + private CompositeBuilder compositeBuilder; + private WorkScheduler workScheduler; + private ScopeRegistry scopeRegistry; + private ProxyFactory proxyFactory; + + 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); + 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); + + // Create the ScopeRegistry + scopeRegistry = ReallySmallRuntimeBuilder.createScopeRegistry(registry); + + // Create a composite activator + compositeActivator = ReallySmallRuntimeBuilder.createCompositeActivator(registry, + assemblyFactory, + messageFactory, + scaBindingFactory, + mapper, + proxyFactory, + scopeRegistry, + workScheduler); + + + // Load the runtime modules + modules = loadModules(registry, classLoader); + + // Start the runtime modules + startModules(registry, modules); + + // Load the definitions.xml + URLArtifactProcessorExtensionPoint documentProcessors = registry.getExtensionPoint(URLArtifactProcessorExtensionPoint.class); + SCADefinitionsDocumentProcessor definitionsProcessor = (SCADefinitionsDocumentProcessor)documentProcessors.getProcessor(SCADefinitions.class); + SCADefinitions definitions = loadDomainDefinitions(definitionsProcessor); + List domainPolicySets; + if ( definitions != null ) { + domainPolicySets = definitions.getPolicySets(); + } else { + domainPolicySets = null; + } + + //Create a composite builder + compositeBuilder = ReallySmallRuntimeBuilder.createCompositeBuilder(assemblyFactory, + scaBindingFactory, + mapper, + domainPolicySets); + if (logger.isLoggable(Level.FINE)) { + long end = System.currentTimeMillis(); + logger.fine("The tuscany runtime is started in " + (end - start) + " ms."); + } + } + + private SCADefinitions loadDomainDefinitions(SCADefinitionsDocumentProcessor definitionsProcessor) throws ActivationException { + URL url = this.classLoader.getResource("definitions.xml"); + SCADefinitions definitions = null; + + if ( url != null ) { + try { + definitions = definitionsProcessor.read(null, null, url); + definitionsProcessor.resolve(definitions, definitionsProcessor.getDomainModelResolver()); + } catch ( ContributionReadException e ) { + throw new ActivationException(e); + } catch ( ContributionResolveException e ) { + throw new ActivationException(e); + } + } + return definitions; + } + + 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 ContributionService getContributionService() { + return contributionService; + } + + public CompositeActivator getCompositeActivator() { + return compositeActivator; + } + + public CompositeBuilder getCompositeBuilder() { + return compositeBuilder; + } + + public AssemblyFactory getAssemblyFactory() { + return assemblyFactory; + } + + @SuppressWarnings("unchecked") + private List loadModules(ExtensionPointRegistry registry, ClassLoader classLoader) throws ActivationException { + + // Load and instantiate the modules found on the classpath + modules = new ArrayList(); + try { + List classNames = ServiceConfigurationUtil.getServiceClassNames(classLoader, ModuleActivator.class.getName()); + for (String className : classNames) { + Class moduleClass = Class.forName(className, true, classLoader); + 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 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 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/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntimeBuilder.java b/sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntimeBuilder.java new file mode 100644 index 0000000000..c7ccb929ed --- /dev/null +++ b/sca-java-1.x/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntimeBuilder.java @@ -0,0 +1,270 @@ +/* + * 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.XMLConstants; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +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.impl.CompositeBuilderImpl; +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.binding.sca.xml.SCABindingProcessor; +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.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.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.ContributionMetadataProcessor; +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.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.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.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); + + // Add the SCABindingProcessor extension + PolicyFactory policyFactory = registry.getExtensionPoint(PolicyFactory.class); + SCABindingProcessor scaBindingProcessor = + new SCABindingProcessor(assemblyFactory, policyFactory, scaBindingFactory); + StAXArtifactProcessorExtensionPoint processors = + registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + processors.addArtifactProcessor(scaBindingProcessor); + + // 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, + InterfaceContractMapper interfaceContractMapper, + List domainPolicySets) { + return new CompositeBuilderImpl(assemblyFactory, scaBindingFactory, interfaceContractMapper, domainPolicySets, 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) + throws ActivationException { + + XMLInputFactory xmlFactory = registry.getExtensionPoint(XMLInputFactory.class); + + // 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, xmlFactory, XMLOutputFactory.newInstance()); + staxProcessors.addArtifactProcessor(new CompositeProcessor(contributionFactory, assemblyFactory, policyFactory, + mapper, 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); + + // Load the Assembly XSD, used for validation + Schema schema = null; + try { + SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + schema = schemaFactory.newSchema(ReallySmallRuntimeBuilder.class.getClassLoader().getResource("tuscany-sca.xsd")); + } catch (Error e) { + //FIXME Log this, some old JDKs don't support XMLSchema validation + //e.printStackTrace(); + } catch (Exception e) { + //FIXME Log this, some old JDKs don't support XMLSchema validation + //e.printStackTrace(); + } + + // Create and register document processors for SCA assembly XML + XMLInputFactory inputFactory = XMLInputFactory.newInstance(); + documentProcessors.addArtifactProcessor(new CompositeDocumentProcessor(staxProcessor, inputFactory, schema)); + documentProcessors.addArtifactProcessor(new ComponentTypeDocumentProcessor(staxProcessor, inputFactory, schema)); + documentProcessors.addArtifactProcessor(new ConstrainingTypeDocumentProcessor(staxProcessor, inputFactory, schema)); + + // 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, xmlFactory, policyFactory, null); + documentProcessors.addArtifactProcessor(definitionsDocumentProcessor); + ModelResolver domainModelResolver = definitionsDocumentProcessor.getDomainModelResolver(); + + // 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", xmlFactory); + } 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, xmlFactory); + 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/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentListener.java b/sca-java-1.x/branches/sca-java-1.0/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/branches/sca-java-1.0/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/branches/sca-java-1.0/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentManager.java b/sca-java-1.x/branches/sca-java-1.0/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/branches/sca-java-1.0/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 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); + +} -- cgit v1.2.3