diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2008-09-12 21:54:50 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2008-09-12 21:54:50 +0000 |
commit | d232b6a46e4225ff35a0123a5f5597da7592fc38 (patch) | |
tree | 0c607d86a472ccbdd5587eb3ae53f535b6aa36f2 /branches/sca-equinox/modules/host-embedded | |
parent | 2e48ecc0ea43d7b859c578080c72e4c739717487 (diff) |
Creating a branch for the equinox work.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@694816 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'branches/sca-equinox/modules/host-embedded')
32 files changed, 3942 insertions, 0 deletions
diff --git a/branches/sca-equinox/modules/host-embedded/LICENSE b/branches/sca-equinox/modules/host-embedded/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/LICENSE @@ -0,0 +1,205 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + diff --git a/branches/sca-equinox/modules/host-embedded/NOTICE b/branches/sca-equinox/modules/host-embedded/NOTICE new file mode 100644 index 0000000000..fdfa0e9faa --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2008 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/branches/sca-equinox/modules/host-embedded/pom.xml b/branches/sca-equinox/modules/host-embedded/pom.xml new file mode 100644 index 0000000000..92fd8cc016 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/pom.xml @@ -0,0 +1,132 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<project> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>1.4-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-host-embedded</artifactId> + <name>Apache Tuscany SCA Embedded Host</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-node-impl</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-extensibility</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-definitions</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-definitions-xml</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-assembly-xml</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-binding-sca</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-binding-sca-xml</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-contribution-impl</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-policy-xml</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core-databinding</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-assembly-xsd</artifactId> + <version>1.4-SNAPSHOT</version> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-endpoint</artifactId> + <version>1.4-SNAPSHOT</version> + <scope>runtime</scope> + </dependency> + + + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + + <configuration> + <instructions> + <Bundle-Version>${tuscany.version}</Bundle-Version> + <Bundle-SymbolicName>org.apache.tuscany.sca.host.embedded</Bundle-SymbolicName> + <Bundle-Description>${pom.name}</Bundle-Description> + <Export-Package>org.apache.tuscany.sca.host.embedded*</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> + +</project> diff --git a/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomain.java b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomain.java new file mode 100644 index 0000000000..a7f148cdda --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomain.java @@ -0,0 +1,226 @@ +/* + * 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.reflect.Constructor; + +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; +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 { + + static final String LOCAL_DOMAIN_URI = "http://localhost"; + + /** + * Static variable to hold the most recent instance of SCADomain + */ + // TODO: Temporary support for SCADomain.connect() API + protected static SCADomain theDomain; + + + /** + * Returns a new instance of a local SCA domain. + * + * @return + */ + public static SCADomain newInstance() { + return createNewInstance(LOCAL_DOMAIN_URI, null); + } + + /** + * Returns a new instance of a local SCA domain. The specified deployable + * composite will be included in the SCA domain. + * + * @param composite the deployable composite to include in the SCA domain. + * @return + */ + public static SCADomain newInstance(String composite) { + return createNewInstance(LOCAL_DOMAIN_URI, "/", composite); + } + + /** + * Returns a new instance of a local SCA domain. The specified deployable + * composites will be included in the SCA domain. + * + * @param domainURI the URI of the SCA domain + * @param contributionLocation the location of an SCA contribution + * @param composites the deployable composites to include in the SCA domain. + * @return + */ + public static SCADomain newInstance(String domainURI, String contributionLocation, String... composites) { + return createNewInstance(domainURI, contributionLocation, composites); + } + + /** + * Removes the specified local SCA Domain instance + * + * @param domainInstance the instance to be removed + */ + // FIXME: Adding this as temporary support for the "connect" API + public static void removeInstance(SCADomain domainInstance) { + theDomain = null; + } + + /** + * Returns an SCADomain representing a remote SCA domain. + * + * @param domainURI the URI of the SCA domain + * @return + */ + // FIXME : this is a temporary implementation to get the capability working + public static SCADomain connect(String domainURI) { + return theDomain; + } + + /** + * Close the SCA domain. + */ + public void close() { + // TODO: temporary to support initial SCADomain.connect capability + SCADomain.removeInstance(this); + } + + /** + * Returns the URI of the SCA Domain. + * + * @return the URI of the SCA Domain + */ + public abstract String getURI(); + + /** + * Cast a type-safe reference to a CallableReference. Converts a type-safe + * reference to an equivalent CallableReference; if the target refers to a + * service then a ServiceReference will be returned, if the target refers to + * a callback then a CallableReference will be returned. + * + * @param target a reference proxy provided by the SCA runtime + * @param <B> the Java type of the business interface for the reference + * @param <R> the type of reference to be returned + * @return a CallableReference equivalent for the proxy + * @throws IllegalArgumentException if the supplied instance is not a + * reference supplied by the SCA runtime + */ + public abstract <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException; + + /** + * Returns a proxy for a service provided by a component in the SCA domain. + * + * @param businessInterface the interface that will be used to invoke the + * service + * @param serviceName the name of the service + * @param <B> the Java type of the business interface for the service + * @return an object that implements the business interface + */ + public abstract <B> B getService(Class<B> businessInterface, String serviceName); + + /** + * Returns a ServiceReference for a service provided by a component in the + * SCA domain. + * + * @param businessInterface the interface that will be used to invoke the + * service + * @param serviceName the name of the service + * @param <B> the Java type of the business interface for the service + * @return a ServiceReference for the designated service + */ + public abstract <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String serviceName); + + /** + * 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(); + + Class<?> implClass = ServiceDiscovery.getInstance().loadFirstServiceClass(SCADomain.class); + + if (implClass == 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 + Constructor<?> constructor = null; + try { + constructor = + implClass.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 = implClass.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/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomainBean.java b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomainBean.java new file mode 100644 index 0000000000..c9bfe499c6 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCADomainBean.java @@ -0,0 +1,125 @@ +/* + * 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; + +/** + * + * @version $Rev$ $Date$ + */ +public class SCADomainBean extends SCADomain { + + private SCADomain instance; + + private String uri = LOCAL_DOMAIN_URI; + private String location = "/"; + private String[] composites; + + /** + * Constructs a new SCA domain + */ + public SCADomainBean() { + } + + @Override + public String getURI() { + return uri; + } + + public void setURI(String uri) { + this.uri = uri; + } + + public void setContributionLocation(String contributionLocation) { + this.location = contributionLocation; + } + + public String getContributionLocation() { + return location; + } + + public void setDeployableComposite(String composite) { + setDeployableComposites(composite); + } + + public void setDeployableComposites(String... composites) { + this.composites = composites; + } + + public String[] getDeployableComposites() { + return composites; + } + + @SuppressWarnings("unchecked") + @Override + public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException { + if (instance == null) { + instance = SCADomain.createNewInstance(uri, location, composites); + } + Object result = instance.cast(target); + return (R) result; + } + + @Override + public void close() { + if (instance == null) { + instance = SCADomain.createNewInstance(uri, location, composites); + } + instance.close(); + instance = null; + } + + @Override + public <B> B getService(Class<B> businessInterface, String serviceName) { + if (instance == null) { + instance = SCADomain.createNewInstance(uri, location, composites); + } + return instance.getService(businessInterface, serviceName); + } + + @Override + public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String referenceName) { + if (instance == null) { + instance = SCADomain.createNewInstance(uri, location, composites); + } + return instance.getServiceReference(businessInterface, referenceName); + } + + @Override + protected void finalize() throws Throwable { + + // Make sure that the SCA domain is closed + if (instance != null) { + instance.close(); + instance = null; + } + } + + @Override + public ComponentManager getComponentManager() { + if (instance == null) { + instance = SCADomain.createNewInstance(uri, location, composites); + } + return instance.getComponentManager(); + } +} diff --git a/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCATestCaseRunner.java b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCATestCaseRunner.java new file mode 100644 index 0000000000..7c893a5c9e --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/SCATestCaseRunner.java @@ -0,0 +1,291 @@ +/* + * 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; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * A helper class that can be used to run an SCA JUnit test case. The test case will run in an isolated class loader. + * + * @version $Rev$ $Date$ + */ +public class SCATestCaseRunner { + + private ClassLoader classLoader; + private Class<?> testSuiteClass; + private Object testSuite; + private Class<?> testResultClass; + private Class<?> testCaseClass; + private Object testCase; + + private Class<?> beforeAnnotation; + private Class<?> beforeClassAnnotation; + private Class<?> afterAnnotation; + private Class<?> afterClassAnnotation; + private Class<?> junit4AdapterClass; + private Class<?> junit3TestCaseClass; + + /** + * Constructs a new TestCase runner. + * + * @param testClass + */ + public SCATestCaseRunner(Class testClass) { + try { + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + classLoader = testClass.getClassLoader(); + if (classLoader instanceof URLClassLoader) { + URL[] urls = ((URLClassLoader)classLoader).getURLs(); + classLoader = new URLClassLoader(urls, classLoader.getParent()); + } else if (classLoader == tccl || classLoader.getParent() == tccl) { + classLoader = new URLClassLoader(new URL[0], classLoader); + } else { + classLoader = tccl; + } + + try { + // Thread.currentThread().setContextClassLoader(classLoader); + // Allow privileged access to set class loader. Requires RuntimePermission + // setContextClassLoader in security policy. + final ClassLoader finalClassLoader = classLoader; + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + Thread.currentThread().setContextClassLoader(finalClassLoader); + return null; + } + }); + + testCaseClass = Class.forName(testClass.getName(), true, classLoader); + testCase = testCaseClass.newInstance(); + ClassLoader testClassLoader = testCaseClass.getClassLoader(); + + junit3TestCaseClass = Class.forName("junit.framework.TestCase", true, testClassLoader); + + testSuiteClass = Class.forName("junit.framework.TestSuite", true, testClassLoader); + Constructor testSuiteConstructor = testSuiteClass.getConstructor(Class.class); + testSuite = testSuiteConstructor.newInstance(testCaseClass); + + testResultClass = Class.forName("junit.framework.TestResult", true, testClassLoader); + + try { + beforeAnnotation = Class.forName("org.junit.Before", true, testClassLoader); + afterAnnotation = Class.forName("org.junit.After", true, testClassLoader); + beforeClassAnnotation = Class.forName("org.junit.BeforeClass", true, testClassLoader); + afterClassAnnotation = Class.forName("org.junit.AfterClass", true, testClassLoader); + junit4AdapterClass = Class.forName("junit.framework.JUnit4TestAdapter", true, testClassLoader); + } catch (Exception e) { + // Unexpected + throw new AssertionError(e); + } + } catch (Throwable e) { + e.printStackTrace(); + } finally { + // Thread.currentThread().setContextClassLoader(tccl); + // Allow privileged access to set class loader. Requires RuntimePermission + // setContextClassLoader in security policy. + final ClassLoader finaltccl = tccl; + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + Thread.currentThread().setContextClassLoader(finaltccl); + return null; + } + }); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Run the test case + */ + public void run() { + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + try { + // Thread.currentThread().setContextClassLoader(classLoader); + // Allow privileged access to set class loader. Requires RuntimePermission + // setContextClassLoader in security policy. + final ClassLoader finalClassLoader = classLoader; + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + Thread.currentThread().setContextClassLoader(finalClassLoader); + return null; + } + }); + + 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); + // Allow privileged access to set class loader. Requires RuntimePermission + // setContextClassLoader in security policy. + final ClassLoader finaltccl = tccl; + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + Thread.currentThread().setContextClassLoader(finaltccl); + return null; + } + }); + } + } + + /** + * 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); + // Allow privileged access to set class loader. Requires RuntimePermission + // setContextClassLoader in security policy. + final ClassLoader finalClassLoader = classLoader; + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + Thread.currentThread().setContextClassLoader(finalClassLoader); + return null; + } + }); + + 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); + // Allow privileged access to set class loader. Requires RuntimePermission + // setContextClassLoader in security policy. + final ClassLoader finaltccl = tccl; + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + Thread.currentThread().setContextClassLoader(finaltccl); + return null; + } + }); + } + } + + /** + * Invoke the specified method + */ + private void execute(String methodName) { + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + try { + // Thread.currentThread().setContextClassLoader(classLoader); + // Allow privileged access to set class loader. Requires RuntimePermission + // setContextClassLoader in security policy. + final ClassLoader finalClassLoader = classLoader; + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + Thread.currentThread().setContextClassLoader(finalClassLoader); + return null; + } + }); + Method setUpMethod = testCaseClass.getDeclaredMethod(methodName); + setUpMethod.setAccessible(true); + setUpMethod.invoke(testCase); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + // Thread.currentThread().setContextClassLoader(tccl); + // Allow privileged access to set class loader. Requires RuntimePermission + // setContextClassLoader in security policy. + final ClassLoader finaltccl = tccl; + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + Thread.currentThread().setContextClassLoader(finaltccl); + return null; + } + }); + } + } + +} diff --git a/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ComponentManagerImpl.java b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ComponentManagerImpl.java new file mode 100644 index 0000000000..187f32f405 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ComponentManagerImpl.java @@ -0,0 +1,120 @@ +/* + * 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; + +/** + * Implementation of the ComponentManager. + * + * @version $Rev$ $Date$ + */ +public class ComponentManagerImpl implements ComponentManager { + + protected List<ComponentListener> listeners = new CopyOnWriteArrayList<ComponentListener>(); + protected EmbeddedSCADomain domain; + + public ComponentManagerImpl(EmbeddedSCADomain domain) { + this.domain = domain; + } + + public void addComponentListener(ComponentListener listener) { + this.listeners.add(listener); + } + + public void removeComponentListener(ComponentListener listener) { + this.listeners.remove(listener); + } + + public Set<String> getComponentNames() { + Set<String> names = new HashSet<String>(); + for (Composite composite: domain.getDomainComposite().getIncludes()) { + for (Component component: composite.getComponents()) { + names.add(component.getName()); + } + } + return names; + } + + public Component getComponent(String componentName) { + for (Composite composite: domain.getDomainComposite().getIncludes()) { + for (Component component: composite.getComponents()) { + if (component.getName().equals(componentName)) { + return component; + } + } + } + return null; + } + + public void startComponent(String componentName) throws ActivationException { + Component component = getComponent(componentName); + if (component == null) { + throw new IllegalArgumentException("no component: " + componentName); + } + domain.getCompositeActivator().start(component); + notifyComponentStarted(componentName); + } + + public void stopComponent(String componentName) throws ActivationException { + Component component = getComponent(componentName); + if (component == null) { + throw new IllegalArgumentException("no component: " + componentName); + } + domain.getCompositeActivator().stop(component); + notifyComponentStopped(componentName); + } + + public void notifyComponentStarted(String componentName) { + for (ComponentListener listener : listeners) { + try { + listener.componentStarted(componentName); + } catch (Exception e) { + e.printStackTrace(); // TODO: log + } + } + } + + public void notifyComponentStopped(String componentName) { + for (ComponentListener listener : listeners) { + try { + listener.componentStopped(componentName); + } catch (Exception e) { + e.printStackTrace(); // TODO: log + } + } + } + + public boolean isComponentStarted(String componentName) { + RuntimeComponentImpl runtimeComponent = (RuntimeComponentImpl)getComponent(componentName); + return runtimeComponent.isStarted(); + } + +} diff --git a/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomain.java b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomain.java new file mode 100644 index 0000000000..1bca290c27 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomain.java @@ -0,0 +1,339 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded.impl; + +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; + +import javax.xml.XMLConstants; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.xml.Constants; +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.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.node.SCAClient; +import org.apache.tuscany.sca.node.SCAContribution; +import org.apache.tuscany.sca.node.SCANode; +import org.apache.tuscany.sca.node.SCANodeFactory; +import org.apache.tuscany.sca.node.impl.NodeImpl; +import org.osoa.sca.CallableReference; +import org.osoa.sca.ServiceReference; + +/** + * A default SCA domain facade implementation. + * + * @version $Rev$ $Date$ + */ +public class DefaultSCADomain extends SCADomain { + + private String uri; + private String[] composites; + // private Composite domainComposite; + // private List<Contribution> contributions; + private Map<String, Component> components; + private ComponentManager componentManager; + // private ClassLoader runtimeClassLoader; + private ClassLoader applicationClassLoader; + private String domainURI; + private List<String> contributionURLs; + + private CompositeActivator compositeActivator; + private SCANode node; + private SCAClient client; + + /** + * Constructs a new domain facade. + * + * @param domainURI + * @param contributionLocation + * @param composites + */ + public DefaultSCADomain(ClassLoader runtimeClassLoader, + ClassLoader applicationClassLoader, + String domainURI, + String contributionLocation, + String... composites) { + this.uri = domainURI; + this.composites = composites; + // this.runtimeClassLoader = runtimeClassLoader; + this.applicationClassLoader = applicationClassLoader; + this.domainURI = domainURI; + this.contributionURLs = new ArrayList<String>(); + if (contributionLocation != null && !"/".equals(contributionLocation)) { + this.contributionURLs.add(contributionLocation); + } + this.composites = composites; + + init(); + + this.componentManager = new DefaultSCADomainComponentManager(this); + + } + + /** + * A hack to create an aggregated composite + * @param classLoader + * @param composites + * @return + */ + private String createDeploymentComposite(ClassLoader classLoader, String composites[]) { + try { + StringBuffer xml = + new StringBuffer("<sca:composite xmlns:sca=\"http://www.osoa.org/xmlns/sca/1.0\"") + .append(" targetNamespace=\"http://tempuri.org\" name=\"aggregated\">\n"); + XMLInputFactory factory = XMLInputFactory.newInstance(); + for (int i = 0; i < composites.length; i++) { + URL url = classLoader.getResource(composites[i]); + if (url == null) { + continue; + } + String location = NodeImpl.getContributionURL(url, composites[i]).toString(); + if (!contributionURLs.contains(location)) { + contributionURLs.add(location); + } + URLConnection connection = url.openConnection(); + connection.setUseCaches(false); + XMLStreamReader reader = factory.createXMLStreamReader(connection.getInputStream()); + reader.nextTag(); + + assert Constants.COMPOSITE_QNAME.equals(reader.getName()); + String ns = reader.getAttributeValue(null, "targetNamespace"); + if (ns == null) { + ns = XMLConstants.NULL_NS_URI; + } + String name = reader.getAttributeValue(null, "name"); + reader.close(); + if (XMLConstants.NULL_NS_URI.equals(ns)) { + xml.append("<sca:include name=\"").append(name).append("\"/>\n"); + } else { + xml.append("<sca:include xmlns:ns").append(i).append("=\"").append(ns).append("\""); + xml.append(" name=\"").append("ns").append(i).append(":").append(name).append("\"/>\n"); + } + } + xml.append("</sca:composite>"); + // System.out.println(xml.toString()); + return xml.toString(); + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + } + + public void init() { + SCANodeFactory factory = SCANodeFactory.newInstance(); + + List<SCAContribution> contributions = new ArrayList<SCAContribution>(); + + if (composites != null && composites.length > 1) { + // Create an aggregated composite that includes all the composites as Node API only takes one composite + String content = createDeploymentComposite(applicationClassLoader, composites); + // Create SCA contributions + for (String location : contributionURLs) { + contributions.add(new SCAContribution(location, location)); + } + node = + factory.createSCANode("http://tempuri.org/aggregated", content, contributions + .toArray(new SCAContribution[contributions.size()])); + } else { + for (String location : contributionURLs) { + contributions.add(new SCAContribution(location, location)); + } + String composite = (composites != null && composites.length >= 1) ? composites[0] : null; + if (!contributions.isEmpty()) { + node = + factory.createSCANode(composite, contributions.toArray(new SCAContribution[contributions.size()])); + } else { + node = factory.createSCANodeFromClassLoader(composite, applicationClassLoader); + } + } + client = (SCAClient)node; + compositeActivator = ((NodeImpl)node).getCompositeActivator(); + components = new HashMap<String, Component>(); + + node.start(); + + getComponents(compositeActivator.getDomainComposite()); + } + + private void getComponents(Composite composite) { + for (Component c : composite.getComponents()) { + components.put(c.getName(), c); + } + for (Composite cp : composite.getIncludes()) { + getComponents(cp); + } + } + + @Override + public void close() { + super.close(); + node.stop(); + + } + + @Override + @SuppressWarnings("unchecked") + public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException { + return (R)client.cast(target); + } + + @Override + public <B> B getService(Class<B> businessInterface, String serviceName) { + return client.getService(businessInterface, serviceName); + } + + @Override + public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String name) { + return client.getServiceReference(businessInterface, name); + } + + @Override + public String getURI() { + return uri; + } + + @Override + public ComponentManager getComponentManager() { + return componentManager; + } + + public Set<String> getComponentNames() { + return components.keySet(); + /* + Set<String> componentNames = new HashSet<String>(); + for (Contribution contribution : contributions) { + for (Artifact artifact : contribution.getArtifacts()) { + if (artifact.getModel() instanceof Composite) { + for (Component component : ((Composite)artifact.getModel()).getComponents()) { + componentNames.add(component.getName()); + } + } + } + } + return componentNames; + */ + } + + public Component getComponent(String componentName) { + return components.get(componentName); + /* + for (Contribution contribution : contributions) { + for (Artifact artifact : contribution.getArtifacts()) { + if (artifact.getModel() instanceof Composite) { + for (Component component : ((Composite)artifact.getModel()).getComponents()) { + if (component.getName().equals(componentName)) { + return component; + } + } + } + } + } + return null; + */ + } + + public void startComponent(String componentName) throws ActivationException { + Component component = getComponent(componentName); + if (component == null) { + throw new IllegalArgumentException("no component: " + componentName); + } + compositeActivator.start(component); + } + + public void stopComponent(String componentName) throws ActivationException { + Component component = getComponent(componentName); + if (component == null) { + throw new IllegalArgumentException("no component: " + componentName); + } + compositeActivator.stop(component); + } +} + +class DefaultSCADomainComponentManager implements ComponentManager { + + protected DefaultSCADomain scaDomain; + protected List<ComponentListener> listeners = new CopyOnWriteArrayList<ComponentListener>(); + + public DefaultSCADomainComponentManager(DefaultSCADomain scaDomain) { + this.scaDomain = scaDomain; + } + + public void addComponentListener(ComponentListener listener) { + this.listeners.add(listener); + } + + public void removeComponentListener(ComponentListener listener) { + this.listeners.remove(listener); + } + + public Set<String> getComponentNames() { + return scaDomain.getComponentNames(); + } + + public Component getComponent(String componentName) { + return scaDomain.getComponent(componentName); + } + + public void startComponent(String componentName) throws ActivationException { + scaDomain.startComponent(componentName); + } + + public void stopComponent(String componentName) throws ActivationException { + scaDomain.stopComponent(componentName); + } + + public void notifyComponentStarted(String componentName) { + for (ComponentListener listener : listeners) { + try { + listener.componentStarted(componentName); + } catch (Exception e) { + e.printStackTrace(); // TODO: log + } + } + } + + public void notifyComponentStopped(String componentName) { + for (ComponentListener listener : listeners) { + try { + listener.componentStopped(componentName); + } catch (Exception e) { + e.printStackTrace(); // TODO: log + } + } + } + + public boolean isComponentStarted(String componentName) { + RuntimeComponentImpl runtimeComponent = (RuntimeComponentImpl)getComponent(componentName); + return runtimeComponent.isStarted(); + } + +} diff --git a/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomain.java b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomain.java new file mode 100644 index 0000000000..519e76d0ae --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomain.java @@ -0,0 +1,235 @@ +/* + * 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.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.assembly.xml.Constants; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.service.ContributionService; +import org.apache.tuscany.sca.core.assembly.ActivationException; +import org.apache.tuscany.sca.core.assembly.CompositeActivator; +import org.apache.tuscany.sca.core.context.ServiceReferenceImpl; +import org.apache.tuscany.sca.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.node.impl.RuntimeBootStrapper; +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 RuntimeBootStrapper 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 RuntimeBootStrapper(runtimeClassLoader); + } + + public void start() throws ActivationException { + + // Start the runtime + runtime.start(); + + // Create an in-memory domain level composite + AssemblyFactory assemblyFactory = runtime.getAssemblyFactory(); + domainComposite = assemblyFactory.createComposite(); + domainComposite.setName(new QName(Constants.SCA10_NS, "domain")); + domainComposite.setURI(uri); + + getCompositeActivator().setDomainComposite(domainComposite); + + } + + public void stop() throws ActivationException { + + // Stop the runtime + runtime.stop(); + + // Cleanup + domainComposite = null; + } + + public void buildComposite(Composite composite) throws CompositeBuilderException { + runtime.buildComposite(composite); + } + + public ContributionService getContributionService() { + return runtime.getContributionService(); + } + + public CompositeBuilder getCompositeBuilder() { + return runtime.getCompositeBuilder(); + } + + public CompositeActivator getCompositeActivator() { + return runtime.getCompositeActivator(); + } + + public Composite getDomainComposite() { + return domainComposite; + } + + @Override + public ComponentManager getComponentManager() { + return componentManager; + } + + @Override + public void close() { + super.close(); + } + + @Override + public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException { + return (R)runtime.getProxyFactory().cast(target); + } + + @Override + public <B> B getService(Class<B> businessInterface, String serviceName) { + ServiceReference<B> serviceReference = getServiceReference(businessInterface, serviceName); + if (serviceReference == null) { + throw new ServiceRuntimeException("Service not found: " + serviceName); + } + return serviceReference.getService(); + } + + private <B> ServiceReference<B> createServiceReference(Class<B> businessInterface, String targetURI) { + try { + AssemblyFactory assemblyFactory = runtime.getAssemblyFactory(); + Composite composite = assemblyFactory.createComposite(); + composite.setName(new QName(Constants.SCA10_TUSCANY_NS, "default")); + RuntimeComponent component = (RuntimeComponent)assemblyFactory.createComponent(); + component.setName("default"); + component.setURI("default"); + runtime.getCompositeActivator().configureComponentContext(component); + composite.getComponents().add(component); + RuntimeComponentReference reference = (RuntimeComponentReference)assemblyFactory.createComponentReference(); + reference.setName("default"); + ModelFactoryExtensionPoint factories = + runtime.getExtensionPointRegistry().getExtensionPoint(ModelFactoryExtensionPoint.class); + JavaInterfaceFactory javaInterfaceFactory = factories.getFactory(JavaInterfaceFactory.class); + InterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract(); + interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(businessInterface)); + reference.setInterfaceContract(interfaceContract); + component.getReferences().add(reference); + reference.setComponent(component); + SCABindingFactory scaBindingFactory = factories.getFactory(SCABindingFactory.class); + SCABinding binding = scaBindingFactory.createSCABinding(); + binding.setURI(targetURI); + reference.getBindings().add(binding); + return new ServiceReferenceImpl<B>(businessInterface, component, reference, binding, runtime + .getProxyFactory(), runtime.getCompositeActivator()); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + @Override + public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String name) { + + // Extract the component name + String componentName; + String serviceName; + int i = name.indexOf('/'); + if (i != -1) { + componentName = name.substring(0, i); + serviceName = name.substring(i + 1); + + } else { + componentName = name; + serviceName = null; + } + + // Lookup the component in the domain + Component component = componentManager.getComponent(componentName); + if (component == null) { + // The component is not local in the partition, try to create a remote service ref + return createServiceReference(businessInterface, name); + } + RuntimeComponentContext componentContext = null; + + // If the component is a composite, then we need to find the + // non-composite component that provides the requested service + if (component.getImplementation() instanceof Composite) { + for (ComponentService componentService : component.getServices()) { + if (serviceName == null || serviceName.equals(componentService.getName())) { + CompositeService compositeService = (CompositeService)componentService.getService(); + if (compositeService != null) { + if (serviceName != null) { + serviceName = "$promoted$" + component.getName() + "$slash$" + 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/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/HotUpdatableSCADomain.java b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/HotUpdatableSCADomain.java new file mode 100644 index 0000000000..d59f1544e5 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/HotUpdatableSCADomain.java @@ -0,0 +1,389 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded.impl; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.service.ContributionService; +import org.apache.tuscany.sca.contribution.service.util.FileHelper; +import org.apache.tuscany.sca.core.assembly.ActivationException; +import org.apache.tuscany.sca.host.embedded.SCADomain; +import org.apache.tuscany.sca.host.embedded.management.ComponentManager; +import org.osoa.sca.CallableReference; +import org.osoa.sca.ServiceReference; +import org.osoa.sca.ServiceRuntimeException; + +/** + * An SCADomain that starts a Tuscany runtime supporting multiple + * SCA contribution jars. All contribution jars found in a repository + * directory will be contributed to the SCA domain. Any changes to the + * contributions in that repository will be automatically detected and + * the SCADomain updated accordingly. + * + * TODO: find how to properly add/remove contributions and start/activate the SCADomain + * 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 + * + * @version $Rev$ $Date$ + */ +public class HotUpdatableSCADomain extends SCADomain { + private static final Logger logger = Logger.getLogger(HotUpdatableSCADomain.class.getName()); + protected String domainURI; + protected File contributionRepository; + + protected EmbeddedSCADomain scaDomain; + + protected boolean hotUpdateActive; + protected Thread hotUpdateThread; + protected int hotUpdateInterval; // milliseconds, 0 = hotupdate disabled + + protected HashMap<URL, Long> existingContributions; // value is last modified time + protected ClassLoader originalCCL; + + protected static final String REPOSITORY_FOLDER = "sca-contributions"; + + public HotUpdatableSCADomain(String domainURI, File contributionRepository, int hotupdateInterval) { + this.domainURI = domainURI; + this.contributionRepository = contributionRepository; + this.hotUpdateInterval = hotupdateInterval; + this.originalCCL = Thread.currentThread().getContextClassLoader(); + start(); + } + + protected void start() { + try { + initEmbeddedSCADomain(); + activateHotUpdate(); + for (URL url : existingContributions.keySet()) { + File f = new File(url.toURI()); + logger.info("added contribution: " + f.getName()); + } + } catch (ActivationException e) { + throw new ServiceRuntimeException(e); + } catch (URISyntaxException e) { + throw new ServiceRuntimeException(e); + } + } + + @Override + public void close() { + try { + hotUpdateActive = false; + scaDomain.stop(); + } catch (ActivationException e) { + throw new ServiceRuntimeException(e); + } + Thread.currentThread().setContextClassLoader(originalCCL); + super.close(); + } + + + protected SCADomain initEmbeddedSCADomain() throws ActivationException { + + URL[] contributionJars = getContributionJarURLs(contributionRepository); + + this.existingContributions = getLastModified(contributionJars); + + if (hotUpdateInterval > 0) { + contributionJars = copyContributionsToTemp(contributionJars); + } + + // Using the CCL as the parent exposes Tuscany to the contributions, want to do this? + URLClassLoader cl = new URLClassLoader(contributionJars, originalCCL); + Thread.currentThread().setContextClassLoader(cl); + + scaDomain = new EmbeddedSCADomain(cl, domainURI); + + scaDomain.start(); + + initContributions(scaDomain, cl, contributionJars); + + return scaDomain; + } + + protected URL[] getContributionJarURLs(File repositoryDir) { + + String[] jars = repositoryDir.list(new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.endsWith(".jar"); + }}); + + List<URL> contributionJars = new ArrayList<URL>(); + if (jars != null) { + for (String jar : jars) { + try { + contributionJars.add(new File(repositoryDir, jar).toURL()); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + } + + return contributionJars.toArray(new URL[contributionJars.size()]); + } + + /** + * TODO: No idea what the 'correct' way to add/contribute and activate/start things to an scaDomain is + * but this seems to work. Doesn't seem to start <service>s or <reference>s which are outside of + * a <component> so something is missing/wrong. Also this doesn't seem to be picking up composites + * located in META-INF/deployables or specified in the sca-deployables.xml. Maybe the EmbeddedSCADomain + * and ContributionService APIs should make all this easier? + */ + protected void initContributions(EmbeddedSCADomain scaDomain, ClassLoader cl, URL[] contributionJars) { + Contribution contribution = null; + ContributionService contributionService = scaDomain.getContributionService(); + for (URL jar : contributionJars) { + InputStream is = null; + try { + is = jar.openStream(); + contribution = contributionService.contribute(jar.toString(), jar, is); + } catch (Exception e) { + System.err.println("exception adding contribution: " + jar); + e.printStackTrace(); + } + if (is != null) { + try { + is.close(); + } catch (IOException e) { + // ignore + } + } + } + + if (contribution != null ) { + try { + + for (Composite composite : contribution.getDeployables()) { + scaDomain.getDomainComposite().getIncludes().add(composite); + scaDomain.getCompositeBuilder().build(composite); + scaDomain.getCompositeActivator().activate(composite); + } + + for (Composite composite : contribution.getDeployables()) { + scaDomain.getCompositeActivator().start(composite); + } + + } catch (ActivationException e) { + throw new RuntimeException(e); + } catch (CompositeBuilderException e) { + throw new RuntimeException(e); + } + } + + } + + /** + * Copies Files to a temp location returning the URLs of the new temp files. + * For hot update to work need to be able to delete/update the contribution jar's + * but as they're in the classpath the URLClassLoader has an open lock on the jar's + * so you can't update them. This solution copies each contribution to a temp + * location for use on the classpath, nicer would be a ClassLoder impl that doesn't + * lock the jar's. + */ + protected URL[] copyContributionsToTemp(URL[] contributionJars) { + try { + + URL[] newURLs = new URL[contributionJars.length]; + File tempDir = new File(System.getProperty("java.io.tmpdir")); + for (int i=0; i<contributionJars.length; i++) { + File fin = new File(contributionJars[i].toURI()); + File fout = File.createTempFile("tuscany", fin.getName(), tempDir); + fout.deleteOnExit(); + FileHelper.copyFile(fin, fout); + fout.setLastModified(System.currentTimeMillis()); + newURLs[i] = fout.toURL(); + } + return newURLs; + + } catch (IOException e) { + throw new RuntimeException(e); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + /** + * Returns the last modified times of the files pointed to by the URLs + */ + protected HashMap<URL, Long> getLastModified(URL[] contrabutions) { + try { + + HashMap<URL, Long> contributionLastUpdates = new HashMap<URL, Long>(); + for (URL url: contrabutions) { + File f = new File(url.toURI()); + contributionLastUpdates.put(url, new Long(f.lastModified())); + } + return contributionLastUpdates; + + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + protected void activateHotUpdate() { + if (hotUpdateInterval == 0) { + return; // hotUpdateInterval of 0 disables hotupdate + } + + Runnable runable = new Runnable() { + public void run() { + logger.info("Tuscany contribution hotupdate running"); + while (hotUpdateActive) { + try { + Thread.sleep(hotUpdateInterval); + } catch (InterruptedException e) { + } + if (hotUpdateActive) { + checkForUpdates(); + } + } + logger.info("Tuscany contribution hotupdate stopped"); + } + }; + hotUpdateThread = new Thread(runable, "TuscanyHotUpdate"); + hotUpdateActive = true; + hotUpdateThread.start(); + } + + + /** + * Checks if any of the contributions have been updated and if so restarts the SCADomain + * 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 separate + * ClassLoader per contribution? But then have all the issues with sharing classes + * across contributions. + */ + protected void checkForUpdates() { + URL[] currentContributions = getContributionJarURLs(contributionRepository); + + if (areContributionsAltered(currentContributions)) { + try { + scaDomain.stop(); + } catch (Exception e) { + e.printStackTrace(); + } + try { + initEmbeddedSCADomain(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + protected boolean areContributionsAltered(URL[] currentContrabutions) { + try { + + List addedContributions = getAddedContributions(currentContrabutions); + List removedContributions = getRemovedContributions(currentContrabutions); + List updatedContributions = getUpdatedContributions(currentContrabutions); + + return (addedContributions.size() > 0 || removedContributions.size() > 0 || updatedContributions.size() > 0); + + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + protected List<URL> getUpdatedContributions(URL[] currentContrabutions) throws URISyntaxException { + List<URL> urls = new ArrayList<URL>(); + for (URL url : currentContrabutions) { + if (existingContributions.containsKey(url)) { + File curentFile = new File(url.toURI()); + if (curentFile.lastModified() != existingContributions.get(url)) { + urls.add(url); + logger.info("updated contribution: " + curentFile.getName()); + } + } + } + return urls; + } + + protected List getRemovedContributions(URL[] currentContrabutions) throws URISyntaxException { + List<URL> currentUrls = Arrays.asList(currentContrabutions); + List<URL> urls = new ArrayList<URL>(); + for (URL url : existingContributions.keySet()) { + if (!currentUrls.contains(url)) { + urls.add(url); + } + } + for (URL url : urls) { + logger.info("removed contributions: " + new File(url.toURI()).getName()); + } + return urls; + } + + protected List getAddedContributions(URL[] currentContrabutions) throws URISyntaxException { + List<URL> urls = new ArrayList<URL>(); + for (URL url : currentContrabutions) { + if (!existingContributions.containsKey(url)) { + urls.add(url); + logger.info("added contribution: " + new File(url.toURI()).getName()); + } + } + return urls; + } + + @Override + public <B, R extends CallableReference<B>> R cast(B target) throws IllegalArgumentException { + throw new UnsupportedOperationException("not implemented"); + } + + @Override + public <B> B getService(Class<B> businessInterface, String serviceName) { + return scaDomain.getService(businessInterface, serviceName); + } + + @Override + public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String referenceName) { + return scaDomain.getServiceReference(businessInterface, referenceName); + } + + @Override + public String getURI() { + return domainURI; + } + + @Override + public ComponentManager getComponentManager(){ + return scaDomain.getComponentManager(); + } + +} diff --git a/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntime.java b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntime.java new file mode 100644 index 0000000000..55b6afb6f2 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntime.java @@ -0,0 +1,385 @@ +/* + * 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.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.TransformerFactory; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.EndpointFactory; +import org.apache.tuscany.sca.assembly.SCABindingFactory; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilder; +import org.apache.tuscany.sca.assembly.builder.CompositeBuilderException; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.resolver.DefaultModelResolver; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionService; +import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.ModuleActivator; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +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.ExtensibleProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint; +import org.apache.tuscany.sca.core.scope.ScopeRegistry; +import org.apache.tuscany.sca.definitions.SCADefinitions; +import org.apache.tuscany.sca.definitions.impl.SCADefinitionsImpl; +import org.apache.tuscany.sca.definitions.util.SCADefinitionsUtil; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.MonitorFactory; +import org.apache.tuscany.sca.monitor.impl.DefaultMonitorFactoryImpl; +import org.apache.tuscany.sca.policy.DefaultIntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.DefaultPolicyFactory; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentAttachPointType; +import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.provider.SCADefinitionsProvider; +import org.apache.tuscany.sca.provider.SCADefinitionsProviderExtensionPoint; +import org.apache.tuscany.sca.work.WorkScheduler; + +/** + * + * @version $Rev$ $Date$ + */ +public class ReallySmallRuntime { + private static final Logger logger = Logger.getLogger(ReallySmallRuntime.class.getName()); + private List<ModuleActivator> modules; + private ExtensionPointRegistry registry; + + private ClassLoader classLoader; + private AssemblyFactory assemblyFactory; + private ContributionService contributionService; + private CompositeActivator compositeActivator; + private CompositeBuilder compositeBuilder; + // private DomainBuilder domainBuilder; + private WorkScheduler workScheduler; + private ScopeRegistry scopeRegistry; + private ProxyFactory proxyFactory; + private List<SCADefinitions> policyDefinitions; + private ModelResolver policyDefinitionsResolver; + private Monitor monitor; + + public ReallySmallRuntime(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + public void start() throws ActivationException { + long start = System.currentTimeMillis(); + + // Create our extension point registry + registry = new DefaultExtensionPointRegistry(); + UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class); + + // Get work scheduler + workScheduler = utilities.getUtility(WorkScheduler.class); + + // Create an interface contract mapper + InterfaceContractMapper mapper = utilities.getUtility(InterfaceContractMapper.class); + + // Get factory extension point + ModelFactoryExtensionPoint factories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + + // Get Message factory + MessageFactory messageFactory = factories.getFactory(MessageFactory.class); + + // Get proxy factory + ProxyFactoryExtensionPoint proxyFactories = registry.getExtensionPoint(ProxyFactoryExtensionPoint.class); + proxyFactory = new ExtensibleProxyFactory(proxyFactories); + + // Create model factories + assemblyFactory = new RuntimeAssemblyFactory(); + factories.addFactory(assemblyFactory); + PolicyFactory policyFactory = new DefaultPolicyFactory(); + factories.addFactory(policyFactory); + + // Load the runtime modules + modules = loadModules(registry); + + // Start the runtime modules + startModules(registry, modules); + + SCABindingFactory scaBindingFactory = factories.getFactory(SCABindingFactory.class); + IntentAttachPointTypeFactory intentAttachPointTypeFactory = new DefaultIntentAttachPointTypeFactory(); + factories.addFactory(intentAttachPointTypeFactory); + ContributionFactory contributionFactory = factories.getFactory(ContributionFactory.class); + + // Create a monitor + MonitorFactory monitorFactory = utilities.getUtility(MonitorFactory.class); + + if (monitorFactory != null){ + monitor = monitorFactory.createMonitor(); + } else { + monitorFactory = new DefaultMonitorFactoryImpl(); + monitor = monitorFactory.createMonitor(); + utilities.addUtility(monitorFactory); + //logger.fine("No MonitorFactory is found on the classpath."); + } + + // Create a contribution service + policyDefinitions = new ArrayList<SCADefinitions>(); + policyDefinitionsResolver = new DefaultModelResolver(); + contributionService = ReallySmallRuntimeBuilder.createContributionService(classLoader, + registry, + contributionFactory, + assemblyFactory, + policyFactory, + mapper, + policyDefinitions, + policyDefinitionsResolver, + monitor); + + // Create the ScopeRegistry + scopeRegistry = ReallySmallRuntimeBuilder.createScopeRegistry(registry); + + // Create a composite activator + compositeActivator = ReallySmallRuntimeBuilder.createCompositeActivator(registry, + assemblyFactory, + messageFactory, + scaBindingFactory, + mapper, + proxyFactory, + scopeRegistry, + workScheduler); + + // Load the definitions.xml + loadSCADefinitions(); + + if (logger.isLoggable(Level.FINE)) { + long end = System.currentTimeMillis(); + logger.fine("The tuscany runtime is started in " + (end - start) + " ms."); + } + } + + public void stop() throws ActivationException { + long start = System.currentTimeMillis(); + + // Stop the runtime modules + stopModules(registry, modules); + + // Stop and destroy the work manager + workScheduler.destroy(); + + // Cleanup + modules = null; + registry = null; + assemblyFactory = null; + contributionService = null; + compositeActivator = null; + workScheduler = null; + scopeRegistry = null; + + if (logger.isLoggable(Level.FINE)) { + long end = System.currentTimeMillis(); + logger.fine("The tuscany runtime is stopped in " + (end - start) + " ms."); + } + } + + public void buildComposite(Composite composite) throws CompositeBuilderException { + //Get factory extension point + ModelFactoryExtensionPoint factories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + SCABindingFactory scaBindingFactory = factories.getFactory(SCABindingFactory.class); + IntentAttachPointTypeFactory intentAttachPointTypeFactory = factories.getFactory(IntentAttachPointTypeFactory.class); + EndpointFactory endpointFactory = factories.getFactory(EndpointFactory.class); + UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class); + InterfaceContractMapper mapper = utilities.getUtility(InterfaceContractMapper.class); + DocumentBuilderFactory documentBuilderFactory = factories.getFactory(DocumentBuilderFactory.class); + TransformerFactory transformerFactory = factories.getFactory(TransformerFactory.class); + + //Create a composite builder + SCADefinitions aggregatedDefinitions = new SCADefinitionsImpl(); + for ( SCADefinitions definition : ((List<SCADefinitions>)policyDefinitions) ) { + SCADefinitionsUtil.aggregateSCADefinitions(definition, aggregatedDefinitions); + } + compositeBuilder = ReallySmallRuntimeBuilder.createCompositeBuilder(monitor, + assemblyFactory, + scaBindingFactory, + endpointFactory, + intentAttachPointTypeFactory, + documentBuilderFactory, + transformerFactory, + mapper, + aggregatedDefinitions); + compositeBuilder.build(composite); + + } + + public ContributionService getContributionService() { + return contributionService; + } + + public CompositeActivator getCompositeActivator() { + return compositeActivator; + } + + public CompositeBuilder getCompositeBuilder() { + return compositeBuilder; + } + + public AssemblyFactory getAssemblyFactory() { + return assemblyFactory; + } + + private void loadSCADefinitions() throws ActivationException { + try { + URLArtifactProcessorExtensionPoint documentProcessors = registry.getExtensionPoint(URLArtifactProcessorExtensionPoint.class); + URLArtifactProcessor<SCADefinitions> definitionsProcessor = documentProcessors.getProcessor(SCADefinitions.class); + SCADefinitionsProviderExtensionPoint scaDefnProviders = registry.getExtensionPoint(SCADefinitionsProviderExtensionPoint.class); + + SCADefinitions systemSCADefinitions = new SCADefinitionsImpl(); + SCADefinitions aSCADefn = null; + for ( SCADefinitionsProvider aProvider : scaDefnProviders.getSCADefinitionsProviders() ) { + aSCADefn = aProvider.getSCADefinition(); + SCADefinitionsUtil.aggregateSCADefinitions(aSCADefn, systemSCADefinitions); + } + + policyDefinitions.add(systemSCADefinitions); + + //we cannot expect that providers will add the intents and policysets into the resolver + //so we do this here explicitly + for ( Intent intent : systemSCADefinitions.getPolicyIntents() ) { + policyDefinitionsResolver.addModel(intent); + } + + for ( PolicySet policySet : systemSCADefinitions.getPolicySets() ) { + policyDefinitionsResolver.addModel(policySet); + } + + for ( IntentAttachPointType attachPoinType : systemSCADefinitions.getBindingTypes() ) { + policyDefinitionsResolver.addModel(attachPoinType); + } + + for ( IntentAttachPointType attachPoinType : systemSCADefinitions.getImplementationTypes() ) { + policyDefinitionsResolver.addModel(attachPoinType); + } + + //now that all system sca definitions have been read, lets resolve them right away + definitionsProcessor.resolve(systemSCADefinitions, + policyDefinitionsResolver); + } catch ( Exception e ) { + throw new ActivationException(e); + } + } + + @SuppressWarnings("unchecked") + private List<ModuleActivator> loadModules(ExtensionPointRegistry registry) throws ActivationException { + + // Load and instantiate the modules found on the classpath (or any registered ClassLoaders) + modules = new ArrayList<ModuleActivator>(); + try { + Set<ServiceDeclaration> moduleActivators = + ServiceDiscovery.getInstance().getServiceDeclarations(ModuleActivator.class); + Set<String> moduleClasses = new HashSet<String>(); + for (ServiceDeclaration moduleDeclarator : moduleActivators) { + if (moduleClasses.contains(moduleDeclarator.getClassName())) { + continue; + } + moduleClasses.add(moduleDeclarator.getClassName()); + Class<?> moduleClass = moduleDeclarator.loadClass(); + ModuleActivator module = (ModuleActivator)moduleClass.newInstance(); + modules.add(module); + } + } catch (IOException e) { + throw new ActivationException(e); + } catch (ClassNotFoundException e) { + throw new ActivationException(e); + } catch (InstantiationException e) { + throw new ActivationException(e); + } catch (IllegalAccessException e) { + throw new ActivationException(e); + } + + return modules; + } + + private void startModules(ExtensionPointRegistry registry, List<ModuleActivator> modules) + throws ActivationException { + boolean debug = logger.isLoggable(Level.FINE); + // Start all the extension modules + for (ModuleActivator module : modules) { + long start = 0L; + if (debug) { + logger.fine(module.getClass().getName() + " is starting."); + start = System.currentTimeMillis(); + } + try { + module.start(registry); + if (debug) { + long end = System.currentTimeMillis(); + logger.fine(module.getClass().getName() + " is started in " + (end - start) + " ms."); + } + } catch (Throwable e) { + logger.log(Level.WARNING, "Exception starting module " + module.getClass().getName() + " :" + e.getMessage()); + logger.log(Level.FINE, "Exception starting module " + module.getClass().getName(), e); + } + } + } + + private void stopModules(final ExtensionPointRegistry registry, List<ModuleActivator> modules) { + boolean debug = logger.isLoggable(Level.FINE); + for (ModuleActivator module : modules) { + long start = 0L; + if (debug) { + logger.fine(module.getClass().getName() + " is stopping."); + start = System.currentTimeMillis(); + } + module.stop(registry); + if (debug) { + long end = System.currentTimeMillis(); + logger.fine(module.getClass().getName() + " is stopped in " + (end - start) + " ms."); + } + } + } + + /** + * @return the proxyFactory + */ + public ProxyFactory getProxyFactory() { + return proxyFactory; + } + + /** + * @return the registry + */ + public ExtensionPointRegistry getExtensionPointRegistry() { + return registry; + } + +} diff --git a/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntimeBuilder.java b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntimeBuilder.java new file mode 100644 index 0000000000..738e5e6248 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/impl/ReallySmallRuntimeBuilder.java @@ -0,0 +1,275 @@ +/* + * 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.security.AccessController; +import java.security.PrivilegedAction; +import java.util.List; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.transform.TransformerFactory; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.EndpointFactory; +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.CompositeDocumentProcessor; +import org.apache.tuscany.sca.context.ContextFactoryExtensionPoint; +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.DefaultValidatingXMLInputFactory; +import org.apache.tuscany.sca.contribution.processor.DefaultValidationSchemaExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ExtensiblePackageProcessor; +import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.ExtensibleURLArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.PackageProcessor; +import org.apache.tuscany.sca.contribution.processor.PackageProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ValidationSchemaExtensionPoint; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint; +import org.apache.tuscany.sca.contribution.service.ContributionListenerExtensionPoint; +import org.apache.tuscany.sca.contribution.service.ContributionRepository; +import org.apache.tuscany.sca.contribution.service.ContributionService; +import org.apache.tuscany.sca.contribution.service.ExtensibleContributionListener; +import org.apache.tuscany.sca.contribution.service.TypeDescriber; +import org.apache.tuscany.sca.contribution.service.impl.ContributionRepositoryImpl; +import org.apache.tuscany.sca.contribution.service.impl.ContributionServiceImpl; +import org.apache.tuscany.sca.contribution.service.impl.PackageTypeDescriberImpl; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +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.invocation.ExtensibleWireProcessor; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.scope.CompositeScopeContainerFactory; +import org.apache.tuscany.sca.core.scope.ConversationalScopeContainerFactory; +import org.apache.tuscany.sca.core.scope.RequestScopeContainerFactory; +import org.apache.tuscany.sca.core.scope.ScopeContainerFactory; +import org.apache.tuscany.sca.core.scope.ScopeRegistry; +import org.apache.tuscany.sca.core.scope.ScopeRegistryImpl; +import org.apache.tuscany.sca.core.scope.StatelessScopeContainerFactory; +import org.apache.tuscany.sca.definitions.SCADefinitions; +import org.apache.tuscany.sca.endpointresolver.EndpointResolverFactoryExtensionPoint; +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.monitor.Monitor; +import org.apache.tuscany.sca.policy.IntentAttachPointTypeFactory; +import org.apache.tuscany.sca.policy.PolicyFactory; +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; + +/** + * + * @version $Rev$ $Date$ + */ +public class ReallySmallRuntimeBuilder { + + // private static final Logger logger = Logger.getLogger(ReallySmallRuntimeBuilder.class.getName()); + + 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); + + // Retrieve the processors extension point + StAXArtifactProcessorExtensionPoint processors = + registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + + // Create a provider factory extension point + ProviderFactoryExtensionPoint providerFactories = + registry.getExtensionPoint(ProviderFactoryExtensionPoint.class); + + // Create a endpoint resolver factory extension point + EndpointResolverFactoryExtensionPoint endpointResolverFactories = + registry.getExtensionPoint(EndpointResolverFactoryExtensionPoint.class); + + JavaInterfaceFactory javaInterfaceFactory = + registry.getExtensionPoint(ModelFactoryExtensionPoint.class).getFactory(JavaInterfaceFactory.class); + RequestContextFactory requestContextFactory = + registry.getExtensionPoint(ContextFactoryExtensionPoint.class).getFactory(RequestContextFactory.class); + + UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class); + ConversationManager conversationManager = utilities.getUtility(ConversationManager.class); + + // Create the composite activator + CompositeActivator compositeActivator = + new CompositeActivatorImpl(assemblyFactory, messageFactory, javaInterfaceFactory, scaBindingFactory, + mapper, scopeRegistry, workScheduler, wireProcessor, requestContextFactory, + proxyFactory, providerFactories, endpointResolverFactories, processors, conversationManager); + + return compositeActivator; + } + + public static CompositeBuilder createCompositeBuilder(Monitor monitor, + AssemblyFactory assemblyFactory, + SCABindingFactory scaBindingFactory, + EndpointFactory endpointFactory, + IntentAttachPointTypeFactory intentAttachPointTypeFactory, + DocumentBuilderFactory documentBuilderFactory, + TransformerFactory transformerFactory, + InterfaceContractMapper interfaceContractMapper, + SCADefinitions policyDefinitions) { + + + return new CompositeBuilderImpl(assemblyFactory, + endpointFactory, + scaBindingFactory, + intentAttachPointTypeFactory, + documentBuilderFactory, + transformerFactory, + interfaceContractMapper, + policyDefinitions, + monitor); + } + + + /** + * Create the contribution service used by this domain. + * + * @throws ActivationException + */ + public static ContributionService createContributionService(ClassLoader classLoader, + ExtensionPointRegistry registry, + ContributionFactory contributionFactory, + AssemblyFactory assemblyFactory, + PolicyFactory policyFactory, + InterfaceContractMapper mapper, + List<SCADefinitions> policyDefinitions, + ModelResolver policyDefinitionResolver, + Monitor monitor) + throws ActivationException { + + // Get the model factory extension point + ModelFactoryExtensionPoint modelFactories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + + // Create a new XML input factory + // Allow privileged access to factory. Requires RuntimePermission in security policy file. + XMLInputFactory inputFactory = AccessController.doPrivileged(new PrivilegedAction<XMLInputFactory>() { + public XMLInputFactory run() { + return XMLInputFactory.newInstance(); + } + }); + modelFactories.addFactory(inputFactory); + + // Create a validation XML schema extension point + ValidationSchemaExtensionPoint schemas = new DefaultValidationSchemaExtensionPoint(); + + // Create a validating XML input factory + XMLInputFactory validatingInputFactory = new DefaultValidatingXMLInputFactory(inputFactory, schemas, monitor); + modelFactories.addFactory(validatingInputFactory); + + // Create StAX artifact processor extension point + StAXArtifactProcessorExtensionPoint staxProcessors = + registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + + // Create and register StAX processors for SCA assembly XML + // Allow privileged access to factory. Requires RuntimePermission in security policy file. + XMLOutputFactory outputFactory = AccessController.doPrivileged(new PrivilegedAction<XMLOutputFactory>() { + public XMLOutputFactory run() { + return XMLOutputFactory.newInstance(); + } + }); + ExtensibleStAXArtifactProcessor staxProcessor = + new ExtensibleStAXArtifactProcessor(staxProcessors, inputFactory, outputFactory, monitor); + + // Create URL artifact processor extension point + URLArtifactProcessorExtensionPoint documentProcessors = + registry.getExtensionPoint(URLArtifactProcessorExtensionPoint.class); + + // Create and register document processors for SCA assembly XML + documentProcessors.getProcessor(Composite.class); + DocumentBuilderFactory documentBuilderFactory = AccessController.doPrivileged(new PrivilegedAction<DocumentBuilderFactory>() { + public DocumentBuilderFactory run() { + return DocumentBuilderFactory.newInstance(); + } + }); + documentProcessors.addArtifactProcessor(new CompositeDocumentProcessor(staxProcessor, validatingInputFactory, documentBuilderFactory, policyDefinitions, monitor)); + + // 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, monitor); + + // Create contribution listener + ExtensibleContributionListener contributionListener = + new ExtensibleContributionListener(registry.getExtensionPoint(ContributionListenerExtensionPoint.class)); + + // Create a contribution repository + ContributionRepository repository; + try { + repository = new ContributionRepositoryImpl("target", inputFactory, monitor); + } catch (IOException e) { + throw new ActivationException(e); + } + + ExtensibleURLArtifactProcessor documentProcessor = new ExtensibleURLArtifactProcessor(documentProcessors, monitor); + + // Create the contribution service + ContributionService contributionService = + new ContributionServiceImpl(repository, packageProcessor, documentProcessor, staxProcessor, + contributionListener, policyDefinitionResolver, modelResolvers, modelFactories, + assemblyFactory, contributionFactory, inputFactory, policyDefinitions, monitor); + 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/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentListener.java b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentListener.java new file mode 100644 index 0000000000..5f38c0c063 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentListener.java @@ -0,0 +1,34 @@ +/* + * 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; + +/** + * Component Listener interface. + * + * @version $Rev$ $Date$ + */ +public interface ComponentListener extends EventListener { + + void componentStarted(String componentName); + void componentStopped(String componentName); + +} diff --git a/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentManager.java b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentManager.java new file mode 100644 index 0000000000..4acb270810 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/main/java/org/apache/tuscany/sca/host/embedded/management/ComponentManager.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded.management; + +import java.util.Set; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.core.assembly.ActivationException; + +/** + * Component Manager interface. + * + * @version $Rev$ $Date$ + */ +public interface ComponentManager { + + Set<String> getComponentNames(); + + Component getComponent(String componentName); + + boolean isComponentStarted(String componentName); + + void startComponent(String componentName) throws ActivationException; + + void stopComponent(String componentName) throws ActivationException; + + void addComponentListener(ComponentListener listener); + + void removeComponentListener(ComponentListener listener); + +} diff --git a/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainBeanTestCase.java b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainBeanTestCase.java new file mode 100644 index 0000000000..9252b114a1 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainBeanTestCase.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.host.embedded.test.extension.TestService; +import org.osoa.sca.ServiceReference; + + + +/** + * Test creation of an SCADomainBean and invocation of a service. + * + * @version $Rev$ $Date$ + */ +public class SCADomainBeanTestCase extends TestCase { + + private SCADomainBean domain; + + @Override + protected void setUp() throws Exception { + domain = new SCADomainBean(); + domain.setDeployableComposites("test.composite"); + } + + public void testInvoke() throws Exception { + ServiceReference<TestService> serviceReference = domain.getServiceReference(TestService.class, "TestServiceComponent"); + assertNotNull(serviceReference); + TestService service = serviceReference.getService(); + String result = service.ping("Bob"); + assertEquals("Hello Bob", result); + } + + @Override + protected void tearDown() throws Exception { + domain.close(); + } + +} diff --git a/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainTestCase.java b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainTestCase.java new file mode 100644 index 0000000000..c52c16d8e1 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/SCADomainTestCase.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.host.embedded.test.extension.TestService; +import org.osoa.sca.ServiceReference; + + + +/** + * Test SCADomain.newInstance and invocation of a service. + * + * @version $Rev$ $Date$ + */ +public class SCADomainTestCase extends TestCase { + + private SCADomain domain; + + @Override + protected void setUp() throws Exception { + domain = SCADomain.newInstance("test.composite"); + } + + public void testInvoke() throws Exception { + ServiceReference<TestService> serviceReference = domain.getServiceReference(TestService.class, "TestServiceComponent"); + assertNotNull(serviceReference); + TestService service = serviceReference.getService(); + String result = service.ping("Bob"); + assertEquals("Hello Bob", result); + } + + @Override + protected void tearDown() throws Exception { + domain.close(); + } + +} diff --git a/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomainTestCase.java b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomainTestCase.java new file mode 100644 index 0000000000..fd5398c8e6 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/impl/DefaultSCADomainTestCase.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded.impl; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.host.embedded.management.ComponentManager; +import org.apache.tuscany.sca.host.embedded.test.extension.TestService; + + +/** + * Test creation of DefaultSCADomain. + * + * @version $Rev$ $Date$ + */ +public class DefaultSCADomainTestCase extends TestCase { + private DefaultSCADomain domain; + + @Override + protected void setUp() throws Exception { + domain = new DefaultSCADomain(getClass().getClassLoader(), getClass().getClassLoader(), + "http://localhost", "./target/test-classes", "test.composite"); + } + + public void testStart() throws Exception { + TestService service = domain.getService(TestService.class, "TestServiceComponent"); + assertNotNull(service); + } + + public void testComponentManager() throws Exception { + ComponentManager componentManager = domain.getComponentManager(); + assertEquals(1, componentManager.getComponentNames().size()); + assertEquals("TestServiceComponent", componentManager.getComponentNames().iterator().next()); + assertNotNull(componentManager.getComponent("TestServiceComponent")); + + assertTrue(componentManager.isComponentStarted("TestServiceComponent")); + componentManager.stopComponent("TestServiceComponent"); + assertFalse(componentManager.isComponentStarted("TestServiceComponent")); + } + + @Override + protected void tearDown() throws Exception { + domain.close(); + } + +} diff --git a/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomainTestCase.java b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomainTestCase.java new file mode 100644 index 0000000000..2a59635a19 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/impl/EmbeddedSCADomainTestCase.java @@ -0,0 +1,189 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded.impl; + +import java.net.URL; + +import javax.xml.namespace.QName; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.contribution.Contribution; +import org.apache.tuscany.sca.contribution.service.ContributionService; +import org.apache.tuscany.sca.host.embedded.management.ComponentListener; +import org.apache.tuscany.sca.host.embedded.management.ComponentManager; +import org.apache.tuscany.sca.host.embedded.test.extension.TestService; + +/** + * Test creation of an EmbeddedSCADomain and invocation of a service. + * + * @version $Rev$ $Date$ + */ +public class EmbeddedSCADomainTestCase extends TestCase { + private EmbeddedSCADomain domain; + + @Override + protected void setUp() throws Exception { + + // Create a test embedded SCA domain + domain = new EmbeddedSCADomain(getClass().getClassLoader(), "http://localhost"); + } + + public void testDomain() throws Exception { + // Start the domain + domain.start(); + + // Determine my class loader and my test SCA contribution location + ClassLoader myClassLoader = getClass().getClassLoader(); + String url = myClassLoader.getResource("test.txt").toString(); + url = url.substring(0, url.length()-8); + + // Contribute the SCA contribution + TestModelResolver myResolver = new TestModelResolver(myClassLoader); + ContributionService contributionService = domain.getContributionService(); + Contribution contribution = contributionService.contribute("http://test/contribution", new URL(url), myResolver, false); + assertNotNull(contribution); + + // Decide which SCA composite I want to deploy + Composite myComposite = myResolver.getComposite(new QName("http://test", "test")); + + // Add the deployable composite to the domain + domain.getDomainComposite().getIncludes().add(myComposite); + + + domain.buildComposite(myComposite); + + // Start the composite + domain.getCompositeActivator().activate(myComposite); + domain.getCompositeActivator().start(myComposite); + + // At this point the domain contains my contribution, my composite and + // it's started, my application code can start using it + + // Get the TestServiceComponent service + TestService service = domain.getService(TestService.class, "TestServiceComponent"); + + // Invoke the service + String result = service.ping("Bob"); + assertEquals("Hello Bob", result); + + // Stop my composite + domain.getCompositeActivator().stop(myComposite); + domain.getCompositeActivator().deactivate(myComposite); + + // Remove my composite + domain.getDomainComposite().getIncludes().remove(myComposite); + + // Remove my contribution + contributionService.remove("http://test/contribution"); + + // Stop the domain + domain.stop(); + } + + public void testComponentManager() throws Exception { + // Start the domain + domain.start(); + + // Determine my class loader and my test SCA contribution location + ClassLoader myClassLoader = getClass().getClassLoader(); + String url = myClassLoader.getResource("test.txt").toString(); + url = url.substring(0, url.length()-8); + + // Contribute the SCA contribution + TestModelResolver myResolver = new TestModelResolver(myClassLoader); + ContributionService contributionService = domain.getContributionService(); + Contribution contribution = contributionService.contribute("http://test/contribution", new URL(url), myResolver, false); + assertNotNull(contribution); + + // Decide which SCA composite I want to deploy + Composite myComposite = myResolver.getComposite(new QName("http://test", "test")); + + // Add the deployable composite to the domain + domain.getDomainComposite().getIncludes().add(myComposite); + + domain.buildComposite(myComposite); + + // Start the composite + domain.getCompositeActivator().activate(myComposite); + domain.getCompositeActivator().start(myComposite); + + // At this point the domain contains my contribution, my composite and + // it's started, my application code can start using it + + ComponentManager componentManager = domain.getComponentManager(); + assertEquals(1, componentManager.getComponentNames().size()); + assertEquals("TestServiceComponent", componentManager.getComponentNames().iterator().next()); + + Component component = componentManager.getComponent("TestServiceComponent"); + assertNotNull(component); + assertEquals("TestServiceComponent", component.getName()); + + MyComponentListener cl = new MyComponentListener(); + componentManager.addComponentListener(cl); + + assertTrue(componentManager.isComponentStarted("TestServiceComponent")); + + assertFalse(cl.stopCalled); + componentManager.stopComponent("TestServiceComponent"); + assertTrue(cl.stopCalled); + assertFalse(componentManager.isComponentStarted("TestServiceComponent")); + + assertFalse(cl.startCalled); + componentManager.startComponent("TestServiceComponent"); + assertTrue(cl.startCalled); + assertTrue(componentManager.isComponentStarted("TestServiceComponent")); + + // Stop my composite + domain.getCompositeActivator().stop(myComposite); + domain.getCompositeActivator().deactivate(myComposite); + + // Remove my composite + domain.getDomainComposite().getIncludes().remove(myComposite); + + // Remove my contribution + contributionService.remove("http://test/contribution"); + + // Stop the domain + domain.stop(); + } + + class MyComponentListener implements ComponentListener { + boolean startCalled; + boolean stopCalled; + + public void componentStarted(String componentName) { + startCalled = true; + } + + public void componentStopped(String componentName) { + stopCalled = true; + } + + } + + @Override + protected void tearDown() throws Exception { + domain.close(); + } + +} diff --git a/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/impl/TestModelResolver.java b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/impl/TestModelResolver.java new file mode 100644 index 0000000000..1cfe5ed5d8 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/impl/TestModelResolver.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded.impl; + +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.contribution.resolver.ClassReference; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; + + +/** + * A test model resolver, based on a map. + * + * @version $Rev$ $Date$ + */ +public class TestModelResolver implements ModelResolver { + private static final long serialVersionUID = -7826976465762296634L; + + private Map<Object, Object> map = new HashMap<Object, Object>(); + private WeakReference<ClassLoader> classLoader; + + private Map<QName, Composite> composites = new HashMap<QName, Composite>(); + + public TestModelResolver(ClassLoader classLoader) { + this.classLoader = new WeakReference<ClassLoader>(classLoader); + } + + public <T> T resolveModel(Class<T> modelClass, T unresolved) { + Object resolved = map.get(unresolved); + if (resolved != null) { + + // Return the resolved object + return modelClass.cast(resolved); + + } else if (unresolved instanceof ClassReference) { + + // Load a class on demand + ClassReference classReference = (ClassReference)unresolved; + Class<?> clazz; + try { + clazz = Class.forName(classReference.getClassName(), true, classLoader.get()); + } catch (ClassNotFoundException e) { + + // Return the unresolved object + return unresolved; + } + + // Store a new ClassReference wrapping the loaded class + resolved = new ClassReference(clazz); + map.put(resolved, resolved); + + // Return the resolved ClassReference + return modelClass.cast(resolved); + + } else { + + // Return the unresolved object + return unresolved; + } + } + + public void addModel(Object resolved) { + map.put(resolved, resolved); + if (resolved instanceof Composite) { + Composite composite = (Composite)resolved; + composites.put(composite.getName(), composite); + } + } + + public Object removeModel(Object resolved) { + if (resolved instanceof Composite) { + Composite composite = (Composite)resolved; + composites.remove(composite.getName()); + } + return map.remove(resolved); + } + + public Composite getComposite(QName qname) { + return composites.get(qname); + } + +} diff --git a/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/DefaultTestImplementationFactory.java b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/DefaultTestImplementationFactory.java new file mode 100644 index 0000000000..86e0cb6a8a --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/DefaultTestImplementationFactory.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded.test.extension; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.host.embedded.test.extension.impl.TestImplementationImpl; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; + + +/** + * Default factory for the test implementation model. + * + * @version $Rev$ $Date$ + */ +public class DefaultTestImplementationFactory implements TestImplementationFactory { + + private AssemblyFactory assemblyFactory; + private JavaInterfaceFactory javaFactory; + + public DefaultTestImplementationFactory(AssemblyFactory assemblyFactory, + JavaInterfaceFactory javaFactory) { + this.assemblyFactory = assemblyFactory; + this.javaFactory = javaFactory; + } + + public TestImplementation createTestImplementation() { + return new TestImplementationImpl(assemblyFactory, javaFactory); + } + +} diff --git a/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementation.java b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementation.java new file mode 100644 index 0000000000..d9f1228307 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementation.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.host.embedded.test.extension; + +import org.apache.tuscany.sca.assembly.Implementation; + +/** + * The model representing a test implementation in an SCA assembly model. + * + * @version $Rev$ $Date$ + */ +public interface TestImplementation extends Implementation { + + /** + * Returns the greeting string that can be configured on test implementations. + * + * @return the greeting string that can be configured on test implementations + */ + String getGreeting(); + + /** + * Sets the greeting string that can be configured on test implementations. + * + * @param greeting the greeting string that can be configured on test implementations + */ + void setGreeting(String greeting); + +} diff --git a/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementationFactory.java b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementationFactory.java new file mode 100644 index 0000000000..9200d850bb --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestImplementationFactory.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded.test.extension; + + +/** + * A factory for the test implementation model. + * + * @version $Rev$ $Date$ + */ +public interface TestImplementationFactory { + + /** + * Creates a new test implementation. + * + * @return + */ + TestImplementation createTestImplementation(); + +} diff --git a/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestService.java b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestService.java new file mode 100644 index 0000000000..4adec91151 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/TestService.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.host.embedded.test.extension; + +/** + * Service interface for test component implementations. + * + * @version $Rev$ $Date$ + */ +public interface TestService { + + String ping(String name); + +} diff --git a/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationImpl.java b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationImpl.java new file mode 100644 index 0000000000..083b01167f --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationImpl.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.host.embedded.test.extension.impl; + +import java.util.Collections; +import java.util.List; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.ConstrainingType; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.host.embedded.test.extension.TestService; +import org.apache.tuscany.sca.host.embedded.test.extension.TestImplementation; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; + + +/** + * The model representing a test implementation in an SCA assembly model. + * + * @version $Rev$ $Date$ + */ +public class TestImplementationImpl implements TestImplementation { + + private Service testService; + private String greeting; + + /** + * Constructs a new test implementation. + */ + public TestImplementationImpl(AssemblyFactory assemblyFactory, + JavaInterfaceFactory javaFactory) { + + // Test implementations always provide a single service exposing + // the TestService interface, and have no references and properties + testService = assemblyFactory.createService(); + testService.setName("Test"); + JavaInterface javaInterface; + try { + javaInterface = javaFactory.createJavaInterface(TestService.class); + } catch (InvalidInterfaceException e) { + throw new IllegalArgumentException(e); + } + JavaInterfaceContract interfaceContract = javaFactory.createJavaInterfaceContract(); + interfaceContract.setInterface(javaInterface); + testService.setInterfaceContract(interfaceContract); + } + + public String getGreeting() { + return greeting; + } + + public void setGreeting(String greeting) { + this.greeting = greeting; + } + + public ConstrainingType getConstrainingType() { + // The test implementation does not support constrainingTypes + return null; + } + + public List<Property> getProperties() { + // The test implementation does not support properties + return Collections.emptyList(); + } + + public List<Service> getServices() { + // The test implementation provides a single fixed Test service + return Collections.singletonList(testService); + } + + public List<Reference> getReferences() { + // The test implementation does not support properties + return Collections.emptyList(); + } + + public String getURI() { + // The test implementation does not have a URI + return null; + } + + public void setConstrainingType(ConstrainingType constrainingType) { + // The test implementation does not support constrainingTypes + } + + public void setURI(String uri) { + // The test implementation does not have a URI + } + + public boolean isUnresolved() { + // The test implementation is always resolved + return false; + } + + public void setUnresolved(boolean unresolved) { + // The test implementation is always resolved + } +} diff --git a/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationProcessor.java b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationProcessor.java new file mode 100644 index 0000000000..73feffad50 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/impl/TestImplementationProcessor.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.host.embedded.test.extension.impl; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.service.ContributionReadException; +import org.apache.tuscany.sca.contribution.service.ContributionResolveException; +import org.apache.tuscany.sca.contribution.service.ContributionWriteException; +import org.apache.tuscany.sca.host.embedded.test.extension.TestImplementation; +import org.apache.tuscany.sca.host.embedded.test.extension.TestImplementationFactory; + + + +/** + * Implements a StAX artifact processor for test implementations. + * + * @version $Rev$ $Date$ + */ +public class TestImplementationProcessor implements StAXArtifactProcessor<TestImplementation> { + private static final QName IMPLEMENTATION_TEST = new QName("http://test/extension", "implementation.test"); + + private TestImplementationFactory testFactory; + + public TestImplementationProcessor(TestImplementationFactory testFactory) { + this.testFactory = testFactory; + } + + public QName getArtifactType() { + // Returns the QName of the XML element processed by this processor + return IMPLEMENTATION_TEST; + } + + public Class<TestImplementation> getModelType() { + // Returns the type of model processed by this processor + return TestImplementation.class; + } + + public TestImplementation read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException { + + // Read an <implementation.test> element + + // Read the message attribute. + String message = reader.getAttributeValue(null, "greeting"); + + // Create and initialize the test implementation model + TestImplementation implementation = testFactory.createTestImplementation(); + implementation.setGreeting(message); + + // Skip to end element + while (reader.hasNext()) { + if (reader.next() == END_ELEMENT && IMPLEMENTATION_TEST.equals(reader.getName())) { + break; + } + } + + return implementation; + } + + public void resolve(TestImplementation impl, ModelResolver resolver) throws ContributionResolveException { + } + + public void write(TestImplementation implementation, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException { + + writer.writeStartElement(IMPLEMENTATION_TEST.getNamespaceURI(), IMPLEMENTATION_TEST.getLocalPart()); + + if (implementation.getGreeting() != null) { + writer.writeAttribute("greeting", implementation.getGreeting()); + } + + writer.writeEndElement(); + } +} diff --git a/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/module/TestModuleActivator.java b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/module/TestModuleActivator.java new file mode 100644 index 0000000000..f6f077e99b --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/module/TestModuleActivator.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded.test.extension.module; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.ModuleActivator; +import org.apache.tuscany.sca.host.embedded.test.extension.DefaultTestImplementationFactory; +import org.apache.tuscany.sca.host.embedded.test.extension.TestImplementationFactory; +import org.apache.tuscany.sca.host.embedded.test.extension.impl.TestImplementationProcessor; +import org.apache.tuscany.sca.host.embedded.test.extension.provider.TestImplementationProviderFactory; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint; + + + +/** + * Implements a module activator for the test implementation extension module. + * + * @version $Rev$ $Date$ + */ +public class TestModuleActivator implements ModuleActivator { + + public void start(ExtensionPointRegistry registry) { + + // Create the test implementation factory + ModelFactoryExtensionPoint modelFactories = registry.getExtensionPoint(ModelFactoryExtensionPoint.class); + AssemblyFactory assemblyFactory = modelFactories.getFactory(AssemblyFactory.class); + JavaInterfaceFactory javaFactory = modelFactories.getFactory(JavaInterfaceFactory.class); + TestImplementationFactory testFactory = new DefaultTestImplementationFactory(assemblyFactory, javaFactory); + modelFactories.addFactory(testFactory); + + // Add the test implementation extension to the StAXArtifactProcessor + // extension point + StAXArtifactProcessorExtensionPoint processors = registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + TestImplementationProcessor implementationArtifactProcessor = new TestImplementationProcessor(testFactory); + processors.addArtifactProcessor(implementationArtifactProcessor); + + // Add the test provider factory to the ProviderFactory extension point + ProviderFactoryExtensionPoint providerFactories = registry.getExtensionPoint(ProviderFactoryExtensionPoint.class); + providerFactories.addProviderFactory(new TestImplementationProviderFactory()); + } + + public void stop(ExtensionPointRegistry registry) { + } +} diff --git a/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProvider.java b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProvider.java new file mode 100644 index 0000000000..1d27e08fee --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProvider.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.host.embedded.test.extension.provider; + +import org.apache.tuscany.sca.host.embedded.test.extension.TestImplementation; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + + +/** + * Implementation provider for test implementations. + * + * @version $Rev$ $Date$ + */ +public class TestImplementationProvider implements ImplementationProvider { + + private RuntimeComponent component; + private TestImplementation implementation; + + /** + * Constructs a new test implementation provider. + */ + public TestImplementationProvider(RuntimeComponent component, TestImplementation implementation) { + this.component = component; + this.implementation = implementation; + } + + public Invoker createInvoker(RuntimeComponentService service, Operation operation) { + TestInvoker invoker = new TestInvoker(operation, implementation.getGreeting()); + return invoker; + } + + public boolean supportsOneWayInvocation() { + return false; + } + + public void start() { + System.out.println("Starting " + component.getName()); + } + + public void stop() { + System.out.println("Stopping " + component.getName()); + } + +} diff --git a/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProviderFactory.java b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProviderFactory.java new file mode 100644 index 0000000000..15d3618fdd --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestImplementationProviderFactory.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.host.embedded.test.extension.provider; + +import org.apache.tuscany.sca.host.embedded.test.extension.TestImplementation; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.ImplementationProviderFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + + +/** + * The model representing a test implementation in an SCA assembly model. + * + * @version $Rev$ $Date$ + */ +public class TestImplementationProviderFactory implements ImplementationProviderFactory<TestImplementation> { + + /** + * Constructs a new test implementation provider factory. + */ + public TestImplementationProviderFactory() { + } + + public ImplementationProvider createImplementationProvider(RuntimeComponent component, TestImplementation implementation) { + return new TestImplementationProvider(component, implementation); + } + + public Class<TestImplementation> getModelType() { + return TestImplementation.class; + } +} diff --git a/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestInvoker.java b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestInvoker.java new file mode 100644 index 0000000000..d49179dec0 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/test/java/org/apache/tuscany/sca/host/embedded/test/extension/provider/TestInvoker.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.host.embedded.test.extension.provider; + +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; + + +/** + * Implements an invoker for test component implementations. + * + * The target invoker is responsible for handling operation invocations. + * + * @version $Rev$ $Date$ + */ +public class TestInvoker implements Invoker { + private Operation operation; + private String greeting; + + public TestInvoker(Operation operation, String greeting) { + this.operation = operation; + this.greeting = greeting; + } + + public Message invoke(Message msg) { + Object[] args = msg.getBody(); + if (operation.getName().equals("ping")) { + msg.setBody(greeting + " " + args[0]); + } else { + msg.setFaultBody(new Exception("Operation " + operation.getName() + " is not supported")); + } + return msg; + } +} diff --git a/branches/sca-equinox/modules/host-embedded/src/test/resources/META-INF/services/org.apache.tuscany.sca.core.ModuleActivator b/branches/sca-equinox/modules/host-embedded/src/test/resources/META-INF/services/org.apache.tuscany.sca.core.ModuleActivator new file mode 100644 index 0000000000..7e2e11e4cc --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/test/resources/META-INF/services/org.apache.tuscany.sca.core.ModuleActivator @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# Implementation class for the ExtensionActivator
+org.apache.tuscany.sca.host.embedded.test.extension.module.TestModuleActivator
diff --git a/branches/sca-equinox/modules/host-embedded/src/test/resources/test.composite b/branches/sca-equinox/modules/host-embedded/src/test/resources/test.composite new file mode 100644 index 0000000000..bd7c5fab79 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/test/resources/test.composite @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" + targetNamespace="http://test" + xmlns:se="http://test" + xmlns:e="http://test/extension" + name="test"> + + <component name="TestServiceComponent"> + <e:implementation.test greeting="Hello" /> + </component> + +</composite> diff --git a/branches/sca-equinox/modules/host-embedded/src/test/resources/test.txt b/branches/sca-equinox/modules/host-embedded/src/test/resources/test.txt new file mode 100644 index 0000000000..287f9b1f65 --- /dev/null +++ b/branches/sca-equinox/modules/host-embedded/src/test/resources/test.txt @@ -0,0 +1,16 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License.
\ No newline at end of file |