diff options
Diffstat (limited to '')
205 files changed, 21154 insertions, 0 deletions
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/LICENSE b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/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/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/META-INF/MANIFEST.MF b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..fe68b72498 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/META-INF/MANIFEST.MF @@ -0,0 +1,30 @@ +Manifest-Version: 1.0
+Private-Package: org.apache.tuscany.sca.core.databinding.module;versio
+ n="2.0.0",org.apache.tuscany.sca.core.databinding.processor;version="2.0.0",
+ org.apache.tuscany.sca.core.databinding.transformers;version="2.0.0"
+ ,org.apache.tuscany.sca.core.databinding.wire;version="2.0.0"
+SCA-Version: 1.1
+Bundle-Name: Apache Tuscany SCA Core/DataBinding Integration
+Bundle-Vendor: The Apache Software Foundation
+Bundle-Version: 2.0.0
+Bundle-ManifestVersion: 2
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-Description: Apache Tuscany SCA Core/DataBinding Integration
+Import-Package: javax.xml.namespace,
+ org.apache.tuscany.sca.core;version="2.0.0",
+ org.apache.tuscany.sca.databinding;version="2.0.0",
+ org.apache.tuscany.sca.databinding.annotation;version="2.0.0",
+ org.apache.tuscany.sca.databinding.impl;version="2.0.0",
+ org.apache.tuscany.sca.databinding.javabeans;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef.java;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef.java.introspect;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef.util;version="2.0.0",
+ org.apache.tuscany.sca.invocation;version="2.0.0",
+ org.apache.tuscany.sca.runtime;version="2.0.0",
+ org.oasisopen.sca;version="2.0.0"
+Bundle-SymbolicName: org.apache.tuscany.sca.core.databinding
+Bundle-DocURL: http://www.apache.org/
+Export-Package: org.apache.tuscany.sca.core.databinding.processor;
+ version="2.0.0";uses:="org.w3c.dom"
+Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/NOTICE b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/NOTICE new file mode 100644 index 0000000000..ad2ba40961 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2010 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/pom.xml b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/pom.xml new file mode 100644 index 0000000000..eb2e522457 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/pom.xml @@ -0,0 +1,91 @@ +<?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> + <parent> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-modules</artifactId> + <version>2.0-Beta1-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <modelVersion>4.0.0</modelVersion> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core-databinding</artifactId> + <packaging>jar</packaging> + <name>Apache Tuscany SCA Core/DataBinding Integration</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-databinding</artifactId> + <version>${project.version}</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core</artifactId> + <version>${project.version}</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core-spi</artifactId> + <version>${project.version}</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-interface-java</artifactId> + <version>${project.version}</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-interface-java-jaxws</artifactId> + <version>${project.version}</version> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-databinding-jaxb</artifactId> + <version>${project.version}</version> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>org.codehaus.woodstox</groupId> + <artifactId>wstx-asl</artifactId> + <scope>runtime</scope> + <version>3.2.4</version> + <exclusions> + <exclusion> + <groupId>stax</groupId> + <artifactId>stax-api</artifactId> + </exclusion> + </exclusions> + </dependency> + + </dependencies> + +</project> diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/processor/DataBindingJavaInterfaceProcessor.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/processor/DataBindingJavaInterfaceProcessor.java new file mode 100644 index 0000000000..01a3c1813c --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/processor/DataBindingJavaInterfaceProcessor.java @@ -0,0 +1,131 @@ +/* + * 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.core.databinding.processor; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.annotation.DataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaOperation; +import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor; + +/** + * The databinding annotation processor for java interfaces + * + * @version $Rev$ $Date$ + */ +public class DataBindingJavaInterfaceProcessor implements JavaInterfaceVisitor { + private DataBindingExtensionPoint dataBindingRegistry; + + public DataBindingJavaInterfaceProcessor(ExtensionPointRegistry registry) { + super(); + this.dataBindingRegistry = registry.getExtensionPoint(DataBindingExtensionPoint.class); + } + + public void visitInterface(JavaInterface javaInterface) throws InvalidInterfaceException { + if (!javaInterface.isRemotable()) { + return; + } + List<Operation> operations = javaInterface.getOperations(); + processInterface(javaInterface, operations); + } + + private void processInterface(JavaInterface javaInterface, List<Operation> operations) { + Class<?> clazz = javaInterface.getJavaClass(); + DataBinding dataBinding = clazz.getAnnotation(DataBinding.class); + String dataBindingId = null; + boolean wrapperStyle = false; + if (dataBinding != null) { + dataBindingId = dataBinding.value(); + wrapperStyle = dataBinding.wrapped(); + } + + Map<String, Operation> opMap = new HashMap<String, Operation>(); + for (Operation op : javaInterface.getOperations()) { + opMap.put(op.getName(), op); + // In the case of @WebMethod, the method name can be different from the operation name + if (op instanceof JavaOperation) { + opMap.put(((JavaOperation)op).getJavaMethod().getName(), op); + } + if (dataBindingId != null) { + op.setDataBinding(dataBindingId); + op.setWrapperStyle(wrapperStyle); + } + } + for (Method method : clazz.getMethods()) { + if (method.getDeclaringClass() == Object.class) { + continue; + } + Operation operation = opMap.get(method.getName()); + if (operation == null) { // @WebMethod exclude=true + continue; + } + DataBinding methodDataBinding = clazz.getAnnotation(DataBinding.class); + if (methodDataBinding == null) { + methodDataBinding = dataBinding; + } + dataBindingId = null; + wrapperStyle = false; + if (dataBinding != null) { + dataBindingId = dataBinding.value(); + wrapperStyle = dataBinding.wrapped(); + operation.setDataBinding(dataBindingId); + operation.setWrapperStyle(wrapperStyle); + } + + // FIXME: We need a better way to identify simple java types + int i = 0; + for (org.apache.tuscany.sca.interfacedef.DataType<?> d : operation.getInputType().getLogical()) { + if (d.getDataBinding() == null) { + d.setDataBinding(dataBindingId); + } + for (Annotation a : method.getParameterAnnotations()[i]) { + if (a.annotationType() == org.apache.tuscany.sca.databinding.annotation.DataType.class) { + String value = ((org.apache.tuscany.sca.databinding.annotation.DataType)a).value(); + d.setDataBinding(value); + } + } + dataBindingRegistry.introspectType(d, operation); + i++; + } + if (operation.getOutputType() != null) { + DataType<?> d = operation.getOutputType(); + if (d.getDataBinding() == null) { + d.setDataBinding(dataBindingId); + } + org.apache.tuscany.sca.databinding.annotation.DataType dt = + method.getAnnotation(org.apache.tuscany.sca.databinding.annotation.DataType.class); + if (dt != null) { + d.setDataBinding(dt.value()); + } + dataBindingRegistry.introspectType(d, operation); + } + } + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/processor/WrapperJavaInterfaceProcessor.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/processor/WrapperJavaInterfaceProcessor.java new file mode 100644 index 0000000000..a5526ab031 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/processor/WrapperJavaInterfaceProcessor.java @@ -0,0 +1,126 @@ +/* + * 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.core.databinding.processor; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.WrapperHandler; +import org.apache.tuscany.sca.databinding.javabeans.JavaBeansDataBinding; +import org.apache.tuscany.sca.databinding.javabeans.SimpleJavaDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; + +/** + * The databinding annotation processor for java interfaces + * + * @version $Rev$ $Date$ + */ +public class WrapperJavaInterfaceProcessor implements JavaInterfaceVisitor { + private static final String JAXB_DATABINDING = "javax.xml.bind.JAXBElement"; + private DataBindingExtensionPoint dataBindingRegistry; + + public WrapperJavaInterfaceProcessor(ExtensionPointRegistry registry) { + super(); + this.dataBindingRegistry = registry.getExtensionPoint(DataBindingExtensionPoint.class); + } + + public void visitInterface(JavaInterface javaInterface) throws InvalidInterfaceException { + if (!javaInterface.isRemotable()) { + return; + } + for (Operation operation : javaInterface.getOperations()) { + WrapperInfo wrapper = operation.getWrapper(); + if (wrapper == null) { + continue; + } + // JIRA: TUSCANY-842 + String db = wrapper.getDataBinding(); + if (db == null || JAXB_DATABINDING.equals(db)) { + db = assignOperationDataBinding(operation); + } + + // Introspect the wrapper data type + org.apache.tuscany.sca.databinding.DataBinding dbObj = dataBindingRegistry.getDataBinding(db); + WrapperHandler handler = dbObj == null ? null : dbObj.getWrapperHandler(); + if (handler != null) { + wrapper.setInputWrapperType(handler.getWrapperType(operation, true)); + wrapper.setOutputWrapperType(handler.getWrapperType(operation, false)); + } + if (dbObj != null && handler == null) { + // To avoid JAXB wrapper bean generation + wrapper.setInputWrapperType(null); + wrapper.setOutputWrapperType(null); + } + } + } + + /* + * Assigns an operation DB if one of the input types, output type, fault types has a non-default DB. + * However, if two of the input types, output type, fault types have two different non-default DBs + * ( e.g. SDO and JAXB), then we do nothing to the operation DB. + * + * The method logic assumes the JavaBeans DataBinding is the default + */ + private String assignOperationDataBinding(Operation operation) { + + Set<String> dbs = new HashSet<String>(); + + // Can't use DataType<?> since operation.getInputType() returns: DataType<List<DataType>> + List<DataType> opDataTypes = new LinkedList<DataType>(); + + opDataTypes.addAll(operation.getInputType().getLogical()); + opDataTypes.add(operation.getOutputType()); + for (DataType<DataType> ft : operation.getFaultTypes()) { + opDataTypes.add(ft.getLogical()); + } + + for (DataType<?> d : opDataTypes) { + if (d != null) { + String dataBinding = d.getDataBinding(); + if ("java:array".equals(dataBinding)) { + dataBinding = ((DataType)d.getLogical()).getDataBinding(); + } + if (dataBinding != null) { + dbs.add(dataBinding); + } + } + } + + dbs.remove(JavaBeansDataBinding.NAME); + dbs.remove(SimpleJavaDataBinding.NAME); + + if (dbs.size() == 1) { + String db = dbs.iterator().next(); + operation.getWrapper().setDataBinding(db); + return db; + } else { + return operation.getWrapper().getDataBinding(); + } + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Array2ArrayTransformer.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Array2ArrayTransformer.java new file mode 100644 index 0000000000..4997a872ba --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Array2ArrayTransformer.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.core.databinding.transformers; + +import java.lang.reflect.Array; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.BaseTransformer; +import org.apache.tuscany.sca.interfacedef.DataType; + +/** + * This is a special transformer to transform the output from one IDL to the + * other one + * + * @version $Rev$ $Date$ + */ +public class Array2ArrayTransformer extends BaseTransformer<Object, Object> implements PullTransformer<Object, Object> { + + protected Mediator mediator; + + public Array2ArrayTransformer(ExtensionPointRegistry registry) { + super(); + this.mediator = registry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(Mediator.class); + } + + @Override + public String getSourceDataBinding() { + return "java:array"; + } + + @Override + public String getTargetDataBinding() { + return "java:array"; + } + + /** + * @see org.apache.tuscany.sca.databinding.BaseTransformer#getSourceType() + */ + @Override + protected Class<Object> getSourceType() { + return Object.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.BaseTransformer#getTargetType() + */ + @Override + protected Class<Object> getTargetType() { + return Object.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.Transformer#getWeight() + */ + @Override + public int getWeight() { + return 10; + } + + @SuppressWarnings("unchecked") + public Object transform(Object array, TransformationContext context) { + try { + if (array == null) { + return null; + } + DataType<DataType> sourceType = context.getSourceDataType(); + DataType<DataType> targetType = context.getTargetDataType(); + int length = Array.getLength(array); + Object targetArray = Array.newInstance(targetType.getPhysical().getComponentType(), length); + for (int i = 0; i < length; i++) { + Object sourceItem = Array.get(array, i); + Object targetItem = + mediator.mediate(sourceItem, sourceType.getLogical(), targetType.getLogical(), context + .getMetadata()); + Array.set(targetArray, i, targetItem); + } + return targetArray; + } catch (Exception e) { + throw new TransformationException(e); + } + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Collection2CollectionTransformer.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Collection2CollectionTransformer.java new file mode 100644 index 0000000000..dcd3c3fda3 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Collection2CollectionTransformer.java @@ -0,0 +1,108 @@ +/* + * 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.core.databinding.transformers; + +import java.util.Collection; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.databinding.BaseTransformer; +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.interfacedef.DataType; + +/** + * This is a special transformer to transform the output from one IDL to the + * other one + * + * @version $Rev$ $Date$ + */ +public class Collection2CollectionTransformer extends BaseTransformer<Collection, Collection> implements + PullTransformer<Collection, Collection> { + + private static final String JAVA_COLLECTION = "java:collection"; + protected Mediator mediator; + + public Collection2CollectionTransformer(ExtensionPointRegistry registry) { + super(); + this.mediator = registry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(Mediator.class); + } + + @Override + public String getSourceDataBinding() { + return JAVA_COLLECTION; + } + + @Override + public String getTargetDataBinding() { + return JAVA_COLLECTION; + } + + /** + * @see org.apache.tuscany.sca.databinding.BaseTransformer#getSourceType() + */ + @Override + protected Class<Collection> getSourceType() { + return Collection.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.BaseTransformer#getTargetType() + */ + @Override + protected Class<Collection> getTargetType() { + return Collection.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.Transformer#getWeight() + */ + @Override + public int getWeight() { + return 10; + } + + @SuppressWarnings("unchecked") + public Collection transform(Collection sourceCollection, TransformationContext context) { + try { + if (sourceCollection == null) { + return null; + } + DataType<DataType> sourceType = context.getSourceDataType(); + DataType<DataType> targetType = context.getTargetDataType(); + Collection targetCollection = createCollection(targetType.getPhysical()); + for (Object sourceItem : sourceCollection) { + Object targetItem = + mediator.mediate(sourceItem, sourceType.getLogical(), targetType.getLogical(), context + .getMetadata()); + targetCollection.add(targetItem); + } + return targetCollection; + } catch (Exception e) { + throw new TransformationException(e); + } + } + + private Collection createCollection(Class<?> collectionClass) throws Exception { + return (Collection) collectionClass.newInstance(); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Exception2ExceptionTransformer.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Exception2ExceptionTransformer.java new file mode 100644 index 0000000000..e78610cce0 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Exception2ExceptionTransformer.java @@ -0,0 +1,112 @@ +/* + * 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.core.databinding.transformers; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.databinding.DataBinding; +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.BaseTransformer; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.FaultExceptionMapper; + +/** + * This is a special transformer to transform the exception from one IDL to the + * other one + * + * @version $Rev$ $Date$ + */ +public class Exception2ExceptionTransformer extends BaseTransformer<Throwable, Throwable> implements + PullTransformer<Throwable, Throwable> { + + protected Mediator mediator; + protected FaultExceptionMapper faultExceptionMapper; + + public Exception2ExceptionTransformer(ExtensionPointRegistry registry) { + super(); + UtilityExtensionPoint utilityExtensionPoint = registry.getExtensionPoint(UtilityExtensionPoint.class); + this.mediator = utilityExtensionPoint.getUtility(Mediator.class); + this.faultExceptionMapper = utilityExtensionPoint.getUtility(FaultExceptionMapper.class); + } + + protected Exception2ExceptionTransformer(Mediator mediator, FaultExceptionMapper faultExceptionMapper) { + super(); + this.mediator = mediator; + this.faultExceptionMapper = faultExceptionMapper; + } + + @Override + public String getSourceDataBinding() { + return DataBinding.IDL_FAULT; + } + + @Override + public String getTargetDataBinding() { + return DataBinding.IDL_FAULT; + } + + /** + * @see org.apache.tuscany.sca.databinding.BaseTransformer#getSourceType() + */ + @Override + protected Class<Throwable> getSourceType() { + return Throwable.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.BaseTransformer#getTargetType() + */ + @Override + protected Class<Throwable> getTargetType() { + return Throwable.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.Transformer#getWeight() + */ + @Override + public int getWeight() { + return 10000; + } + + @SuppressWarnings("unchecked") + public Throwable transform(Throwable source, TransformationContext context) { + DataType<DataType> sourceType = context.getSourceDataType(); + + DataType<DataType> targetType = context.getTargetDataType(); + + Object sourceFaultInfo = faultExceptionMapper.getFaultInfo(source, sourceType.getLogical().getPhysical(), context.getSourceOperation()); + Object targetFaultInfo = + mediator.mediate(sourceFaultInfo, sourceType.getLogical(), targetType.getLogical(), context.getMetadata()); + + Throwable targetException = + faultExceptionMapper.wrapFaultInfo(targetType, source.getMessage(), targetFaultInfo, source.getCause(), context.getTargetOperation()); + + // FIXME + return targetException == null ? source : targetException; + + } + + public void setFaultExceptionMapper(FaultExceptionMapper faultExceptionMapper) { + this.faultExceptionMapper = faultExceptionMapper; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Input2InputTransformer.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Input2InputTransformer.java new file mode 100644 index 0000000000..2efc3578bd --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Input2InputTransformer.java @@ -0,0 +1,270 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.databinding.transformers; + +import java.util.List; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.databinding.DataBinding; +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.WrapperHandler; +import org.apache.tuscany.sca.databinding.BaseTransformer; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.ElementInfo; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * This is a special transformer to transform the input from one IDL to the + * other one + * + * @version $Rev$ $Date$ + */ +public class Input2InputTransformer extends BaseTransformer<Object[], Object[]> implements + PullTransformer<Object[], Object[]> { + protected Mediator mediator; + + public Input2InputTransformer(ExtensionPointRegistry registry) { + super(); + this.mediator = registry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(Mediator.class); + } + + @Override + public String getSourceDataBinding() { + return DataBinding.IDL_INPUT; + } + + @Override + public String getTargetDataBinding() { + return DataBinding.IDL_INPUT; + } + + /** + * @see org.apache.tuscany.sca.databinding.BaseTransformer#getSourceType() + */ + @Override + protected Class<Object[]> getSourceType() { + return Object[].class; + } + + /** + * @see org.apache.tuscany.sca.databinding.BaseTransformer#getTargetType() + */ + @Override + protected Class<Object[]> getTargetType() { + return Object[].class; + } + + /** + * @see org.apache.tuscany.sca.databinding.Transformer#getWeight() + */ + @Override + public int getWeight() { + return 10000; + } + + /** + * Match the structure of the wrapper element. If it matches, then we can do + * wrapper to wrapper transformation. Otherwise, we do child to child. + * @param w1 + * @param w2 + * @return + */ + private boolean matches(WrapperInfo w1, WrapperInfo w2) { + if (w1 == null || w2 == null) { + return false; + } + if (!w1.getInputWrapperElement().equals(w2.getInputWrapperElement())) { + return false; + } + + // Compare the child elements + List<ElementInfo> list1 = w1.getInputChildElements(); + List<ElementInfo> list2 = w2.getInputChildElements(); + if (list1.size() != list2.size()) { + return false; + } + // FXIME: [rfeng] At this point, the J2W generates local elments under the namespace + // of the interface instead of "". We only compare the local parts only to work around + // the namespace mismatch + for (int i = 0; i < list1.size(); i++) { + String n1 = list1.get(i).getQName().getLocalPart(); + String n2 = list2.get(i).getQName().getLocalPart(); + if (!n1.equals(n2)) { + return false; + } + } + return true; + } + + @SuppressWarnings("unchecked") + public Object[] transform(Object[] source, TransformationContext context) { + // Check if the source operation is wrapped + DataType<List<DataType>> sourceType = context.getSourceDataType(); + Operation sourceOp = context.getSourceOperation(); + boolean sourceWrapped = sourceOp != null && sourceOp.isWrapperStyle() && sourceOp.getWrapper() != null; + boolean sourceBare = sourceOp != null && !sourceOp.isWrapperStyle() && sourceOp.getWrapper() == null; + + // Find the wrapper handler for source data + WrapperHandler sourceWrapperHandler = null; + String sourceDataBinding = getDataBinding(sourceOp); + sourceWrapperHandler = getWrapperHandler(sourceDataBinding, sourceWrapped); + + // Check if the target operation is wrapped + DataType<List<DataType>> targetType = context.getTargetDataType(); + Operation targetOp = (Operation)context.getTargetOperation(); + boolean targetWrapped = targetOp != null && targetOp.isWrapperStyle() && targetOp.getWrapper() != null; + boolean targetBare = targetOp != null && !targetOp.isWrapperStyle() && targetOp.getWrapper() == null; + + // Find the wrapper handler for target data + WrapperHandler targetWrapperHandler = null; + String targetDataBinding = getDataBinding(targetOp); + targetWrapperHandler = getWrapperHandler(targetDataBinding, targetWrapped); + + if ((!sourceWrapped && !sourceBare) && targetWrapped) { + // Unwrapped --> Wrapped + WrapperInfo wrapper = targetOp.getWrapper(); + // ElementInfo wrapperElement = wrapper.getInputWrapperElement(); + + // Class<?> targetWrapperClass = wrapper != null ? wrapper.getInputWrapperClass() : null; + + if (source == null) { + // Empty child elements + Object targetWrapper = targetWrapperHandler.create(targetOp, true); + return new Object[] {targetWrapper}; + } + + // If the source can be wrapped, wrapped it first + if (sourceWrapperHandler != null) { + WrapperInfo sourceWrapperInfo = sourceOp.getWrapper(); + DataType sourceWrapperType = sourceWrapperInfo != null ? sourceWrapperInfo.getInputWrapperType() : null; + + // We only do wrapper to wrapper transformation if the source has a wrapper and both sides + // match by XML structure + if (sourceWrapperType != null && matches(sourceOp.getWrapper(), targetOp.getWrapper())) { + Class<?> sourceWrapperClass = sourceWrapperType.getPhysical(); + + // Create the source wrapper + Object sourceWrapper = sourceWrapperHandler.create(sourceOp, true); + + // Populate the source wrapper + if (sourceWrapper != null) { + sourceWrapperHandler.setChildren(sourceWrapper, + source, + sourceOp, + true); + + // Transform the data from source wrapper to target wrapper + Object targetWrapper = + mediator.mediate(sourceWrapper, sourceWrapperType, targetType.getLogical().get(0), context + .getMetadata()); + return new Object[] {targetWrapper}; + } + } + } + // Fall back to child by child transformation + Object targetWrapper = targetWrapperHandler.create(targetOp, true); + List<DataType> argTypes = wrapper.getUnwrappedInputType().getLogical(); + Object[] targetChildren = new Object[source.length]; + for (int i = 0; i < source.length; i++) { + // ElementInfo argElement = wrapper.getInputChildElements().get(i); + DataType<XMLType> argType = argTypes.get(i); + targetChildren[i] = + mediator.mediate(source[i], sourceType.getLogical().get(i), argType, context.getMetadata()); + } + targetWrapperHandler.setChildren(targetWrapper, + targetChildren, + targetOp, + true); + return new Object[] {targetWrapper}; + + } else if (sourceWrapped && (!targetWrapped && !targetBare)) { + // Wrapped to Unwrapped + Object sourceWrapper = source[0]; + Object[] target = null; + + // List<ElementInfo> childElements = sourceOp.getWrapper().getInputChildElements(); + if (targetWrapperHandler != null) { + // ElementInfo wrapperElement = sourceOp.getWrapper().getInputWrapperElement(); + // FIXME: This is a workaround for the wsdless support as it passes in child elements + // under the wrapper that only matches by position + if (sourceWrapperHandler.isInstance(sourceWrapper, sourceOp, true)) { + + WrapperInfo targetWrapperInfo = targetOp.getWrapper(); + DataType targetWrapperType = + targetWrapperInfo != null ? targetWrapperInfo.getInputWrapperType() : null; + if (targetWrapperType != null && matches(sourceOp.getWrapper(), targetOp.getWrapper())) { + Object targetWrapper = + mediator.mediate(sourceWrapper, sourceType.getLogical().get(0), targetWrapperType, context + .getMetadata()); + target = targetWrapperHandler.getChildren(targetWrapper, targetOp, true).toArray(); + return target; + } + } + } + Object[] sourceChildren = sourceWrapperHandler.getChildren(sourceWrapper, sourceOp, true).toArray(); + target = new Object[sourceChildren.length]; + for (int i = 0; i < sourceChildren.length; i++) { + DataType<XMLType> childType = sourceOp.getWrapper().getUnwrappedInputType().getLogical().get(i); + target[i] = + mediator.mediate(sourceChildren[i], childType, targetType.getLogical().get(i), context + .getMetadata()); + } + return target; + } else { + // Assuming wrapper to wrapper conversion can be handled here as well + Object[] newArgs = new Object[source.length]; + for (int i = 0; i < source.length; i++) { + Object child = + mediator.mediate(source[i], sourceType.getLogical().get(i), targetType.getLogical().get(i), context + .getMetadata()); + newArgs[i] = child; + } + return newArgs; + } + } + + private WrapperHandler getWrapperHandler(String dataBindingId, boolean required) { + WrapperHandler wrapperHandler = null; + if (dataBindingId != null) { + DataBinding dataBinding = mediator.getDataBindings().getDataBinding(dataBindingId); + wrapperHandler = dataBinding == null ? null : dataBinding.getWrapperHandler(); + } + if (wrapperHandler == null && required) { + throw new TransformationException("No wrapper handler is provided for databinding: " + dataBindingId); + } + return wrapperHandler; + } + + private String getDataBinding(Operation operation) { + WrapperInfo wrapper = operation.getWrapper(); + if (wrapper != null) { + return wrapper.getDataBinding(); + } else { + return null; + } + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Map2MapTransformer.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Map2MapTransformer.java new file mode 100644 index 0000000000..5be7ba1da4 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Map2MapTransformer.java @@ -0,0 +1,108 @@ +/* + * 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.core.databinding.transformers; + +import java.util.Map; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.databinding.BaseTransformer; +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.interfacedef.DataType; + +/** + * This is a special transformer to transform the output from one IDL to the + * other one + * + * @version $Rev$ $Date$ + */ +public class Map2MapTransformer extends BaseTransformer<Map, Map> implements PullTransformer<Map, Map> { + + private static final String JAVA_MAP = "java:map"; + protected Mediator mediator; + + public Map2MapTransformer(ExtensionPointRegistry registry) { + super(); + this.mediator = registry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(Mediator.class); + } + + @Override + public String getSourceDataBinding() { + return JAVA_MAP; + } + + @Override + public String getTargetDataBinding() { + return JAVA_MAP; + } + + /** + * @see org.apache.tuscany.sca.databinding.BaseTransformer#getSourceType() + */ + @Override + protected Class<Map> getSourceType() { + return Map.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.BaseTransformer#getTargetType() + */ + @Override + protected Class<Map> getTargetType() { + return Map.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.Transformer#getWeight() + */ + @Override + public int getWeight() { + return 10; + } + + @SuppressWarnings("unchecked") + public Map transform(Map sourceMap, TransformationContext context) { + try { + if (sourceMap == null) { + return null; + } + DataType<DataType> sourceType = context.getSourceDataType(); + DataType<DataType> targetType = context.getTargetDataType(); + Map targetMap = createMap(targetType.getPhysical()); + for (Object sourceItem : sourceMap.entrySet()) { + Map.Entry entry = (Map.Entry)sourceItem; + Object targetValue = + mediator.mediate(entry.getValue(), sourceType.getLogical(), targetType.getLogical(), context + .getMetadata()); + targetMap.put(entry.getKey(), targetValue); + } + return targetMap; + } catch (Exception e) { + throw new TransformationException(e); + } + } + + private Map createMap(Class<?> collectionClass) throws Exception { + return (Map)collectionClass.newInstance(); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Output2OutputTransformer.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Output2OutputTransformer.java new file mode 100644 index 0000000000..71dcc654eb --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/transformers/Output2OutputTransformer.java @@ -0,0 +1,251 @@ +/* + * 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.core.databinding.transformers; + +import java.util.List; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.databinding.DataBinding; +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.WrapperHandler; +import org.apache.tuscany.sca.databinding.BaseTransformer; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.ElementInfo; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * This is a special transformer to transform the output from one IDL to the + * other one + * + * @version $Rev$ $Date$ + */ +public class Output2OutputTransformer extends BaseTransformer<Object, Object> implements + PullTransformer<Object, Object> { + + protected Mediator mediator; + + /** + * @param wrapperHandler + */ + public Output2OutputTransformer(ExtensionPointRegistry registry) { + super(); + this.mediator = registry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(Mediator.class); + } + + @Override + public String getSourceDataBinding() { + return DataBinding.IDL_OUTPUT; + } + + @Override + public String getTargetDataBinding() { + return DataBinding.IDL_OUTPUT; + } + + /** + * @see org.apache.tuscany.sca.databinding.BaseTransformer#getSourceType() + */ + @Override + protected Class<Object> getSourceType() { + return Object.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.BaseTransformer#getTargetType() + */ + @Override + protected Class<Object> getTargetType() { + return Object.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.Transformer#getWeight() + */ + @Override + public int getWeight() { + return 10; + } + + private String getDataBinding(Operation operation) { + WrapperInfo wrapper = operation.getWrapper(); + if (wrapper != null) { + return wrapper.getDataBinding(); + } else { + return null; + } + } + + private WrapperHandler getWrapperHandler(String dataBindingId, boolean required) { + WrapperHandler wrapperHandler = null; + if (dataBindingId != null) { + DataBinding dataBinding = mediator.getDataBindings().getDataBinding(dataBindingId); + wrapperHandler = dataBinding == null ? null : dataBinding.getWrapperHandler(); + } + if (wrapperHandler == null && required) { + throw new TransformationException("No wrapper handler is provided for databinding: " + dataBindingId); + } + return wrapperHandler; + } + + /** + * Match the structure of the wrapper element. If it matches, then we can do + * wrapper to wrapper transformation. Otherwise, we do child to child. + * @param w1 + * @param w2 + * @return + */ + private boolean matches(WrapperInfo w1, WrapperInfo w2) { + if (w1 == null || w2 == null) { + return false; + } + if (!w1.getOutputWrapperElement().equals(w2.getOutputWrapperElement())) { + return false; + } + + // Compare the child elements + List<ElementInfo> list1 = w1.getOutputChildElements(); + List<ElementInfo> list2 = w2.getOutputChildElements(); + if (list1.size() != list2.size()) { + return false; + } + // FXIME: [rfeng] At this point, the J2W generates local elments under the namespace + // of the interface instead of "". We only compare the local parts only to work around + // the namespace mismatch + for (int i = 0; i < list1.size(); i++) { + String n1 = list1.get(i).getQName().getLocalPart(); + String n2 = list2.get(i).getQName().getLocalPart(); + if (!n1.equals(n2)) { + return false; + } + } + return true; + } + + @SuppressWarnings("unchecked") + public Object transform(Object response, TransformationContext context) { + try { + DataType<DataType> sourceType = context.getSourceDataType(); + Operation sourceOp = context.getSourceOperation(); + boolean sourceWrapped = sourceOp != null && sourceOp.isWrapperStyle() && sourceOp.getWrapper() != null; + boolean sourceBare = sourceOp != null && !sourceOp.isWrapperStyle() && sourceOp.getWrapper() == null; + + WrapperHandler sourceWrapperHandler = null; + String sourceDataBinding = getDataBinding(sourceOp); + sourceWrapperHandler = getWrapperHandler(sourceDataBinding, sourceWrapped); + + DataType<DataType> targetType = context.getTargetDataType(); + Operation targetOp = (Operation)context.getTargetOperation(); + boolean targetWrapped = targetOp != null && targetOp.isWrapperStyle() && targetOp.getWrapper() != null; + boolean targetBare = targetOp != null && !targetOp.isWrapperStyle() && targetOp.getWrapper() == null; + + WrapperHandler targetWrapperHandler = null; + String targetDataBinding = getDataBinding(targetOp); + targetWrapperHandler = getWrapperHandler(targetDataBinding, targetWrapped); + + if ((!sourceWrapped &&!sourceBare) && targetWrapped) { + // Unwrapped --> Wrapped + WrapperInfo wrapper = targetOp.getWrapper(); + ElementInfo wrapperElement = wrapper.getOutputWrapperElement(); + List<ElementInfo> childElements = wrapper.getOutputChildElements(); + Class<?> targetWrapperClass = wrapper != null ? wrapper.getOutputWrapperClass() : null; + + // If the source can be wrapped, wrapped it first + if (sourceWrapperHandler != null) { + WrapperInfo sourceWrapperInfo = sourceOp.getWrapper(); + DataType sourceWrapperType = + sourceWrapperInfo != null ? sourceWrapperInfo.getOutputWrapperType() : null; + + if (sourceWrapperType != null && matches(sourceOp.getWrapper(), targetOp.getWrapper())) { + Class<?> sourceWrapperClass = sourceWrapperType.getPhysical(); + + Object sourceWrapper = sourceWrapperHandler.create(sourceOp, false); + if (sourceWrapper != null) { + if (!childElements.isEmpty()) { + // Set the return value + sourceWrapperHandler.setChildren(sourceWrapper, + new Object[] {response}, + sourceOp, + false); + } + Object targetWrapper = + mediator.mediate(sourceWrapper, sourceWrapperType, targetType.getLogical(), context + .getMetadata()); + return targetWrapper; + } + } + } + Object targetWrapper = targetWrapperHandler.create(targetOp, false); + + if (childElements.isEmpty()) { + // void output + return targetWrapper; + } + + DataType<XMLType> argType = wrapper.getUnwrappedOutputType(); + Object child = response; + child = mediator.mediate(response, sourceType.getLogical(), argType, context.getMetadata()); + targetWrapperHandler.setChildren(targetWrapper, new Object[] {child}, targetOp, false); + return targetWrapper; + } else if (sourceWrapped && (!targetWrapped && !targetBare)) { + // Wrapped to Unwrapped + Object sourceWrapper = response; + List<ElementInfo> childElements = sourceOp.getWrapper().getOutputChildElements(); + if (childElements.isEmpty()) { + // The void output + return null; + } + if (targetWrapperHandler != null) { + ElementInfo wrapperElement = sourceOp.getWrapper().getOutputWrapperElement(); + + // FIXME: This is a workaround for the wsdless support as it passes in child elements + // under the wrapper that only matches by position + if (sourceWrapperHandler.isInstance(sourceWrapper, sourceOp, false)) { + + WrapperInfo targetWrapperInfo = targetOp.getWrapper(); + DataType targetWrapperType = + targetWrapperInfo != null ? targetWrapperInfo.getOutputWrapperType() : null; + + if (targetWrapperType != null && matches(sourceOp.getWrapper(), targetOp.getWrapper())) { + Object targetWrapper = + mediator.mediate(sourceWrapper, sourceType.getLogical(), targetWrapperType, context + .getMetadata()); + return targetWrapperHandler.getChildren(targetWrapper, targetOp, false).get(0); + } + } + } + Object child = sourceWrapperHandler.getChildren(sourceWrapper, sourceOp, false).get(0); + DataType<?> childType = sourceOp.getWrapper().getUnwrappedOutputType(); + return mediator.mediate(child, childType, targetType.getLogical(), context.getMetadata()); + } else { + // FIXME: Do we want to handle wrapped to wrapped? + return mediator.mediate(response, sourceType.getLogical(), targetType.getLogical(), context + .getMetadata()); + } + } catch (Exception e) { + throw new TransformationException(e); + } + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataBindingRuntimeWireProcessor.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataBindingRuntimeWireProcessor.java new file mode 100644 index 0000000000..0e615519f1 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataBindingRuntimeWireProcessor.java @@ -0,0 +1,184 @@ +/* + * 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.core.databinding.wire; + +import java.util.List; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Interceptor; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Phase; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessor; + +/** + * This processor is responsible to add an interceptor to invocation chain if + * the source and target operations have different databinding requirements + * + * @version $Rev$ $Date$ + */ +public class DataBindingRuntimeWireProcessor implements RuntimeWireProcessor { + private Mediator mediator; + + public DataBindingRuntimeWireProcessor(ExtensionPointRegistry registry) { + super(); + this.mediator = registry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(Mediator.class); + } + + public boolean isTransformationRequired(DataType source, DataType target) { + if (source == null || target == null) { // void return type + return false; + } + if (source == target) { + return false; + } + + // Output type can be null + if (source == null && target == null) { + return false; + } else if (source == null || target == null) { + return true; + } + String sourceDataBinding = source.getDataBinding(); + String targetDataBinding = target.getDataBinding(); + if (sourceDataBinding == targetDataBinding) { + return false; + } + if (sourceDataBinding == null || targetDataBinding == null) { + // TODO: If any of the databinding is null, then no transformation + return false; + } + return !sourceDataBinding.equals(targetDataBinding); + } + + public boolean isTransformationRequired(Operation source, Operation target) { + if (source == target) { + return false; + } + + if (source.isWrapperStyle() != target.isWrapperStyle()) { + return true; + } + + // Check output type + DataType sourceOutputType = source.getOutputType(); + DataType targetOutputType = target.getOutputType(); + + // Note the target output type is now the source for checking + // compatibility + if (isTransformationRequired(targetOutputType, sourceOutputType)) { + return true; + } + + List<DataType> sourceInputType = source.getInputType().getLogical(); + List<DataType> targetInputType = target.getInputType().getLogical(); + + int size = sourceInputType.size(); + if (size != targetInputType.size()) { + // TUSCANY-1682: The wrapper style may have different arguments + return true; + } + for (int i = 0; i < size; i++) { + if (isTransformationRequired(sourceInputType.get(i), targetInputType.get(i))) { + return true; + } + } + + return false; + } + + private boolean isTransformationRequired(InterfaceContract sourceContract, + Operation sourceOperation, + InterfaceContract targetContract, + Operation targetOperation) { + if (targetContract == null) { + targetContract = sourceContract; + } + if (sourceContract == targetContract) { + return false; + } + return isTransformationRequired(sourceOperation, targetOperation); + } + + public void process(RuntimeEndpoint endpoint) { + InterfaceContract sourceContract = endpoint.getBindingInterfaceContract(); + InterfaceContract targetContract = endpoint.getComponentTypeServiceInterfaceContract(); + if (targetContract == null) { + targetContract = sourceContract; + } + + if (!sourceContract.getInterface().isRemotable()) { + return; + } + List<InvocationChain> chains = endpoint.getInvocationChains(); + for (InvocationChain chain : chains) { + Operation sourceOperation = chain.getSourceOperation(); + Operation targetOperation = chain.getTargetOperation(); + + Interceptor interceptor = null; + if (isTransformationRequired(sourceContract, sourceOperation, targetContract, targetOperation)) { + // Add the interceptor to the source side because multiple + // references can be wired to the same service + interceptor = new DataTransformationInterceptor(endpoint, sourceOperation, targetOperation, mediator); + } + if (interceptor != null) { + String phase = Phase.SERVICE_INTERFACE; + chain.addInterceptor(phase, interceptor); + } + } + + } + + public void process(RuntimeEndpointReference endpointReference) { + InterfaceContract sourceContract = endpointReference.getComponentTypeReferenceInterfaceContract(); + InterfaceContract targetContract = endpointReference.getBindingInterfaceContract(); + if (targetContract == null) { + targetContract = sourceContract; + } + + if (sourceContract == null || !sourceContract.getInterface().isRemotable()) { + return; + } + List<InvocationChain> chains = endpointReference.getInvocationChains(); + for (InvocationChain chain : chains) { + Operation sourceOperation = chain.getSourceOperation(); + Operation targetOperation = chain.getTargetOperation(); + + Interceptor interceptor = null; + if (isTransformationRequired(sourceContract, sourceOperation, targetContract, targetOperation)) { + // Add the interceptor to the source side because multiple + // references can be wired to the same service + interceptor = new DataTransformationInterceptor(endpointReference, sourceOperation, targetOperation, mediator); + } + if (interceptor != null) { + String phase = Phase.REFERENCE_INTERFACE; + chain.addInterceptor(phase, interceptor); + } + } + + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java new file mode 100644 index 0000000000..de29088c1d --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java @@ -0,0 +1,98 @@ +/* + * 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.core.databinding.wire; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Interceptor; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.Invocable; + +/** + * An interceptor to transform data across databindings on the wire + * + * @version $Rev$ $Date$ + */ +public class DataTransformationInterceptor implements Interceptor { + private Invoker next; + + private Operation sourceOperation; + + private Operation targetOperation; + private Invocable invocable; + private Mediator mediator; + + public DataTransformationInterceptor(Invocable invocable, + Operation sourceOperation, + Operation targetOperation, + Mediator mediator) { + super(); + this.sourceOperation = sourceOperation; + this.targetOperation = targetOperation; + this.mediator = mediator; + this.invocable = invocable; + } + + public Invoker getNext() { + return next; + } + + public Message invoke(Message msg) { + Map<String, Object> metadata = new HashMap<String, Object>(); + metadata.put(Invocable.class.getName(), invocable); + Object input = mediator.mediateInput(msg.getBody(), sourceOperation, targetOperation, metadata); + msg.setBody(input); + Message resultMsg = next.invoke(msg); + Object result = resultMsg.getBody(); + if (sourceOperation.isNonBlocking()) { + // Not to reset the message body + return resultMsg; + } + + if (resultMsg.isFault()) { + Object transformedFault = null; + if ((result instanceof Exception) && !(result instanceof RuntimeException)) { + transformedFault = mediator.mediateFault(result, sourceOperation, targetOperation, metadata); + if (transformedFault != result) { + resultMsg.setFaultBody(transformedFault); + } + } + // + // Leave it to another layer to actually throw the Exception which constitutes + // the message body. We don't throw it here. + // + } else { + assert !(result instanceof Throwable) : "Expected messages that are not throwable " + result; + Object newResult = mediator.mediateOutput(result, sourceOperation, targetOperation, metadata); + resultMsg.setBody(newResult); + } + + return resultMsg; + } + + public void setNext(Invoker next) { + this.next = next; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/PassByValueInterceptor.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/PassByValueInterceptor.java new file mode 100644 index 0000000000..44e5072e61 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/PassByValueInterceptor.java @@ -0,0 +1,80 @@ +/* + * 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.core.databinding.wire; + +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Interceptor; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; + +/** + * Implementation of an interceptor that enforces pass-by-value semantics + * on operation invocations by copying the operation input and output data. + * + * @version $Rev$ $Date$ + */ +public class PassByValueInterceptor implements Interceptor { + + private Mediator mediator; + private Operation operation; + private Invoker nextInvoker; + private InvocationChain chain; + + /** + * Constructs a new PassByValueInterceptor. + * @param dataBindings databinding extension point + * @param operation the intercepted operation + */ + public PassByValueInterceptor(Mediator mediator, InvocationChain chain, Operation operation) { + this.mediator = mediator; + this.chain = chain; + this.operation = operation; + } + + public Message invoke(Message msg) { + if (chain.allowsPassByReference()) { + return nextInvoker.invoke(msg); + } + + msg.setBody(mediator.copyInput(msg.getBody(), operation)); + + Message resultMsg = nextInvoker.invoke(msg); + + if (!resultMsg.isFault() && operation.getOutputType() != null) { + resultMsg.setBody(mediator.copyOutput(resultMsg.getBody(), operation)); + } + + if (resultMsg.isFault()) { + resultMsg.setFaultBody(mediator.copyFault(resultMsg.getBody(), operation)); + } + return resultMsg; + } + + public Invoker getNext() { + return nextInvoker; + } + + public void setNext(Invoker next) { + this.nextInvoker = next; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer new file mode 100644 index 0000000000..a1f5d37ff3 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer @@ -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.
+
+# Implementation classes for special transformers
+#
+# Java array --> Java array
+org.apache.tuscany.sca.core.databinding.transformers.Array2ArrayTransformer;source=java:array,target=java:array,weight=10,public=false
+# Java exception --> Java exception
+org.apache.tuscany.sca.core.databinding.transformers.Exception2ExceptionTransformer;source=idl:fault,target=idl:fault,weight=10,public=false
+# Input to Input
+org.apache.tuscany.sca.core.databinding.transformers.Input2InputTransformer;source=idl:input,target=idl:input,weight=10,public=false
+# Output to Output
+org.apache.tuscany.sca.core.databinding.transformers.Output2OutputTransformer;source=idl:output,target=idl:output,weight=10,public=false
+# Group to Group
+org.apache.tuscany.sca.databinding.impl.Group2GroupTransformer;source=databinding:group,target=databinding:group,weight=10,public=false
+
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor new file mode 100644 index 0000000000..875814fccc --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor @@ -0,0 +1,19 @@ +# 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. + +org.apache.tuscany.sca.core.databinding.processor.DataBindingJavaInterfaceProcessor;ranking=300 +org.apache.tuscany.sca.core.databinding.processor.WrapperJavaInterfaceProcessor;ranking=200
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.RuntimeWireProcessor b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.RuntimeWireProcessor new file mode 100644 index 0000000000..dfd86a3a53 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-databinding/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.RuntimeWireProcessor @@ -0,0 +1,17 @@ +# 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.
+org.apache.tuscany.sca.core.databinding.wire.DataBindingRuntimeWireProcessor
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/LICENSE b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/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/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/META-INF/MANIFEST.MF b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..1ae10356d5 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/META-INF/MANIFEST.MF @@ -0,0 +1,48 @@ +Manifest-Version: 1.0
+Export-Package: org.apache.tuscany.sca.context;version="2.0.0";
+ uses:="org.apache.tuscany.sca.runtime,
+ org.apache.tuscany.sca.assembly,
+ org.apache.tuscany.sca.core,
+ org.oasisopen.sca,
+ org.apache.tuscany.sca.extensibility",
+ org.apache.tuscany.sca.invocation;version="2.0.0";uses:="org.apache.tuscany.sca.runtime,org.apache.tuscany.sca.interfacedef",
+ org.apache.tuscany.sca.management;version="2.0.0";uses:="org.apache.tuscany.sca.runtime",
+ org.apache.tuscany.sca.provider;version="2.0.0";
+ uses:="org.apache.tuscany.sca.invocation,
+ org.apache.tuscany.sca.runtime,
+ org.apache.tuscany.sca.assembly,
+ org.apache.tuscany.sca.definitions,
+ org.apache.tuscany.sca.core,
+ org.apache.tuscany.sca.interfacedef,
+ org.apache.tuscany.sca.extensibility",
+ org.apache.tuscany.sca.runtime;version="2.0.0";
+ uses:="org.apache.tuscany.sca.invocation,
+ org.apache.tuscany.sca.assembly,
+ org.apache.tuscany.sca.endpointresolver,
+ org.apache.tuscany.sca.provider,
+ org.oasisopen.sca,
+ org.apache.tuscany.sca.interfacedef",
+ org.apache.tuscany.sca.work;version="2.0.0"
+SCA-Version: 1.1
+Bundle-Name: Apache Tuscany SCA Core SPI
+Bundle-Vendor: The Apache Software Foundation
+Bundle-Version: 2.0.0
+Bundle-ManifestVersion: 2
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-Description: Apache Tuscany SCA Core SPI
+Import-Package: org.apache.tuscany.sca.assembly;version="2.0.0",
+ org.apache.tuscany.sca.context;version="2.0.0",
+ org.apache.tuscany.sca.core;version="2.0.0",
+ org.apache.tuscany.sca.definitions;version="2.0.0",
+ org.apache.tuscany.sca.extensibility;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef;version="2.0.0",
+ org.apache.tuscany.sca.invocation;version="2.0.0",
+ org.apache.tuscany.sca.management;version="2.0.0",
+ org.apache.tuscany.sca.policy;version="2.0.0",
+ org.apache.tuscany.sca.provider;version="2.0.0",
+ org.apache.tuscany.sca.runtime;version="2.0.0",
+ org.apache.tuscany.sca.work;version="2.0.0",
+ org.oasisopen.sca;version="2.0.0"
+Bundle-SymbolicName: org.apache.tuscany.sca.core.spi
+Bundle-DocURL: http://www.apache.org/
+Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/NOTICE b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/NOTICE new file mode 100644 index 0000000000..ad2ba40961 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2010 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/pom.xml b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/pom.xml new file mode 100644 index 0000000000..091cde88c3 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/pom.xml @@ -0,0 +1,118 @@ +<?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>2.0-Beta1-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-core-spi</artifactId> + <name>Apache Tuscany SCA Core SPI</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-extensibility</artifactId> + <version>2.0-Beta1-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-sca-api</artifactId> + <version>2.0-Beta1-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-assembly</artifactId> + <version>2.0-Beta1-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-contribution</artifactId> + <version>2.0-Beta1-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.codehaus.woodstox</groupId> + <artifactId>wstx-asl</artifactId> + <version>3.2.4</version> + <scope>runtime</scope> + <exclusions> + <exclusion> + <groupId>stax</groupId> + <artifactId>stax-api</artifactId> + </exclusion> + </exclusions> + </dependency> + + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>buildnumber-maven-plugin</artifactId> + <version>1.0-beta-4</version> + <executions> + <execution> + <phase>validate</phase> + <goals> + <goal>create</goal> + </goals> + </execution> + </executions> + <configuration> + <buildNumberPropertyName>sources.version</buildNumberPropertyName> + <timestampPropertyName>build.timestamp</timestampPropertyName> + <doCheck>false</doCheck> + <doUpdate>true</doUpdate> + <revisionOnScmFailure>00000</revisionOnScmFailure> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-antrun-plugin</artifactId> + <executions> + <execution> + <id>process-resources</id> + <phase>process-resources</phase> + <configuration> + <tasks> + <filter token="version" value="${pom.version}"/> + <filter token="svnRevision" value="${sources.version}"/> + <filter token="buildtime" value="${build.timestamp}"/> + <copy toDir="${basedir}/target/classes/org/apache/tuscany/sca/runtime" overwrite="true" + filtering="on" file="${basedir}/src/main/resources/org/apache/tuscany/sca/runtime/revision.properties"/> + </tasks> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + +</project> diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/doc/Context Model.emx b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/doc/Context Model.emx new file mode 100644 index 0000000000..0445ea5a6b --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/doc/Context Model.emx @@ -0,0 +1,673 @@ +<?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.
+-->
+<!--xtools2_universal_type_manager-->
+<uml:Model xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:notation="http://www.ibm.com/xtools/1.5.0/Notation" xmlns:uml="http://www.eclipse.org/uml2/1.0.0/UML" xmlns:umlnotation="http://www.ibm.com/xtools/1.5.0/Umlnotation" xmi:id="_al1S8NovEdqRBPR5WyT36A" name="Context Model" appliedProfile="_al1S9NovEdqRBPR5WyT36A _al1S99ovEdqRBPR5WyT36A _al1S-tovEdqRBPR5WyT36A _al1S_dovEdqRBPR5WyT36A _al1TANovEdqRBPR5WyT36A">
+ <eAnnotations xmi:id="_al1S8dovEdqRBPR5WyT36A" source="uml2.diagrams" references="_al1S8tovEdqRBPR5WyT36A">
+ <contents xmi:type="notation:Diagram" xmi:id="_al1S8tovEdqRBPR5WyT36A" type="Class" name="Main">
+ <children xmi:id="_ePDcYdovEdqRBPR5WyT36A" sourceEdges="_Fd3lQdowEdqRBPR5WyT36A _R5Rjwdo1EdqRBPR5WyT36A _pdfmkNo2EdqRBPR5WyT36A" targetEdges="_hmIF4dovEdqRBPR5WyT36A _mu9A4dovEdqRBPR5WyT36A _pe3jwNovEdqRBPR5WyT36A" element="_ePDcYNovEdqRBPR5WyT36A">
+ <children xmi:id="_ePJjANovEdqRBPR5WyT36A" type="ImageCompartment" element="_ePDcYNovEdqRBPR5WyT36A">
+ <layoutConstraint xmi:type="notation:Size" xmi:id="_ePJjAdovEdqRBPR5WyT36A" width="530" height="530"/>
+ </children>
+ <children xmi:id="_ePJjAtovEdqRBPR5WyT36A" type="Stereotype" element="_ePDcYNovEdqRBPR5WyT36A"/>
+ <children xmi:id="_ePJjA9ovEdqRBPR5WyT36A" type="Kind" element="_ePDcYNovEdqRBPR5WyT36A"/>
+ <children xmi:id="_ePJjBNovEdqRBPR5WyT36A" type="Name" element="_ePDcYNovEdqRBPR5WyT36A"/>
+ <children xmi:id="_ePJjBdovEdqRBPR5WyT36A" type="AttributeCompartment" element="_ePDcYNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_ePJjBtovEdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_ePJjB9ovEdqRBPR5WyT36A" type="OperationCompartment" element="_ePDcYNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_ePJjCNovEdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_ePJjCdovEdqRBPR5WyT36A" visible="false" type="SignalCompartment" element="_ePDcYNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_ePJjCtovEdqRBPR5WyT36A"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLClassifierStyle" xmi:id="_ePDcYtovEdqRBPR5WyT36A" showStereotype="Label" useClassifierShape="true"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_ePDcY9ovEdqRBPR5WyT36A" x="6693" y="3545"/>
+ </children>
+ <children xmi:id="_fs1pANovEdqRBPR5WyT36A" sourceEdges="_hmIF4dovEdqRBPR5WyT36A _pe3jwNovEdqRBPR5WyT36A" targetEdges="_xInjYdovEdqRBPR5WyT36A" element="_fsviYNovEdqRBPR5WyT36A">
+ <children xmi:id="_fs1pA9ovEdqRBPR5WyT36A" type="ImageCompartment" element="_fsviYNovEdqRBPR5WyT36A">
+ <layoutConstraint xmi:type="notation:Size" xmi:id="_fs1pBNovEdqRBPR5WyT36A" width="530" height="530"/>
+ </children>
+ <children xmi:id="_fs1pBdovEdqRBPR5WyT36A" type="Stereotype" element="_fsviYNovEdqRBPR5WyT36A"/>
+ <children xmi:id="_fs1pBtovEdqRBPR5WyT36A" type="Kind" element="_fsviYNovEdqRBPR5WyT36A"/>
+ <children xmi:id="_fs1pB9ovEdqRBPR5WyT36A" type="Name" element="_fsviYNovEdqRBPR5WyT36A"/>
+ <children xmi:id="_fs1pCNovEdqRBPR5WyT36A" type="AttributeCompartment" element="_fsviYNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_fs1pCdovEdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_fs1pCtovEdqRBPR5WyT36A" type="OperationCompartment" element="_fsviYNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_fs1pC9ovEdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_fs1pDNovEdqRBPR5WyT36A" visible="false" type="SignalCompartment" element="_fsviYNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_fs1pDdovEdqRBPR5WyT36A"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLClassifierStyle" xmi:id="_fs1pAdovEdqRBPR5WyT36A" showStereotype="Label" useClassifierShape="true"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_fs1pAtovEdqRBPR5WyT36A" x="2226" y="8268"/>
+ </children>
+ <children xmi:id="_ikr_4NovEdqRBPR5WyT36A" sourceEdges="_mu9A4dovEdqRBPR5WyT36A" element="_ikl5QNovEdqRBPR5WyT36A">
+ <children xmi:id="_ikr_49ovEdqRBPR5WyT36A" type="ImageCompartment" element="_ikl5QNovEdqRBPR5WyT36A">
+ <layoutConstraint xmi:type="notation:Size" xmi:id="_ikr_5NovEdqRBPR5WyT36A" width="530" height="530"/>
+ </children>
+ <children xmi:id="_ikr_5dovEdqRBPR5WyT36A" type="Stereotype" element="_ikl5QNovEdqRBPR5WyT36A"/>
+ <children xmi:id="_ikr_5tovEdqRBPR5WyT36A" type="Kind" element="_ikl5QNovEdqRBPR5WyT36A"/>
+ <children xmi:id="_ikr_59ovEdqRBPR5WyT36A" type="Name" element="_ikl5QNovEdqRBPR5WyT36A"/>
+ <children xmi:id="_ikr_6NovEdqRBPR5WyT36A" type="AttributeCompartment" element="_ikl5QNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_ikr_6dovEdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_ikr_6tovEdqRBPR5WyT36A" type="OperationCompartment" element="_ikl5QNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_ikr_69ovEdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_ikr_7NovEdqRBPR5WyT36A" visible="false" type="SignalCompartment" element="_ikl5QNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_ikr_7dovEdqRBPR5WyT36A"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLClassifierStyle" xmi:id="_ikr_4dovEdqRBPR5WyT36A" showStereotype="Label" useClassifierShape="true"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_ikr_4tovEdqRBPR5WyT36A" x="9222" y="8268"/>
+ </children>
+ <children xmi:id="_tZF9odovEdqRBPR5WyT36A" sourceEdges="_xInjYdovEdqRBPR5WyT36A _BkUg0dowEdqRBPR5WyT36A" element="_tZF9oNovEdqRBPR5WyT36A">
+ <children xmi:id="_tZF9pNovEdqRBPR5WyT36A" type="ImageCompartment" element="_tZF9oNovEdqRBPR5WyT36A">
+ <layoutConstraint xmi:type="notation:Size" xmi:id="_tZF9pdovEdqRBPR5WyT36A" width="530" height="530"/>
+ </children>
+ <children xmi:id="_tZF9ptovEdqRBPR5WyT36A" type="Stereotype" element="_tZF9oNovEdqRBPR5WyT36A"/>
+ <children xmi:id="_tZF9p9ovEdqRBPR5WyT36A" type="Kind" element="_tZF9oNovEdqRBPR5WyT36A"/>
+ <children xmi:id="_tZF9qNovEdqRBPR5WyT36A" type="Name" element="_tZF9oNovEdqRBPR5WyT36A"/>
+ <children xmi:id="_tZF9qdovEdqRBPR5WyT36A" type="AttributeCompartment" element="_tZF9oNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_tZF9qtovEdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_tZF9q9ovEdqRBPR5WyT36A" type="OperationCompartment" element="_tZF9oNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_tZF9rNovEdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_tZF9rdovEdqRBPR5WyT36A" visible="false" type="SignalCompartment" element="_tZF9oNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_tZF9rtovEdqRBPR5WyT36A"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLClassifierStyle" xmi:id="_tZF9otovEdqRBPR5WyT36A" showStereotype="Label" useClassifierShape="true"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_tZF9o9ovEdqRBPR5WyT36A" x="2226" y="12084"/>
+ </children>
+ <children xmi:id="_z_m-oNovEdqRBPR5WyT36A" sourceEdges="_cN4xsdo2EdqRBPR5WyT36A" targetEdges="_3Ic-4NovEdqRBPR5WyT36A _9XeF4tovEdqRBPR5WyT36A _Fd3lQdowEdqRBPR5WyT36A" element="_z_g4ANovEdqRBPR5WyT36A">
+ <children xmi:id="_z_m-o9ovEdqRBPR5WyT36A" type="ImageCompartment" element="_z_g4ANovEdqRBPR5WyT36A">
+ <layoutConstraint xmi:type="notation:Size" xmi:id="_z_m-pNovEdqRBPR5WyT36A" width="530" height="530"/>
+ </children>
+ <children xmi:id="_z_m-pdovEdqRBPR5WyT36A" type="Stereotype" element="_z_g4ANovEdqRBPR5WyT36A"/>
+ <children xmi:id="_z_m-ptovEdqRBPR5WyT36A" type="Kind" element="_z_g4ANovEdqRBPR5WyT36A"/>
+ <children xmi:id="_z_m-p9ovEdqRBPR5WyT36A" type="Name" element="_z_g4ANovEdqRBPR5WyT36A"/>
+ <children xmi:id="_z_m-qNovEdqRBPR5WyT36A" type="AttributeCompartment" element="_z_g4ANovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_z_m-qdovEdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_z_m-qtovEdqRBPR5WyT36A" type="OperationCompartment" element="_z_g4ANovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_z_m-q9ovEdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_z_m-rNovEdqRBPR5WyT36A" visible="false" type="SignalCompartment" element="_z_g4ANovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_z_m-rdovEdqRBPR5WyT36A"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLClassifierStyle" xmi:id="_z_m-odovEdqRBPR5WyT36A" showStereotype="Label" useClassifierShape="true"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_z_m-otovEdqRBPR5WyT36A" x="17172" y="6996"/>
+ </children>
+ <children xmi:id="_1y-ZsNovEdqRBPR5WyT36A" sourceEdges="_3Ic-4NovEdqRBPR5WyT36A _9-BEUNo2EdqRBPR5WyT36A" targetEdges="_BkUg0dowEdqRBPR5WyT36A" element="_1yyMcNovEdqRBPR5WyT36A">
+ <children xmi:id="_1y-Zs9ovEdqRBPR5WyT36A" type="ImageCompartment" element="_1yyMcNovEdqRBPR5WyT36A">
+ <layoutConstraint xmi:type="notation:Size" xmi:id="_1y-ZtNovEdqRBPR5WyT36A" width="1320" height="1320"/>
+ </children>
+ <children xmi:id="_1y-ZtdovEdqRBPR5WyT36A" type="Stereotype" element="_1yyMcNovEdqRBPR5WyT36A"/>
+ <children xmi:id="_1y-ZttovEdqRBPR5WyT36A" type="Name" element="_1yyMcNovEdqRBPR5WyT36A"/>
+ <children xmi:id="_1y-Zt9ovEdqRBPR5WyT36A" type="AttributeCompartment" element="_1yyMcNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_1y-ZuNovEdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_1y-ZudovEdqRBPR5WyT36A" type="OperationCompartment" element="_1yyMcNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_1y-ZutovEdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_1y-Zu9ovEdqRBPR5WyT36A" visible="false" type="SignalCompartment" element="_1yyMcNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_1y-ZvNovEdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_1y-ZvdovEdqRBPR5WyT36A" visible="false" type="StructureCompartment" element="_1yyMcNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLShapeCompartmentStyle" xmi:id="_1y-ZvtovEdqRBPR5WyT36A"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLShapeStyle" xmi:id="_1y-ZsdovEdqRBPR5WyT36A" showStereotype="Label"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_1y-ZstovEdqRBPR5WyT36A" x="13992" y="12084"/>
+ </children>
+ <children xmi:id="_4WSrANovEdqRBPR5WyT36A" sourceEdges="_9XeF4tovEdqRBPR5WyT36A _9PaR4No2EdqRBPR5WyT36A" element="_4WMkYNovEdqRBPR5WyT36A">
+ <children xmi:id="_4WSrA9ovEdqRBPR5WyT36A" type="ImageCompartment" element="_4WMkYNovEdqRBPR5WyT36A">
+ <layoutConstraint xmi:type="notation:Size" xmi:id="_4WSrBNovEdqRBPR5WyT36A" width="1320" height="1320"/>
+ </children>
+ <children xmi:id="_4WSrBdovEdqRBPR5WyT36A" type="Stereotype" element="_4WMkYNovEdqRBPR5WyT36A"/>
+ <children xmi:id="_4WSrBtovEdqRBPR5WyT36A" type="Name" element="_4WMkYNovEdqRBPR5WyT36A"/>
+ <children xmi:id="_4WSrB9ovEdqRBPR5WyT36A" type="AttributeCompartment" element="_4WMkYNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_4WSrCNovEdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_4WSrCdovEdqRBPR5WyT36A" type="OperationCompartment" element="_4WMkYNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_4WSrCtovEdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_4WSrC9ovEdqRBPR5WyT36A" visible="false" type="SignalCompartment" element="_4WMkYNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_4WSrDNovEdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_4WSrDdovEdqRBPR5WyT36A" visible="false" type="StructureCompartment" element="_4WMkYNovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLShapeCompartmentStyle" xmi:id="_4WSrDtovEdqRBPR5WyT36A"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLShapeStyle" xmi:id="_4WSrAdovEdqRBPR5WyT36A" showStereotype="Label"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_4WSrAtovEdqRBPR5WyT36A" x="19716" y="12084"/>
+ </children>
+ <children xmi:id="_o2m3oNo0EdqRBPR5WyT36A" targetEdges="_9PaR4No2EdqRBPR5WyT36A _9-BEUNo2EdqRBPR5WyT36A" element="_o2gxANo0EdqRBPR5WyT36A">
+ <children xmi:id="_o2m3o9o0EdqRBPR5WyT36A" type="ImageCompartment" element="_o2gxANo0EdqRBPR5WyT36A">
+ <layoutConstraint xmi:type="notation:Size" xmi:id="_o2m3pNo0EdqRBPR5WyT36A" width="530" height="530"/>
+ </children>
+ <children xmi:id="_o2m3pdo0EdqRBPR5WyT36A" type="Stereotype" element="_o2gxANo0EdqRBPR5WyT36A"/>
+ <children xmi:id="_o2m3pto0EdqRBPR5WyT36A" type="Kind" element="_o2gxANo0EdqRBPR5WyT36A"/>
+ <children xmi:id="_o2m3p9o0EdqRBPR5WyT36A" type="Name" element="_o2gxANo0EdqRBPR5WyT36A"/>
+ <children xmi:id="_o2m3qNo0EdqRBPR5WyT36A" type="AttributeCompartment" element="_o2gxANo0EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_o2m3qdo0EdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_o2m3qto0EdqRBPR5WyT36A" type="OperationCompartment" element="_o2gxANo0EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_o2m3q9o0EdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_o2m3rNo0EdqRBPR5WyT36A" visible="false" type="SignalCompartment" element="_o2gxANo0EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_o2m3rdo0EdqRBPR5WyT36A"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLClassifierStyle" xmi:id="_o2m3odo0EdqRBPR5WyT36A" showStereotype="Label" useClassifierShape="true"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_o2m3oto0EdqRBPR5WyT36A" x="23532" y="6996"/>
+ </children>
+ <children xmi:id="_M0FLkNo1EdqRBPR5WyT36A" targetEdges="_R5Rjwdo1EdqRBPR5WyT36A _V7zlEdo1EdqRBPR5WyT36A" element="_Mz_E8No1EdqRBPR5WyT36A">
+ <children xmi:id="_M0FLk9o1EdqRBPR5WyT36A" type="ImageCompartment" element="_Mz_E8No1EdqRBPR5WyT36A">
+ <layoutConstraint xmi:type="notation:Size" xmi:id="_M0FLlNo1EdqRBPR5WyT36A" width="530" height="530"/>
+ </children>
+ <children xmi:id="_M0FLldo1EdqRBPR5WyT36A" type="Stereotype" element="_Mz_E8No1EdqRBPR5WyT36A"/>
+ <children xmi:id="_M0FLlto1EdqRBPR5WyT36A" type="Kind" element="_Mz_E8No1EdqRBPR5WyT36A"/>
+ <children xmi:id="_M0FLl9o1EdqRBPR5WyT36A" type="Name" element="_Mz_E8No1EdqRBPR5WyT36A"/>
+ <children xmi:id="_M0FLmNo1EdqRBPR5WyT36A" type="AttributeCompartment" element="_Mz_E8No1EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_M0FLmdo1EdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_M0FLmto1EdqRBPR5WyT36A" type="OperationCompartment" element="_Mz_E8No1EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_M0FLm9o1EdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_M0FLnNo1EdqRBPR5WyT36A" visible="false" type="SignalCompartment" element="_Mz_E8No1EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_M0FLndo1EdqRBPR5WyT36A"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLClassifierStyle" xmi:id="_M0FLkdo1EdqRBPR5WyT36A" showStereotype="Label" useClassifierShape="true"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_M0FLkto1EdqRBPR5WyT36A" x="6678" y="318"/>
+ </children>
+ <children xmi:id="_TJHbANo1EdqRBPR5WyT36A" sourceEdges="_V7zlEdo1EdqRBPR5WyT36A" targetEdges="_cN4xsdo2EdqRBPR5WyT36A" element="_TI7NwNo1EdqRBPR5WyT36A">
+ <children xmi:id="_TJHbA9o1EdqRBPR5WyT36A" type="ImageCompartment" element="_TI7NwNo1EdqRBPR5WyT36A">
+ <layoutConstraint xmi:type="notation:Size" xmi:id="_TJHbBNo1EdqRBPR5WyT36A" width="530" height="530"/>
+ </children>
+ <children xmi:id="_TJHbBdo1EdqRBPR5WyT36A" type="Stereotype" element="_TI7NwNo1EdqRBPR5WyT36A"/>
+ <children xmi:id="_TJHbBto1EdqRBPR5WyT36A" type="Kind" element="_TI7NwNo1EdqRBPR5WyT36A"/>
+ <children xmi:id="_TJHbB9o1EdqRBPR5WyT36A" type="Name" element="_TI7NwNo1EdqRBPR5WyT36A"/>
+ <children xmi:id="_TJHbCNo1EdqRBPR5WyT36A" type="AttributeCompartment" element="_TI7NwNo1EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_TJHbCdo1EdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_TJHbCto1EdqRBPR5WyT36A" type="OperationCompartment" element="_TI7NwNo1EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_TJHbC9o1EdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_TJHbDNo1EdqRBPR5WyT36A" visible="false" type="SignalCompartment" element="_TI7NwNo1EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_TJHbDdo1EdqRBPR5WyT36A"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLClassifierStyle" xmi:id="_TJHbAdo1EdqRBPR5WyT36A" showStereotype="Label" useClassifierShape="true"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_TJHbAto1EdqRBPR5WyT36A" x="16854" y="318"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLDiagramStyle" xmi:id="_al1S89ovEdqRBPR5WyT36A"/>
+ <edges xmi:id="_hmIF4dovEdqRBPR5WyT36A" element="_hmIF4NovEdqRBPR5WyT36A" source="_fs1pANovEdqRBPR5WyT36A" target="_ePDcYdovEdqRBPR5WyT36A">
+ <children xmi:id="_hmIF5NovEdqRBPR5WyT36A" type="NameLabel" element="_hmIF4NovEdqRBPR5WyT36A">
+ <children xmi:id="_hmIF5tovEdqRBPR5WyT36A" type="Stereotype" element="_hmIF4NovEdqRBPR5WyT36A"/>
+ <children xmi:id="_hmIF59ovEdqRBPR5WyT36A" type="Name" element="_hmIF4NovEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_hmIF5dovEdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLConnectorStyle" xmi:id="_hmIF4tovEdqRBPR5WyT36A" routing="Tree" showStereotype="Text"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_hmIF49ovEdqRBPR5WyT36A" points="[26, -31, -110, 148]$[140, -148, 4, 31]"/>
+ </edges>
+ <edges xmi:id="_mu9A4dovEdqRBPR5WyT36A" element="_mu9A4NovEdqRBPR5WyT36A" source="_ikr_4NovEdqRBPR5WyT36A" target="_ePDcYdovEdqRBPR5WyT36A">
+ <children xmi:id="_mu9A5NovEdqRBPR5WyT36A" type="NameLabel" element="_mu9A4NovEdqRBPR5WyT36A">
+ <children xmi:id="_mu9A5tovEdqRBPR5WyT36A" type="Stereotype" element="_mu9A4NovEdqRBPR5WyT36A"/>
+ <children xmi:id="_mu9A59ovEdqRBPR5WyT36A" type="Name" element="_mu9A4NovEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_mu9A5dovEdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLConnectorStyle" xmi:id="_mu9A4tovEdqRBPR5WyT36A" routing="Tree" showStereotype="Text"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_mu9A49ovEdqRBPR5WyT36A" points="[-185, -820, 2937, 3916]$[-185, -3042, 2937, 1694]$[-3255, -3042, -133, 1694]$[-3255, -3916, -133, 820]"/>
+ </edges>
+ <edges xmi:id="_pe3jwNovEdqRBPR5WyT36A" element="_peM1YNovEdqRBPR5WyT36A" source="_fs1pANovEdqRBPR5WyT36A" target="_ePDcYdovEdqRBPR5WyT36A">
+ <children xmi:id="_pe3jw9ovEdqRBPR5WyT36A" type="NameLabel" element="_peM1YNovEdqRBPR5WyT36A">
+ <children xmi:id="_pe3jxdovEdqRBPR5WyT36A" type="Stereotype" element="_peM1YNovEdqRBPR5WyT36A"/>
+ <children xmi:id="_pe3jxtovEdqRBPR5WyT36A" type="Name" element="_peM1YNovEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_pe3jxNovEdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <children xmi:id="_pe3jx9ovEdqRBPR5WyT36A" type="ToMultiplicityLabel" element="_peM1YtovEdqRBPR5WyT36A">
+ <children xmi:id="_pe3jydovEdqRBPR5WyT36A" type="ToMultiplicity" element="_peM1YtovEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_pe3jyNovEdqRBPR5WyT36A" y="397"/>
+ </children>
+ <children xmi:id="_pe3jytovEdqRBPR5WyT36A" type="ToRoleLabel" element="_peM1YtovEdqRBPR5WyT36A">
+ <children xmi:id="_pe3jzNovEdqRBPR5WyT36A" type="ToRole" element="_peM1YtovEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_pe3jy9ovEdqRBPR5WyT36A" y="-397"/>
+ </children>
+ <children xmi:id="_pe3jzdovEdqRBPR5WyT36A" type="FromMultiplicityLabel" element="_peM1YdovEdqRBPR5WyT36A">
+ <children xmi:id="_pe3jz9ovEdqRBPR5WyT36A" type="FromMultiplicity" element="_peM1YdovEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_pe3jztovEdqRBPR5WyT36A" y="397"/>
+ </children>
+ <children xmi:id="_pe3j0NovEdqRBPR5WyT36A" type="FromRoleLabel" element="_peM1YdovEdqRBPR5WyT36A">
+ <children xmi:id="_pe3j0tovEdqRBPR5WyT36A" type="FromRole" element="_peM1YdovEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_pe3j0dovEdqRBPR5WyT36A" y="-397"/>
+ </children>
+ <children xmi:id="_pe3j09ovEdqRBPR5WyT36A" type="ToQualifierLabel" element="_peM1YtovEdqRBPR5WyT36A">
+ <children xmi:id="_pe3j1dovEdqRBPR5WyT36A" type="QualifierCompartment" element="_peM1YtovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_pe3j1tovEdqRBPR5WyT36A"/>
+ </children>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_pe3j1NovEdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <children xmi:id="_pe3j19ovEdqRBPR5WyT36A" type="FromQualifierLabel" element="_peM1YdovEdqRBPR5WyT36A">
+ <children xmi:id="_pe3j2dovEdqRBPR5WyT36A" type="QualifierCompartment" element="_peM1YdovEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_pe3j2tovEdqRBPR5WyT36A"/>
+ </children>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_pe3j2NovEdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLConnectorStyle" xmi:id="_pe3jwdovEdqRBPR5WyT36A" showStereotype="Text"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_pe3jwtovEdqRBPR5WyT36A" points="[-317, -820, -3916, 3916]$[-1931, -4762, -5530, -26]$[2382, -4762, -1217, -26]"/>
+ </edges>
+ <edges xmi:id="_xInjYdovEdqRBPR5WyT36A" element="_xInjYNovEdqRBPR5WyT36A" source="_tZF9odovEdqRBPR5WyT36A" target="_fs1pANovEdqRBPR5WyT36A">
+ <children xmi:id="_xInjZNovEdqRBPR5WyT36A" type="NameLabel" element="_xInjYNovEdqRBPR5WyT36A">
+ <children xmi:id="_xInjZtovEdqRBPR5WyT36A" type="Stereotype" element="_xInjYNovEdqRBPR5WyT36A"/>
+ <children xmi:id="_xInjZ9ovEdqRBPR5WyT36A" type="Name" element="_xInjYNovEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_xInjZdovEdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLConnectorStyle" xmi:id="_xInjYtovEdqRBPR5WyT36A" showStereotype="Text"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_xInjY9ovEdqRBPR5WyT36A" points="[-4, -31, 1, 113]$[-4, -115, 1, 29]"/>
+ </edges>
+ <edges xmi:id="_3Ic-4NovEdqRBPR5WyT36A" element="_3IW4QNovEdqRBPR5WyT36A" source="_1y-ZsNovEdqRBPR5WyT36A" target="_z_m-oNovEdqRBPR5WyT36A">
+ <children xmi:id="_3Ic-49ovEdqRBPR5WyT36A" type="NameLabel" element="_3IW4QNovEdqRBPR5WyT36A">
+ <children xmi:id="_3Ic-5dovEdqRBPR5WyT36A" type="Stereotype" element="_3IW4QNovEdqRBPR5WyT36A"/>
+ <children xmi:id="_3Ic-5tovEdqRBPR5WyT36A" type="Name" element="_3IW4QNovEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_3Ic-5NovEdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLConnectorStyle" xmi:id="_3Ic-4dovEdqRBPR5WyT36A" showStereotype="Text"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_3Ic-4tovEdqRBPR5WyT36A" points="[6, -24, -37, 154]$[-22, -170, -65, 8]"/>
+ </edges>
+ <edges xmi:id="_9XeF4tovEdqRBPR5WyT36A" element="_9XeF4NovEdqRBPR5WyT36A" source="_4WSrANovEdqRBPR5WyT36A" target="_z_m-oNovEdqRBPR5WyT36A">
+ <children xmi:id="_9XeF5dovEdqRBPR5WyT36A" type="NameLabel" element="_9XeF4NovEdqRBPR5WyT36A">
+ <children xmi:id="_9XeF59ovEdqRBPR5WyT36A" type="Stereotype" element="_9XeF4NovEdqRBPR5WyT36A"/>
+ <children xmi:id="_9XeF6NovEdqRBPR5WyT36A" type="Name" element="_9XeF4NovEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_9XeF5tovEdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLConnectorStyle" xmi:id="_9XeF49ovEdqRBPR5WyT36A" showStereotype="Text"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_9XeF5NovEdqRBPR5WyT36A" points="[-23, -23, 162, 151]$[-121, -170, 64, 4]"/>
+ </edges>
+ <edges xmi:id="_BkUg0dowEdqRBPR5WyT36A" element="_Bj8GUNowEdqRBPR5WyT36A" source="_tZF9odovEdqRBPR5WyT36A" target="_1y-ZsNovEdqRBPR5WyT36A">
+ <children xmi:id="_BkancNowEdqRBPR5WyT36A" type="NameLabel" element="_Bj8GUNowEdqRBPR5WyT36A">
+ <children xmi:id="_BkanctowEdqRBPR5WyT36A" type="Stereotype" element="_Bj8GUNowEdqRBPR5WyT36A"/>
+ <children xmi:id="_Bkanc9owEdqRBPR5WyT36A" type="Name" element="_Bj8GUNowEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_BkancdowEdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <children xmi:id="_BkandNowEdqRBPR5WyT36A" type="ToMultiplicityLabel" element="_Bj8GUtowEdqRBPR5WyT36A">
+ <children xmi:id="_BkandtowEdqRBPR5WyT36A" type="ToMultiplicity" element="_Bj8GUtowEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_BkanddowEdqRBPR5WyT36A" y="397"/>
+ </children>
+ <children xmi:id="_Bkand9owEdqRBPR5WyT36A" type="ToRoleLabel" element="_Bj8GUtowEdqRBPR5WyT36A">
+ <children xmi:id="_BkanedowEdqRBPR5WyT36A" type="ToRole" element="_Bj8GUtowEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_BkaneNowEdqRBPR5WyT36A" y="-397"/>
+ </children>
+ <children xmi:id="_BkanetowEdqRBPR5WyT36A" type="FromMultiplicityLabel" element="_Bj8GUdowEdqRBPR5WyT36A">
+ <children xmi:id="_BkanfNowEdqRBPR5WyT36A" type="FromMultiplicity" element="_Bj8GUdowEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_Bkane9owEdqRBPR5WyT36A" y="397"/>
+ </children>
+ <children xmi:id="_BkanfdowEdqRBPR5WyT36A" type="FromRoleLabel" element="_Bj8GUdowEdqRBPR5WyT36A">
+ <children xmi:id="_Bkanf9owEdqRBPR5WyT36A" type="FromRole" element="_Bj8GUdowEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_BkanftowEdqRBPR5WyT36A" y="-397"/>
+ </children>
+ <children xmi:id="_BkangNowEdqRBPR5WyT36A" type="ToQualifierLabel" element="_Bj8GUtowEdqRBPR5WyT36A">
+ <children xmi:id="_BkangtowEdqRBPR5WyT36A" type="QualifierCompartment" element="_Bj8GUtowEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_Bkang9owEdqRBPR5WyT36A"/>
+ </children>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_BkangdowEdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <children xmi:id="_BkanhNowEdqRBPR5WyT36A" type="FromQualifierLabel" element="_Bj8GUdowEdqRBPR5WyT36A">
+ <children xmi:id="_BkanhtowEdqRBPR5WyT36A" type="QualifierCompartment" element="_Bj8GUdowEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_Bkanh9owEdqRBPR5WyT36A"/>
+ </children>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_BkanhdowEdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLConnectorStyle" xmi:id="_BkUg0towEdqRBPR5WyT36A" showStereotype="Text"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_BkUg09owEdqRBPR5WyT36A" points="[83, -24, -490, 123]$[486, -151, -87, -4]"/>
+ </edges>
+ <edges xmi:id="_Fd3lQdowEdqRBPR5WyT36A" element="_FdlRYNowEdqRBPR5WyT36A" source="_ePDcYdovEdqRBPR5WyT36A" target="_z_m-oNovEdqRBPR5WyT36A">
+ <children xmi:id="_Fd3lRNowEdqRBPR5WyT36A" type="NameLabel" element="_FdlRYNowEdqRBPR5WyT36A">
+ <children xmi:id="_Fd3lRtowEdqRBPR5WyT36A" type="Stereotype" element="_FdlRYNowEdqRBPR5WyT36A"/>
+ <children xmi:id="_Fd3lR9owEdqRBPR5WyT36A" type="Name" element="_FdlRYNowEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_Fd3lRdowEdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <children xmi:id="_Fd3lSNowEdqRBPR5WyT36A" type="ToMultiplicityLabel" element="_FdlRYtowEdqRBPR5WyT36A">
+ <children xmi:id="_Fd3lStowEdqRBPR5WyT36A" type="ToMultiplicity" element="_FdlRYtowEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_Fd3lSdowEdqRBPR5WyT36A" y="397"/>
+ </children>
+ <children xmi:id="_Fd3lS9owEdqRBPR5WyT36A" type="ToRoleLabel" element="_FdlRYtowEdqRBPR5WyT36A">
+ <children xmi:id="_Fd3lTdowEdqRBPR5WyT36A" type="ToRole" element="_FdlRYtowEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_Fd3lTNowEdqRBPR5WyT36A" y="-397"/>
+ </children>
+ <children xmi:id="_Fd3lTtowEdqRBPR5WyT36A" type="FromMultiplicityLabel" element="_FdlRYdowEdqRBPR5WyT36A">
+ <children xmi:id="_Fd3lUNowEdqRBPR5WyT36A" type="FromMultiplicity" element="_FdlRYdowEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_Fd3lT9owEdqRBPR5WyT36A" y="397"/>
+ </children>
+ <children xmi:id="_Fd3lUdowEdqRBPR5WyT36A" type="FromRoleLabel" element="_FdlRYdowEdqRBPR5WyT36A">
+ <children xmi:id="_Fd3lU9owEdqRBPR5WyT36A" type="FromRole" element="_FdlRYdowEdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_Fd3lUtowEdqRBPR5WyT36A" y="-397"/>
+ </children>
+ <children xmi:id="_Fd3lVNowEdqRBPR5WyT36A" type="ToQualifierLabel" element="_FdlRYtowEdqRBPR5WyT36A">
+ <children xmi:id="_Fd3lVtowEdqRBPR5WyT36A" type="QualifierCompartment" element="_FdlRYtowEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_Fd3lV9owEdqRBPR5WyT36A"/>
+ </children>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_Fd3lVdowEdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <children xmi:id="_Fd3lWNowEdqRBPR5WyT36A" type="FromQualifierLabel" element="_FdlRYdowEdqRBPR5WyT36A">
+ <children xmi:id="_Fd3lWtowEdqRBPR5WyT36A" type="QualifierCompartment" element="_FdlRYdowEdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_Fd3lW9owEdqRBPR5WyT36A"/>
+ </children>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_Fd3lWdowEdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLConnectorStyle" xmi:id="_Fd3lQtowEdqRBPR5WyT36A" showStereotype="Text"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_Fd3lQ9owEdqRBPR5WyT36A" points="[46, -11, -369, -9]$[351, -11, -64, -9]"/>
+ </edges>
+ <edges xmi:id="_R5Rjwdo1EdqRBPR5WyT36A" element="_R5RjwNo1EdqRBPR5WyT36A" source="_ePDcYdovEdqRBPR5WyT36A" target="_M0FLkNo1EdqRBPR5WyT36A">
+ <children xmi:id="_R5RjxNo1EdqRBPR5WyT36A" type="NameLabel" element="_R5RjwNo1EdqRBPR5WyT36A">
+ <children xmi:id="_R5Rjxto1EdqRBPR5WyT36A" type="Stereotype" element="_R5RjwNo1EdqRBPR5WyT36A"/>
+ <children xmi:id="_R5Rjx9o1EdqRBPR5WyT36A" type="Name" element="_R5RjwNo1EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_R5Rjxdo1EdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLConnectorStyle" xmi:id="_R5Rjwto1EdqRBPR5WyT36A" showStereotype="Text"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_R5Rjw9o1EdqRBPR5WyT36A" points="[-2, -31, -2, 91]$[-2, -91, -2, 31]"/>
+ </edges>
+ <edges xmi:id="_V7zlEdo1EdqRBPR5WyT36A" element="_V7zlENo1EdqRBPR5WyT36A" source="_TJHbANo1EdqRBPR5WyT36A" target="_M0FLkNo1EdqRBPR5WyT36A">
+ <children xmi:id="_V7zlFNo1EdqRBPR5WyT36A" type="NameLabel" element="_V7zlENo1EdqRBPR5WyT36A">
+ <children xmi:id="_V7zlFto1EdqRBPR5WyT36A" type="Stereotype" element="_V7zlENo1EdqRBPR5WyT36A"/>
+ <children xmi:id="_V7zlF9o1EdqRBPR5WyT36A" type="Name" element="_V7zlENo1EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_V7zlFdo1EdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLConnectorStyle" xmi:id="_V7zlEto1EdqRBPR5WyT36A" showStereotype="Text"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_V7zlE9o1EdqRBPR5WyT36A" points="[-73, 0, 339, 0]$[-457, 0, -45, 0]"/>
+ </edges>
+ <edges xmi:id="_cN4xsdo2EdqRBPR5WyT36A" targetEdges="_pdfmkNo2EdqRBPR5WyT36A" element="_cNskcNo2EdqRBPR5WyT36A" source="_z_m-oNovEdqRBPR5WyT36A" target="_TJHbANo1EdqRBPR5WyT36A">
+ <children xmi:id="_cN4xtNo2EdqRBPR5WyT36A" type="NameLabel" element="_cNskcNo2EdqRBPR5WyT36A">
+ <children xmi:id="_cN4xtto2EdqRBPR5WyT36A" type="Stereotype" element="_cNskcNo2EdqRBPR5WyT36A"/>
+ <children xmi:id="_cN4xt9o2EdqRBPR5WyT36A" type="Name" element="_cNskcNo2EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_cN4xtdo2EdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <children xmi:id="_cN4xuNo2EdqRBPR5WyT36A" type="ToMultiplicityLabel" element="_cNskcto2EdqRBPR5WyT36A">
+ <children xmi:id="_cN4xuto2EdqRBPR5WyT36A" type="ToMultiplicity" element="_cNskcto2EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_cN4xudo2EdqRBPR5WyT36A" y="397"/>
+ </children>
+ <children xmi:id="_cN4xu9o2EdqRBPR5WyT36A" type="ToRoleLabel" element="_cNskcto2EdqRBPR5WyT36A">
+ <children xmi:id="_cN4xvdo2EdqRBPR5WyT36A" type="ToRole" element="_cNskcto2EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_cN4xvNo2EdqRBPR5WyT36A" y="-397"/>
+ </children>
+ <children xmi:id="_cN_fYNo2EdqRBPR5WyT36A" type="FromMultiplicityLabel" element="_cNskcdo2EdqRBPR5WyT36A">
+ <children xmi:id="_cN_fYto2EdqRBPR5WyT36A" type="FromMultiplicity" element="_cNskcdo2EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_cN_fYdo2EdqRBPR5WyT36A" y="397"/>
+ </children>
+ <children xmi:id="_cN_fY9o2EdqRBPR5WyT36A" type="FromRoleLabel" element="_cNskcdo2EdqRBPR5WyT36A">
+ <children xmi:id="_cN_fZdo2EdqRBPR5WyT36A" type="FromRole" element="_cNskcdo2EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_cN_fZNo2EdqRBPR5WyT36A" y="-397"/>
+ </children>
+ <children xmi:id="_cN_fZto2EdqRBPR5WyT36A" type="ToQualifierLabel" element="_cNskcto2EdqRBPR5WyT36A">
+ <children xmi:id="_cN_faNo2EdqRBPR5WyT36A" type="QualifierCompartment" element="_cNskcto2EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_cN_fado2EdqRBPR5WyT36A"/>
+ </children>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_cN_fZ9o2EdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <children xmi:id="_cN_fato2EdqRBPR5WyT36A" type="FromQualifierLabel" element="_cNskcdo2EdqRBPR5WyT36A">
+ <children xmi:id="_cN_fbNo2EdqRBPR5WyT36A" type="QualifierCompartment" element="_cNskcdo2EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_cN_fbdo2EdqRBPR5WyT36A"/>
+ </children>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_cN_fa9o2EdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLConnectorStyle" xmi:id="_cN4xsto2EdqRBPR5WyT36A" showStereotype="Text"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_cN4xs9o2EdqRBPR5WyT36A" points="[-2, -29, 1, 91]$[26, -89, 29, 31]"/>
+ </edges>
+ <edges xmi:id="_pdfmkNo2EdqRBPR5WyT36A" element="_pdHMENo2EdqRBPR5WyT36A" source="_ePDcYdovEdqRBPR5WyT36A" target="_cN4xsdo2EdqRBPR5WyT36A">
+ <children xmi:id="_pdfml9o2EdqRBPR5WyT36A" type="ToMultiplicityLabel" element="_pdTZUdo2EdqRBPR5WyT36A">
+ <children xmi:id="_pdfmmdo2EdqRBPR5WyT36A" type="ToMultiplicity" element="_pdTZUdo2EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_pdfmmNo2EdqRBPR5WyT36A" y="397"/>
+ </children>
+ <children xmi:id="_pdfmmto2EdqRBPR5WyT36A" type="ToRoleLabel" element="_pdTZUdo2EdqRBPR5WyT36A">
+ <children xmi:id="_pdfmnNo2EdqRBPR5WyT36A" type="ToRole" element="_pdTZUdo2EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_pdfmm9o2EdqRBPR5WyT36A" y="-397"/>
+ </children>
+ <children xmi:id="_pdfmndo2EdqRBPR5WyT36A" type="FromMultiplicityLabel" element="_pdTZUNo2EdqRBPR5WyT36A">
+ <children xmi:id="_pdfmn9o2EdqRBPR5WyT36A" type="FromMultiplicity" element="_pdTZUNo2EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_pdfmnto2EdqRBPR5WyT36A" y="397"/>
+ </children>
+ <children xmi:id="_pdfmoNo2EdqRBPR5WyT36A" type="FromRoleLabel" element="_pdTZUNo2EdqRBPR5WyT36A">
+ <children xmi:id="_pdfmoto2EdqRBPR5WyT36A" type="FromRole" element="_pdTZUNo2EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_pdfmodo2EdqRBPR5WyT36A" y="-397"/>
+ </children>
+ <children xmi:id="_pdfmo9o2EdqRBPR5WyT36A" type="ToQualifierLabel" element="_pdTZUdo2EdqRBPR5WyT36A">
+ <children xmi:id="_pdfmpdo2EdqRBPR5WyT36A" type="QualifierCompartment" element="_pdTZUdo2EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_pdfmpto2EdqRBPR5WyT36A"/>
+ </children>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_pdfmpNo2EdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <children xmi:id="_pdfmp9o2EdqRBPR5WyT36A" type="FromQualifierLabel" element="_pdTZUNo2EdqRBPR5WyT36A">
+ <children xmi:id="_pdfmqdo2EdqRBPR5WyT36A" type="QualifierCompartment" element="_pdTZUNo2EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_pdfmqto2EdqRBPR5WyT36A"/>
+ </children>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_pdfmqNo2EdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <children xmi:id="_pdfmq9o2EdqRBPR5WyT36A" element="_pdHMENo2EdqRBPR5WyT36A">
+ <children xmi:id="_pdfmrto2EdqRBPR5WyT36A" type="ImageCompartment" element="_pdHMENo2EdqRBPR5WyT36A">
+ <layoutConstraint xmi:type="notation:Size" xmi:id="_pdfmr9o2EdqRBPR5WyT36A" width="1320" height="1320"/>
+ </children>
+ <children xmi:id="_pdfmsNo2EdqRBPR5WyT36A" type="Stereotype" element="_pdHMENo2EdqRBPR5WyT36A"/>
+ <children xmi:id="_pdfmsdo2EdqRBPR5WyT36A" type="Name" element="_pdHMENo2EdqRBPR5WyT36A"/>
+ <children xmi:id="_pdfmsto2EdqRBPR5WyT36A" type="AttributeCompartment" element="_pdHMENo2EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_pdfms9o2EdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_pdfmtNo2EdqRBPR5WyT36A" type="OperationCompartment" element="_pdHMENo2EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_pdfmtdo2EdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_pdfmtto2EdqRBPR5WyT36A" visible="false" type="SignalCompartment" element="_pdHMENo2EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_pdfmt9o2EdqRBPR5WyT36A"/>
+ </children>
+ <children xmi:id="_pdfmuNo2EdqRBPR5WyT36A" visible="false" type="StructureCompartment" element="_pdHMENo2EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLShapeCompartmentStyle" xmi:id="_pdfmudo2EdqRBPR5WyT36A"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLShapeStyle" xmi:id="_pdfmrNo2EdqRBPR5WyT36A" showStereotype="Label"/>
+ <layoutConstraint xmi:type="notation:Bounds" xmi:id="_pdfmrdo2EdqRBPR5WyT36A" y="1323"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLConnectorStyle" xmi:id="_pdfmkdo2EdqRBPR5WyT36A" showStereotype="Text"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_pdfmkto2EdqRBPR5WyT36A" points="[46, 3, -366, 94]$[412, -91, 0, 0]"/>
+ <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_pdrz0No2EdqRBPR5WyT36A" id="100"/>
+ </edges>
+ <edges xmi:id="_9PaR4No2EdqRBPR5WyT36A" element="_9PH-ANo2EdqRBPR5WyT36A" source="_4WSrANovEdqRBPR5WyT36A" target="_o2m3oNo0EdqRBPR5WyT36A">
+ <children xmi:id="_9PaR49o2EdqRBPR5WyT36A" type="NameLabel" element="_9PH-ANo2EdqRBPR5WyT36A">
+ <children xmi:id="_9PaR5do2EdqRBPR5WyT36A" type="Stereotype" element="_9PH-ANo2EdqRBPR5WyT36A"/>
+ <children xmi:id="_9PaR5to2EdqRBPR5WyT36A" type="Name" element="_9PH-ANo2EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_9PaR5No2EdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <children xmi:id="_9PaR59o2EdqRBPR5WyT36A" type="ToMultiplicityLabel" element="_9PH-Ato2EdqRBPR5WyT36A">
+ <children xmi:id="_9PaR6do2EdqRBPR5WyT36A" type="ToMultiplicity" element="_9PH-Ato2EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_9PaR6No2EdqRBPR5WyT36A" y="397"/>
+ </children>
+ <children xmi:id="_9PaR6to2EdqRBPR5WyT36A" type="ToRoleLabel" element="_9PH-Ato2EdqRBPR5WyT36A">
+ <children xmi:id="_9PaR7No2EdqRBPR5WyT36A" type="ToRole" element="_9PH-Ato2EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_9PaR69o2EdqRBPR5WyT36A" y="-397"/>
+ </children>
+ <children xmi:id="_9PaR7do2EdqRBPR5WyT36A" type="FromMultiplicityLabel" element="_9PH-Ado2EdqRBPR5WyT36A">
+ <children xmi:id="_9PaR79o2EdqRBPR5WyT36A" type="FromMultiplicity" element="_9PH-Ado2EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_9PaR7to2EdqRBPR5WyT36A" y="397"/>
+ </children>
+ <children xmi:id="_9PaR8No2EdqRBPR5WyT36A" type="FromRoleLabel" element="_9PH-Ado2EdqRBPR5WyT36A">
+ <children xmi:id="_9PaR8to2EdqRBPR5WyT36A" type="FromRole" element="_9PH-Ado2EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_9PaR8do2EdqRBPR5WyT36A" y="-397"/>
+ </children>
+ <children xmi:id="_9PgYgNo2EdqRBPR5WyT36A" type="ToQualifierLabel" element="_9PH-Ato2EdqRBPR5WyT36A">
+ <children xmi:id="_9PgYgto2EdqRBPR5WyT36A" type="QualifierCompartment" element="_9PH-Ato2EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_9PgYg9o2EdqRBPR5WyT36A"/>
+ </children>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_9PgYgdo2EdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <children xmi:id="_9PgYhNo2EdqRBPR5WyT36A" type="FromQualifierLabel" element="_9PH-Ado2EdqRBPR5WyT36A">
+ <children xmi:id="_9PgYhto2EdqRBPR5WyT36A" type="QualifierCompartment" element="_9PH-Ado2EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_9PgYh9o2EdqRBPR5WyT36A"/>
+ </children>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_9PgYhdo2EdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLConnectorStyle" xmi:id="_9PaR4do2EdqRBPR5WyT36A" showStereotype="Text"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_9PaR4to2EdqRBPR5WyT36A" points="[12, -24, -94, 162]$[80, -155, -26, 31]"/>
+ </edges>
+ <edges xmi:id="_9-BEUNo2EdqRBPR5WyT36A" element="_99uwcNo2EdqRBPR5WyT36A" source="_1y-ZsNovEdqRBPR5WyT36A" target="_o2m3oNo0EdqRBPR5WyT36A">
+ <children xmi:id="_9-BEU9o2EdqRBPR5WyT36A" type="NameLabel" element="_99uwcNo2EdqRBPR5WyT36A">
+ <children xmi:id="_9-HK8No2EdqRBPR5WyT36A" type="Stereotype" element="_99uwcNo2EdqRBPR5WyT36A"/>
+ <children xmi:id="_9-HK8do2EdqRBPR5WyT36A" type="Name" element="_99uwcNo2EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_9-BEVNo2EdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <children xmi:id="_9-HK8to2EdqRBPR5WyT36A" type="ToMultiplicityLabel" element="_99uwcto2EdqRBPR5WyT36A">
+ <children xmi:id="_9-HK9No2EdqRBPR5WyT36A" type="ToMultiplicity" element="_99uwcto2EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_9-HK89o2EdqRBPR5WyT36A" y="397"/>
+ </children>
+ <children xmi:id="_9-HK9do2EdqRBPR5WyT36A" type="ToRoleLabel" element="_99uwcto2EdqRBPR5WyT36A">
+ <children xmi:id="_9-HK99o2EdqRBPR5WyT36A" type="ToRole" element="_99uwcto2EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_9-HK9to2EdqRBPR5WyT36A" y="-397"/>
+ </children>
+ <children xmi:id="_9-HK-No2EdqRBPR5WyT36A" type="FromMultiplicityLabel" element="_99uwcdo2EdqRBPR5WyT36A">
+ <children xmi:id="_9-HK-to2EdqRBPR5WyT36A" type="FromMultiplicity" element="_99uwcdo2EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_9-HK-do2EdqRBPR5WyT36A" y="397"/>
+ </children>
+ <children xmi:id="_9-HK-9o2EdqRBPR5WyT36A" type="FromRoleLabel" element="_99uwcdo2EdqRBPR5WyT36A">
+ <children xmi:id="_9-HK_do2EdqRBPR5WyT36A" type="FromRole" element="_99uwcdo2EdqRBPR5WyT36A"/>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_9-HK_No2EdqRBPR5WyT36A" y="-397"/>
+ </children>
+ <children xmi:id="_9-HK_to2EdqRBPR5WyT36A" type="ToQualifierLabel" element="_99uwcto2EdqRBPR5WyT36A">
+ <children xmi:id="_9-HLANo2EdqRBPR5WyT36A" type="QualifierCompartment" element="_99uwcto2EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_9-HLAdo2EdqRBPR5WyT36A"/>
+ </children>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_9-HK_9o2EdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <children xmi:id="_9-HLAto2EdqRBPR5WyT36A" type="FromQualifierLabel" element="_99uwcdo2EdqRBPR5WyT36A">
+ <children xmi:id="_9-HLBNo2EdqRBPR5WyT36A" type="QualifierCompartment" element="_99uwcdo2EdqRBPR5WyT36A">
+ <styles xmi:type="umlnotation:UMLListCompartmentStyle" xmi:id="_9-HLBdo2EdqRBPR5WyT36A"/>
+ </children>
+ <layoutConstraint xmi:type="notation:Location" xmi:id="_9-HLA9o2EdqRBPR5WyT36A" y="-185"/>
+ </children>
+ <styles xmi:type="umlnotation:UMLConnectorStyle" xmi:id="_9-BEUdo2EdqRBPR5WyT36A" showStereotype="Text"/>
+ <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_9-BEUto2EdqRBPR5WyT36A" points="[49, -24, -290, 162]$[404, -163, 65, 23]"/>
+ </edges>
+ </contents>
+ </eAnnotations>
+ <packageImport xmi:type="uml:ProfileApplication" xmi:id="_al1S9NovEdqRBPR5WyT36A">
+ <eAnnotations xmi:id="_al1S9dovEdqRBPR5WyT36A" source="attributes">
+ <details xmi:id="_al1S9tovEdqRBPR5WyT36A" key="version" value="0"/>
+ </eAnnotations>
+ <importedPackage xmi:type="uml:Profile" href="pathmap://UML2_PROFILES/Basic.profile.uml2#_6mFRgK86Edih9-GG5afQ0g"/>
+ <importedProfile href="pathmap://UML2_PROFILES/Basic.profile.uml2#_6mFRgK86Edih9-GG5afQ0g"/>
+ </packageImport>
+ <packageImport xmi:type="uml:ProfileApplication" xmi:id="_al1S99ovEdqRBPR5WyT36A">
+ <eAnnotations xmi:id="_al1S-NovEdqRBPR5WyT36A" source="attributes">
+ <details xmi:id="_al1S-dovEdqRBPR5WyT36A" key="version" value="0"/>
+ </eAnnotations>
+ <importedPackage xmi:type="uml:Profile" href="pathmap://UML2_PROFILES/Intermediate.profile.uml2#_Cz7csK87Edih9-GG5afQ0g"/>
+ <importedProfile href="pathmap://UML2_PROFILES/Intermediate.profile.uml2#_Cz7csK87Edih9-GG5afQ0g"/>
+ </packageImport>
+ <packageImport xmi:type="uml:ProfileApplication" xmi:id="_al1S-tovEdqRBPR5WyT36A">
+ <eAnnotations xmi:id="_al1S-9ovEdqRBPR5WyT36A" source="attributes">
+ <details xmi:id="_al1S_NovEdqRBPR5WyT36A" key="version" value="0"/>
+ </eAnnotations>
+ <importedPackage xmi:type="uml:Profile" href="pathmap://UML2_PROFILES/Complete.profile.uml2#_M7pTkK87Edih9-GG5afQ0g"/>
+ <importedProfile href="pathmap://UML2_PROFILES/Complete.profile.uml2#_M7pTkK87Edih9-GG5afQ0g"/>
+ </packageImport>
+ <packageImport xmi:type="uml:ProfileApplication" xmi:id="_al1S_dovEdqRBPR5WyT36A">
+ <eAnnotations xmi:id="_al1S_tovEdqRBPR5WyT36A" source="attributes">
+ <details xmi:id="_al1S_9ovEdqRBPR5WyT36A" key="version" value="0"/>
+ </eAnnotations>
+ <importedPackage xmi:type="uml:Profile" href="pathmap://UML2_MSL_PROFILES/Default.epx#_a_S3wNWLEdiy4IqP8whjFA?Default"/>
+ <importedProfile href="pathmap://UML2_MSL_PROFILES/Default.epx#_a_S3wNWLEdiy4IqP8whjFA?Default"/>
+ </packageImport>
+ <packageImport xmi:type="uml:ProfileApplication" xmi:id="_al1TANovEdqRBPR5WyT36A">
+ <eAnnotations xmi:id="_al1TAdovEdqRBPR5WyT36A" source="attributes">
+ <details xmi:id="_al1TAtovEdqRBPR5WyT36A" key="version" value="0"/>
+ </eAnnotations>
+ <importedPackage xmi:type="uml:Profile" href="pathmap://UML2_MSL_PROFILES/Deployment.epx#_vjbuwOvHEdiDX5bji0iVSA?Deployment"/>
+ <importedProfile href="pathmap://UML2_MSL_PROFILES/Deployment.epx#_vjbuwOvHEdiDX5bji0iVSA?Deployment"/>
+ </packageImport>
+ <packageImport xmi:id="_al1TA9ovEdqRBPR5WyT36A">
+ <importedPackage xmi:type="uml:Model" href="pathmap://UML2_LIBRARIES/UML2PrimitiveTypes.library.uml2#_EfRZoK86EdieaYgxtVWN8Q"/>
+ </packageImport>
+ <ownedMember xmi:type="uml:Interface" xmi:id="_ePDcYNovEdqRBPR5WyT36A" name="Context">
+ <generalization xmi:id="_R5RjwNo1EdqRBPR5WyT36A" general="_Mz_E8No1EdqRBPR5WyT36A"/>
+ <ownedAttribute xmi:id="_FdlRYdowEdqRBPR5WyT36A" name="scopecontext" visibility="private" type="_z_g4ANovEdqRBPR5WyT36A" association="_FdlRYNowEdqRBPR5WyT36A">
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_FdlRZNowEdqRBPR5WyT36A" value="1"/>
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_FdlRY9owEdqRBPR5WyT36A"/>
+ </ownedAttribute>
+ </ownedMember>
+ <ownedMember xmi:type="uml:Interface" xmi:id="_fsviYNovEdqRBPR5WyT36A" name="CompositeContext">
+ <generalization xmi:id="_hmIF4NovEdqRBPR5WyT36A" general="_ePDcYNovEdqRBPR5WyT36A"/>
+ <ownedAttribute xmi:id="_peM1YdovEdqRBPR5WyT36A" name="context" visibility="private" type="_ePDcYNovEdqRBPR5WyT36A" association="_peM1YNovEdqRBPR5WyT36A" aggregation="composite">
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_peM1ZNovEdqRBPR5WyT36A" value="-1"/>
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_peM1Y9ovEdqRBPR5WyT36A"/>
+ </ownedAttribute>
+ </ownedMember>
+ <ownedMember xmi:type="uml:Interface" xmi:id="_ikl5QNovEdqRBPR5WyT36A" name="AtomicContext">
+ <generalization xmi:id="_mu9A4NovEdqRBPR5WyT36A" general="_ePDcYNovEdqRBPR5WyT36A"/>
+ </ownedMember>
+ <ownedMember xmi:type="uml:Association" xmi:id="_peM1YNovEdqRBPR5WyT36A" memberEnd="_peM1YdovEdqRBPR5WyT36A _peM1YtovEdqRBPR5WyT36A">
+ <ownedEnd xmi:id="_peM1YtovEdqRBPR5WyT36A" visibility="private" type="_fsviYNovEdqRBPR5WyT36A" association="_peM1YNovEdqRBPR5WyT36A"/>
+ </ownedMember>
+ <ownedMember xmi:type="uml:Interface" xmi:id="_tZF9oNovEdqRBPR5WyT36A" name="DeploymentContext">
+ <generalization xmi:id="_xInjYNovEdqRBPR5WyT36A" general="_fsviYNovEdqRBPR5WyT36A"/>
+ <ownedAttribute xmi:id="_Bj8GUdowEdqRBPR5WyT36A" name="modulescopecontext" visibility="private" type="_1yyMcNovEdqRBPR5WyT36A" association="_Bj8GUNowEdqRBPR5WyT36A">
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_Bj8GVNowEdqRBPR5WyT36A" value="1"/>
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_Bj8GU9owEdqRBPR5WyT36A"/>
+ </ownedAttribute>
+ </ownedMember>
+ <ownedMember xmi:type="uml:Interface" xmi:id="_z_g4ANovEdqRBPR5WyT36A" name="ScopeContext">
+ <ownedAttribute xmi:id="_cNskcdo2EdqRBPR5WyT36A" name="instancewrapper" visibility="private" type="_TI7NwNo1EdqRBPR5WyT36A" association="_cNskcNo2EdqRBPR5WyT36A">
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_cNskdNo2EdqRBPR5WyT36A" value="1"/>
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_cNskc9o2EdqRBPR5WyT36A"/>
+ </ownedAttribute>
+ </ownedMember>
+ <ownedMember xmi:type="uml:Class" xmi:id="_1yyMcNovEdqRBPR5WyT36A" name="ModuleScopeContext" clientDependency="_3IW4QNovEdqRBPR5WyT36A">
+ <implementation xmi:id="_3IW4QNovEdqRBPR5WyT36A" client="_1yyMcNovEdqRBPR5WyT36A" supplier="_z_g4ANovEdqRBPR5WyT36A" realizingClassifier="_z_g4ANovEdqRBPR5WyT36A" contract="_z_g4ANovEdqRBPR5WyT36A">
+ <mapping xmi:id="_3IW4QdovEdqRBPR5WyT36A"/>
+ </implementation>
+ <ownedAttribute xmi:id="_99uwcdo2EdqRBPR5WyT36A" name="scoperegistry" visibility="private" type="_o2gxANo0EdqRBPR5WyT36A" association="_99uwcNo2EdqRBPR5WyT36A">
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_99uwdNo2EdqRBPR5WyT36A" value="1"/>
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_99uwc9o2EdqRBPR5WyT36A"/>
+ </ownedAttribute>
+ </ownedMember>
+ <ownedMember xmi:type="uml:Class" xmi:id="_4WMkYNovEdqRBPR5WyT36A" name="HTTPSessionScopeContext" clientDependency="_9XeF4NovEdqRBPR5WyT36A">
+ <implementation xmi:id="_9XeF4NovEdqRBPR5WyT36A" client="_4WMkYNovEdqRBPR5WyT36A" supplier="_z_g4ANovEdqRBPR5WyT36A" realizingClassifier="_z_g4ANovEdqRBPR5WyT36A" contract="_z_g4ANovEdqRBPR5WyT36A">
+ <mapping xmi:id="_9XeF4dovEdqRBPR5WyT36A"/>
+ </implementation>
+ <ownedAttribute xmi:id="_9PH-Ado2EdqRBPR5WyT36A" name="scoperegistry" visibility="private" type="_o2gxANo0EdqRBPR5WyT36A" association="_9PH-ANo2EdqRBPR5WyT36A">
+ <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_9PH-BNo2EdqRBPR5WyT36A" value="1"/>
+ <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_9PH-A9o2EdqRBPR5WyT36A"/>
+ </ownedAttribute>
+ </ownedMember>
+ <ownedMember xmi:type="uml:Association" xmi:id="_Bj8GUNowEdqRBPR5WyT36A" memberEnd="_Bj8GUdowEdqRBPR5WyT36A _Bj8GUtowEdqRBPR5WyT36A">
+ <ownedEnd xmi:id="_Bj8GUtowEdqRBPR5WyT36A" visibility="private" type="_tZF9oNovEdqRBPR5WyT36A" association="_Bj8GUNowEdqRBPR5WyT36A"/>
+ </ownedMember>
+ <ownedMember xmi:type="uml:Association" xmi:id="_FdlRYNowEdqRBPR5WyT36A" memberEnd="_FdlRYdowEdqRBPR5WyT36A _FdlRYtowEdqRBPR5WyT36A">
+ <ownedEnd xmi:id="_FdlRYtowEdqRBPR5WyT36A" visibility="private" type="_ePDcYNovEdqRBPR5WyT36A" association="_FdlRYNowEdqRBPR5WyT36A"/>
+ </ownedMember>
+ <ownedMember xmi:type="uml:Interface" xmi:id="_o2gxANo0EdqRBPR5WyT36A" name="ScopeRegistry"/>
+ <ownedMember xmi:type="uml:Interface" xmi:id="_Mz_E8No1EdqRBPR5WyT36A" name="Lifecycle"/>
+ <ownedMember xmi:type="uml:Interface" xmi:id="_TI7NwNo1EdqRBPR5WyT36A" name="InstanceWrapper">
+ <generalization xmi:id="_V7zlENo1EdqRBPR5WyT36A" general="_Mz_E8No1EdqRBPR5WyT36A"/>
+ </ownedMember>
+ <ownedMember xmi:type="uml:Association" xmi:id="_cNskcNo2EdqRBPR5WyT36A" memberEnd="_cNskcdo2EdqRBPR5WyT36A _cNskcto2EdqRBPR5WyT36A">
+ <ownedEnd xmi:id="_cNskcto2EdqRBPR5WyT36A" visibility="private" type="_z_g4ANovEdqRBPR5WyT36A" association="_cNskcNo2EdqRBPR5WyT36A"/>
+ </ownedMember>
+ <ownedMember xmi:type="uml:AssociationClass" xmi:id="_pdHMENo2EdqRBPR5WyT36A" name="AssociationClass1" memberEnd="_pdTZUNo2EdqRBPR5WyT36A _pdTZUdo2EdqRBPR5WyT36A">
+ <ownedEnd xmi:id="_pdTZUNo2EdqRBPR5WyT36A" visibility="private" type="_cNskcNo2EdqRBPR5WyT36A" association="_pdHMENo2EdqRBPR5WyT36A"/>
+ <ownedEnd xmi:id="_pdTZUdo2EdqRBPR5WyT36A" visibility="private" type="_ePDcYNovEdqRBPR5WyT36A" association="_pdHMENo2EdqRBPR5WyT36A"/>
+ </ownedMember>
+ <ownedMember xmi:type="uml:Association" xmi:id="_9PH-ANo2EdqRBPR5WyT36A" memberEnd="_9PH-Ado2EdqRBPR5WyT36A _9PH-Ato2EdqRBPR5WyT36A">
+ <ownedEnd xmi:id="_9PH-Ato2EdqRBPR5WyT36A" visibility="private" type="_4WMkYNovEdqRBPR5WyT36A" association="_9PH-ANo2EdqRBPR5WyT36A"/>
+ </ownedMember>
+ <ownedMember xmi:type="uml:Association" xmi:id="_99uwcNo2EdqRBPR5WyT36A" memberEnd="_99uwcdo2EdqRBPR5WyT36A _99uwcto2EdqRBPR5WyT36A">
+ <ownedEnd xmi:id="_99uwcto2EdqRBPR5WyT36A" visibility="private" type="_1yyMcNovEdqRBPR5WyT36A" association="_99uwcNo2EdqRBPR5WyT36A"/>
+ </ownedMember>
+</uml:Model>
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/ComponentContextFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/ComponentContextFactory.java new file mode 100644 index 0000000000..2a690dbf0d --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/ComponentContextFactory.java @@ -0,0 +1,38 @@ +/* + * 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.context; + +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.oasisopen.sca.ComponentContext; + +/** + * Interface implemented by the provider of the ComponentContext. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface ComponentContextFactory { + /** + * Create an instance of ComponentContext + * + * @param component The runtime component + * @return An instance of ComponentContext for the component + */ + ComponentContext createComponentContext(CompositeContext compositeContext, RuntimeComponent component); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/CompositeContext.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/CompositeContext.java new file mode 100644 index 0000000000..23a50e5f22 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/CompositeContext.java @@ -0,0 +1,152 @@ +/* + * 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.context; + +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.definitions.Definitions; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.EndpointRegistry; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentContext; + +/** + * The context associated with the Node that provides access to ExtensionPointRegistry and EndpointRegistry + * + * @version $Rev$ $Date$ + */ +public class CompositeContext { + protected final static InheritableThreadLocal<CompositeContext> context = new InheritableThreadLocal<CompositeContext>(); + protected ExtensionPointRegistry extensionPointRegistry; + protected EndpointRegistry endpointRegistry; + protected ComponentContextFactory componentContextFactory; + protected Composite domainComposite; + protected String nodeURI; + protected String domainURI; + protected Definitions systemDefinitions; + + public CompositeContext(ExtensionPointRegistry registry, EndpointRegistry endpointRegistry, Composite domainComposite, String domainURI, String nodeURI, Definitions systemDefinitions) { + this.extensionPointRegistry = registry; + this.endpointRegistry = endpointRegistry; + ContextFactoryExtensionPoint contextFactories = registry.getExtensionPoint(ContextFactoryExtensionPoint.class); + this.componentContextFactory = contextFactories.getFactory(ComponentContextFactory.class); + this.domainComposite = domainComposite; + this.domainURI = domainURI; + this.nodeURI = nodeURI; + this.systemDefinitions = systemDefinitions; + } + + public CompositeContext(ExtensionPointRegistry registry, EndpointRegistry endpointRegistry) { + this(registry, endpointRegistry, null, "default", "default", null); + } + + /** + * @return + */ + public static RuntimeComponent getCurrentComponent() { + Message message = ThreadMessageContext.getMessageContext(); + if (message != null) { + Endpoint to = message.getTo(); + if (to == null) { + return null; + } + RuntimeComponent component = (RuntimeComponent)message.getTo().getComponent(); + return component; + } + return null; + } + + /** + * @return + */ + public static CompositeContext getCurrentCompositeContext() { + RuntimeComponent component = getCurrentComponent(); + if (component != null) { + RuntimeComponentContext componentContext = component.getComponentContext(); + return componentContext.getCompositeContext(); + } + CompositeContext compositeContext = context.get(); + if (compositeContext != null) { + return compositeContext; + } + return null; + } + + public void bindComponent(RuntimeComponent runtimeComponent) { + RuntimeComponentContext componentContext = + (RuntimeComponentContext)componentContextFactory.createComponentContext(this, runtimeComponent); + runtimeComponent.setComponentContext(componentContext); + } + /** + * + * @param endpointReference + */ + public void bindEndpointReference(EndpointReference endpointReference) { + + } + + /** + * Get the ExtensionPointRegistry for this node + * @return The ExtensionPointRegistry + */ + public ExtensionPointRegistry getExtensionPointRegistry() { + return extensionPointRegistry; + } + + /** + * Get the EndpointRegistry + * @return The EndpointRegistry for this node + */ + public EndpointRegistry getEndpointRegistry() { + return endpointRegistry; + } + + public Composite getDomainComposite() { + return domainComposite; + } + + public static void setThreadCompositeContext(CompositeContext value) { + context.set(value); + } + + public static void removeCompositeContext() { + context.remove(); + } + + public String getNodeURI() { + return nodeURI; + } + + public String getDomainURI() { + return domainURI; + } + + /** + * The system definitions that result from starting the runtime. + * TODO - these can be null when the SCAClient starts the runtime + * + * @return systemDefinitions + */ + public Definitions getSystemDefinitions() { + return systemDefinitions; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/ContextFactoryExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/ContextFactoryExtensionPoint.java new file mode 100644 index 0000000000..ddcc46a1ac --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/ContextFactoryExtensionPoint.java @@ -0,0 +1,51 @@ +/* + * 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.context; + +/** + * An extension point for context factories. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface ContextFactoryExtensionPoint { + + /** + * Add a context factory extension. + * + * @param factory The factory to add + */ + void addFactory(Object factory); + + /** + * Remove a context factory extension. + * + * @param factory The factory to remove + */ + void removeFactory(Object factory); + + /** + * Get a factory implementing the given interface. + * @param factoryInterface the lookup key (factory interface) + * @return The factory + */ + <T> T getFactory(Class<T> factoryInterface); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/DefaultContextFactoryExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/DefaultContextFactoryExtensionPoint.java new file mode 100644 index 0000000000..50882c9498 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/DefaultContextFactoryExtensionPoint.java @@ -0,0 +1,115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.context; + +import java.lang.reflect.Constructor; +import java.util.HashMap; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; + +/** + * Default implementation of a model factory extension point. + * + * @version $Rev$ $Date$ + */ +public class DefaultContextFactoryExtensionPoint implements ContextFactoryExtensionPoint { + + /** + * The Map of Factories that have been registered. + */ + private HashMap<Class<?>, Object> factories = new HashMap<Class<?>, Object>(); + + private ExtensionPointRegistry registry; + + public DefaultContextFactoryExtensionPoint(ExtensionPointRegistry registry) { + this.registry = registry; + } + + /** + * Add a model factory extension. + * + * @param factory The factory to add. + * @throws IllegalArgumentException if factory is null + */ + public void addFactory(Object factory) throws IllegalArgumentException { + if (factory == null) { + throw new IllegalArgumentException("Cannot add null as a factory"); + } + + Class<?>[] interfaces = factory.getClass().getInterfaces(); + for (int i = 0; i<interfaces.length; i++) { + factories.put(interfaces[i], factory); + } + } + + /** + * Remove a model factory extension. + * + * @param factory The factory to remove + * @throws IllegalArgumentException if factory is null + */ + public void removeFactory(Object factory) throws IllegalArgumentException { + if (factory == null) { + throw new IllegalArgumentException("Cannot remove null as a factory"); + } + + Class<?>[] interfaces = factory.getClass().getInterfaces(); + for (int i = 0; i<interfaces.length; i++) { + factories.remove(interfaces[i]); + } + } + + /** + * Get a factory implementing the given interface. + * + * @param factoryInterface The lookup key (factory interface) + * @return The factory + */ + public <T> T getFactory(Class<T> factoryInterface) throws IllegalArgumentException { + if (factoryInterface == null) { + throw new IllegalArgumentException("Cannot get null as a factory"); + } + + Object factory = factories.get(factoryInterface); + if (factory == null) { + + // Dynamically load a factory class declared under META-INF/services + try { + ServiceDeclaration factoryDeclaration = registry.getServiceDiscovery().getServiceDeclaration(factoryInterface.getName()); + if (factoryDeclaration != null) { + Class<?> factoryClass = factoryDeclaration.loadClass(); + + // Default empty constructor + Constructor<?> constructor = factoryClass.getConstructor(ExtensionPointRegistry.class); + factory = constructor.newInstance(registry); + + // Cache the loaded factory + addFactory(factory); + } + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + + } + + return factoryInterface.cast(factory); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/PropertyValueFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/PropertyValueFactory.java new file mode 100644 index 0000000000..5b91db124c --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/PropertyValueFactory.java @@ -0,0 +1,42 @@ +/* + * 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.context; + +import org.apache.tuscany.sca.assembly.ComponentProperty; + +/** + * Interface implemented by the provider of the property values + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + * @tuscany.spi.extension.inheritfrom + */ +public interface PropertyValueFactory { + + /** + * This method will create an instance of the value for the specified Property. + * + * @param property The Property from which to retrieve the property value + * @param type The type of the property value being retrieved from the Property + * @param <B> Type type of the property value being looked up + * + * @return the value for the Property + */ + <B> B createPropertyValue(ComponentProperty property, Class<B> type); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/RequestContextFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/RequestContextFactory.java new file mode 100644 index 0000000000..4475427d4b --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/RequestContextFactory.java @@ -0,0 +1,35 @@ +/* + * 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.context; + +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.oasisopen.sca.RequestContext; + +/** + * Interface implemented by the provider of the RequestContext. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface RequestContextFactory { + /** + * @return An instance of RequestContext for the current invocation + */ + RequestContext createRequestContext(RuntimeComponent component); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/ThreadMessageContext.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/ThreadMessageContext.java new file mode 100644 index 0000000000..d6237b7ce3 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/context/ThreadMessageContext.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.context; + +import org.apache.tuscany.sca.invocation.Message; + +/** + * Class for tunnelling a WorkContext through the invocation of a user class. + * + * @version $Rev$ $Date$ + */ +public final class ThreadMessageContext { + + private static final ThreadLocal<Message> CONTEXT = new ThreadLocal<Message>(); + + private ThreadMessageContext() { + } + + public static Message setMessageContext(Message context) { + Message old = CONTEXT.get(); + CONTEXT.set(context); + return old; + } + + /** + * Returns the WorkContext for the current thread. + * + * @return the WorkContext for the current thread + */ + public static Message getMessageContext() { + return CONTEXT.get(); + } + + /** + * Removes and state from the current thread to ensure that + * any associated classloaders can be GCd + */ + public static void removeMessageContext() { + CONTEXT.remove(); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/DataExchangeSemantics.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/DataExchangeSemantics.java new file mode 100644 index 0000000000..957a15ce8a --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/DataExchangeSemantics.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.invocation; + +/** + * An invoker or interceptor can optionally implement this interface to indicate if they can + * enforce the pass-by-value semantics for an operation on remotable interfaces. + * + * @version $Rev$ $Date$ + */ +public interface DataExchangeSemantics { + /** + * Indicate if the data can be passed in by reference as they won't be mutated. + * @return true if pass-by-reference is allowed + */ + boolean allowsPassByReference(); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/Interceptor.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/Interceptor.java new file mode 100644 index 0000000000..42954555b1 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/Interceptor.java @@ -0,0 +1,41 @@ +/* + * 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.invocation; + +/** + * Synchronous mediation associated with a client- or target- side wire. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public interface Interceptor extends Invoker { + + /** + * Sets the next invoker + * @param next The next invoker + */ + void setNext(Invoker next); + + /** + * Returns the next invoker or null + * @return The next Invoker + */ + Invoker getNext(); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/InvocationChain.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/InvocationChain.java new file mode 100644 index 0000000000..579e0c3da9 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/InvocationChain.java @@ -0,0 +1,108 @@ +/* + * 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.invocation; + +import org.apache.tuscany.sca.interfacedef.Operation; + +/** + * A wire consists of 1..n invocation chains associated with the operations of its source service contract. + * <p/> + * Invocation chains may contain <code>Interceptors</code> that process invocations. + * <p/> + * A <code>Message</code> is used to pass data associated with an invocation through the chain. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface InvocationChain { + /** + * Returns the target operation for this invocation chain. + * + * @return The target operation for this invocation chain + */ + Operation getTargetOperation(); + + /** + * Updates the target operation for this invocation chain. + * + * @param operation The new target operation for this invocation chain + */ + void setTargetOperation(Operation operation); + + /** + * Returns the source operation for this invocation chain. + * + * @return The source operation for this invocation chain + */ + Operation getSourceOperation(); + + /** + * Updates the source operation for this invocation chain. + * + * @param operation The new source operation for this invocation chain + */ + void setSourceOperation(Operation operation); + + /** + * Adds an interceptor to the chain. For reference side, it will be added to + * Phase.REFERENCE. For service side, it will be added to Phase.SERVICE + * + * @param interceptor The interceptor to add + */ + void addInterceptor(Interceptor interceptor); + + /** + * Adds an invoker to the chain + * + * @param invoker The invoker to add + */ + void addInvoker(Invoker invoker); + + /** + * Returns the first invoker in the chain. + * + * @return The first invoker in the chain + */ + Invoker getHeadInvoker(); + + /** + * Get the first invoker that is on the same or later phase + * @param phase + * @return The first invoker that is on the same or later phase + */ + Invoker getHeadInvoker(String phase); + + /** + * Add an interceptor to the given phase + * @param phase + * @param interceptor + */ + void addInterceptor(String phase, Interceptor interceptor); + + /** + * Indicate if the data can be passed in by reference as they won't be mutated. + * @return true if pass-by-reference is allowed + */ + boolean allowsPassByReference(); + /** + * Force the invocation to allow pass-by-reference + * @param allowsPBR + */ + void setAllowsPassByReference(boolean allowsPBR); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/Invoker.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/Invoker.java new file mode 100644 index 0000000000..69309f6dd0 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/Invoker.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.invocation; + +/** + * Synchronous mediation associated with a client- or target- side wire. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public interface Invoker { + + /** + * Process a synchronous wire + * + * @param msg The request Message for the wire + * @return The response Message from the wire + */ + Message invoke(Message msg); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/Message.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/Message.java new file mode 100644 index 0000000000..2bafdb64b8 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/Message.java @@ -0,0 +1,129 @@ +/* + * 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.invocation; + +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.interfacedef.Operation; + +/** + * Represents a request, response, or exception flowing through a wire + * + * @version $Rev $Date$ + * @tuscany.spi.extension.asclient + */ +public interface Message { + + /** + * Returns the body of the message, which will be the payload or parameters associated with the wire + * @return The body of the message + */ + <T> T getBody(); + + /** + * Sets the body of the message. + * @param body The body of the message + */ + <T> void setBody(T body); + + /** + * Get the end point reference of the source reference + * @return The end point reference of the reference originating the message + */ + EndpointReference getFrom(); + + /** + * Set the end point reference of the reference originating the message + * @param from The end point reference of the reference originating the message + */ + void setFrom(EndpointReference from); + + /** + * Get the end point reference of target service + * @return The end point reference of the service that the message targets + */ + Endpoint getTo(); + + /** + * Set the end point reference of target service + * @param to The end point reference of the service that the message targets + */ + void setTo(Endpoint to); + + /** + * Returns the id of the message + * @return The message Id + */ + Object getMessageID(); + + /** + * Sets the id of the message + * @param messageId The message ID + */ + void setMessageID(Object messageId); + + /** + * Determines if the message represents a fault/exception + * + * @return true If the message body is a fault object, false if the body is a normal payload + */ + boolean isFault(); + + /** + * Set the message body with a fault object. After this method is called, isFault() returns true. + * + * @param fault The fault object represents an exception + */ + <T> void setFaultBody(T fault); + + /** + * Returns the operation that created the message. + * + * @return The operation that created the message + */ + Operation getOperation(); + + /** + * Sets the operation that created the message. + * + * @param op The operation that created the message + */ + void setOperation(Operation op); + + /** + * Returns a list of objects that are contained in the message header + * + * @return + */ + Map<String, Object> getHeaders(); + + /** + * Returns the binding context in force for this message + */ + <T> T getBindingContext(); + + /** + * Set the binding context that is in force for this message + * @param bindingContext + */ + <T> void setBindingContext(T bindingContext); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/MessageFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/MessageFactory.java new file mode 100644 index 0000000000..711c09728b --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/MessageFactory.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.invocation; + + +/** + * A factory for messages + * + * @version $Rev $Date$ + * @tuscany.spi.extension.asclient + */ +public interface MessageFactory { + + /** + * Creates a new message. + * + * @return The new message + */ + Message createMessage(); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/Phase.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/Phase.java new file mode 100644 index 0000000000..8bb81b7eda --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/Phase.java @@ -0,0 +1,60 @@ +/* + * 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.invocation; + +/** + * Tuscany built-in phases for the invocation chain. The phases are organized + * here such that a message passing from reference component implementation to + * service component implementation passes through the phases from top to bottom + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface Phase { + + // Reference operation chains + + String REFERENCE = "component.reference"; // The first phase for outgoing invocations via a reference + String REFERENCE_INTERFACE = "reference.interface"; // data transformation and validation + String REFERENCE_POLICY = "reference.policy"; // reference policy handling + String REFERENCE_BINDING = "reference.binding"; // reference binding invoker + + // Reference binding chain + + String REFERENCE_BINDING_WIREFORMAT = "reference.binding.wireformat"; + String REFERENCE_BINDING_POLICY = "reference.binding.policy"; + String REFERENCE_BINDING_TRANSPORT = "reference.binding.transport"; + + // Service binding chain + + String SERVICE_BINDING_TRANSPORT = "service.binding.transport"; + String SERVICE_BINDING_OPERATION_SELECTOR = "service.binding.operationselector"; + String SERVICE_BINDING_WIREFORMAT = "service.binding.wireformat"; + String SERVICE_BINDING_POLICY = "service.binding.policy"; + + // Service operation chains + + String SERVICE_BINDING = "service.binding"; // The first phase for incoming invocations via a service + String SERVICE_POLICY = "service.policy"; // service policy handling + String SERVICE_INTERFACE = "service.interface"; // data validation and transformation + String SERVICE = "component.service"; // TODO: not sure if we need to have this phase + String IMPLEMENTATION_POLICY = "implementation.policy"; // implementation policy handling + String IMPLEMENTATION = "component.implementation"; // implementation invoker +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/PhasedInterceptor.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/PhasedInterceptor.java new file mode 100644 index 0000000000..f77a662779 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/invocation/PhasedInterceptor.java @@ -0,0 +1,32 @@ +/* + * 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.invocation; + +/** + * An interceptor that is designated to be a given phase + * @tuscany.spi.extension.inheritfrom + */ +public interface PhasedInterceptor extends Interceptor { + /** + * Get the name of the phase that this interceptor is positioned + * @return + */ + String getPhase(); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/management/ConfigAttributes.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/management/ConfigAttributes.java new file mode 100644 index 0000000000..7d20ec7fc0 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/management/ConfigAttributes.java @@ -0,0 +1,26 @@ +/* + * 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.management; + +import java.util.Map; + +public interface ConfigAttributes { + Map<String, String> getAttributes(); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/management/ManagementService.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/management/ManagementService.java new file mode 100644 index 0000000000..3887db4873 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/management/ManagementService.java @@ -0,0 +1,39 @@ +/* + * 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.management; + +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * Interface for the management service abstraction. The implementation + * could be based on a variety of technologies including JMX, WSDM, + * SNMP etc. + * + * @version $Revision$ $Date$ + */ +public interface ManagementService { + + /** + * Registers a component for management. + * + * @param name Name of the component. + * @param component Component to be registered. + */ + void registerComponent(String name, RuntimeComponent component); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/BasePolicyProvider.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/BasePolicyProvider.java new file mode 100644 index 0000000000..d4fcc0e8fc --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/BasePolicyProvider.java @@ -0,0 +1,186 @@ +/* + * 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.provider; + +import java.security.Policy; +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.PhasedInterceptor; +import org.apache.tuscany.sca.policy.PolicyContainer; +import org.apache.tuscany.sca.policy.PolicyExpression; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.policy.PolicySubject; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; + +/** + * Abstract base class for policy providers + * @tuscany.spi.extension.inheritfrom + */ +public abstract class BasePolicyProvider<T> implements PolicyProvider { + protected Class<T> policyType; + protected PolicySubject subject; + + protected BasePolicyProvider(Class<T> policyType, PolicySubject subject) { + this.policyType = policyType; + this.subject = subject; + } + + protected List<T> findPolicies() { + List<T> policies = new ArrayList<T>(); + List<PolicySet> policySets = subject.getPolicySets(); + for (PolicySet ps : policySets) { + for (Object p : ps.getPolicies()) { + if (policyType.isInstance(p)) { + policies.add(policyType.cast(p)); + } + + if (p instanceof PolicyExpression) { + PolicyExpression exp = (PolicyExpression)p; + if (policyType.isInstance(exp.getPolicy())) { + policies.add(policyType.cast(exp.getPolicy())); + } + + // TODO - some code to handle the case where the + // policy expression is a WS-Policy + // Experimental at the moment. + if (PolicyContainer.class.isInstance(exp.getPolicy())){ + Object policy = ((PolicyContainer)exp.getPolicy()).getChildPolicy(policyType); + if(policy != null){ + policies.add(policyType.cast(policy)); + } + } + } + } + } + return policies; + } + + protected List<PolicySet> findPolicySets() { + List<PolicySet> policies = new ArrayList<PolicySet>(); + List<PolicySet> policySets = subject.getPolicySets(); + for (PolicySet ps : policySets) { + for (Object p : ps.getPolicies()) { + if (policyType.isInstance(p)) { + policies.add(ps); + } + if (p instanceof PolicyExpression) { + PolicyExpression exp = (PolicyExpression)p; + if (policyType.isInstance(exp.getPolicy())) { + policies.add(ps); + } + } + } + } + return policies; + } + + protected PolicySet findPolicySet() { + List<PolicySet> policySets = subject.getPolicySets(); + for (PolicySet ps : policySets) { + for (Object p : ps.getPolicies()) { + if (policyType.isInstance(p)) { + return ps; + } + if (p instanceof PolicyExpression) { + PolicyExpression exp = (PolicyExpression)p; + if (policyType.isInstance(exp.getPolicy())) { + return ps; + } + } + } + } + return null; + } + + protected String getContext() { + if (subject instanceof Endpoint) { + Endpoint endpoint = (Endpoint)subject; + return endpoint.getURI(); + } else if (subject instanceof EndpointReference) { + EndpointReference endpointReference = (EndpointReference)subject; + return endpointReference.getURI(); + } else if (subject instanceof Component) { + Component component = (Component)subject; + return component.getURI(); + } + return null; + } + + public void start() { + } + + public void stop() { + } + + public PhasedInterceptor createInterceptor(Operation operation) { + return null; + } + + public PhasedInterceptor createBindingInterceptor() { + return null; + } + + public void configureBinding(Object configuration){ + } + + protected InvocationChain getInvocationChain() { + if (subject instanceof RuntimeEndpoint) { + RuntimeEndpoint endpoint = (RuntimeEndpoint)subject; + List<InvocationChain> chains = endpoint.getInvocationChains(); + for (InvocationChain chain : chains) { + configure(chain, chain.getTargetOperation()); + } + + } else if (subject instanceof RuntimeEndpointReference) { + RuntimeEndpointReference endpointReference = (RuntimeEndpointReference)subject; + List<InvocationChain> chains = endpointReference.getInvocationChains(); + for (InvocationChain chain : chains) { + configure(chain, chain.getSourceOperation()); + } + } else if (subject instanceof RuntimeComponent) { + RuntimeComponent component = (RuntimeComponent)subject; + for (ComponentService s : component.getServices()) { + RuntimeComponentService service = (RuntimeComponentService)s; + for (Endpoint ep : service.getEndpoints()) { + List<InvocationChain> chains = ((RuntimeEndpoint)ep).getInvocationChains(); + for (InvocationChain chain : chains) { + configure(chain, chain.getTargetOperation()); + } + } + + } + } + return null; + } + + protected void configure(InvocationChain invocationChain, Operation operation) { + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/BindingPolicyProvider.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/BindingPolicyProvider.java new file mode 100644 index 0000000000..5f2e6bd315 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/BindingPolicyProvider.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.provider; + +import org.apache.tuscany.sca.invocation.PhasedInterceptor; + +/** + * TODO RRB experiment + * This is an experiment extension to try out the request response + * binding function + * @version $Rev$ $Date$ + */ +public interface BindingPolicyProvider extends PolicyProvider { + /** + * Create a binding interceptor + * @return An interceptor that realize the policySet + */ + PhasedInterceptor createBindingInterceptor(); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/BindingProviderFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/BindingProviderFactory.java new file mode 100644 index 0000000000..36e34c11b7 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/BindingProviderFactory.java @@ -0,0 +1,51 @@ +/* + * 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.provider; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; + +/** + * A factory for creating the runtime artifacts that represent bindings. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public interface BindingProviderFactory<M extends Binding> extends ProviderFactory<M> { + + /** + * Creates a new reference binding provider for the given endpoint reference + * + * @param endpointReference defines the component/reference/binding against which to create the provider + * @return The binding provider + */ + ReferenceBindingProvider createReferenceBindingProvider(RuntimeEndpointReference endpointReference); + + /** + * Creates a new service binding provider for the given component and + * service. + * + * @param endpoint defines the component/service/binding against which to create the provider + * @return The binding provider + */ + ServiceBindingProvider createServiceBindingProvider(RuntimeEndpoint endpoint); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/DefaultProviderFactoryExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/DefaultProviderFactoryExtensionPoint.java new file mode 100644 index 0000000000..6aad6786e3 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/DefaultProviderFactoryExtensionPoint.java @@ -0,0 +1,500 @@ +/* + * 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.provider; + +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; + +/** + * Default implementation of a provider factory extension point. + * + * @version $Rev$ $Date$ + */ +public class DefaultProviderFactoryExtensionPoint implements ProviderFactoryExtensionPoint { + + private ExtensionPointRegistry registry; + private final Map<Class<?>, ProviderFactory> providerFactories = new HashMap<Class<?>, ProviderFactory>(); + private final List<PolicyProviderFactory> policyProviderFactories = new ArrayList<PolicyProviderFactory>(); + private boolean loaded; + + /** + * The default constructor. Does nothing. + * + */ + public DefaultProviderFactoryExtensionPoint(ExtensionPointRegistry registry) { + this.registry = registry; + } + + /** + * Add a provider factory. + * + * @param providerFactory The provider factory + */ + public void addProviderFactory(ProviderFactory providerFactory) { + if(providerFactory instanceof PolicyProviderFactory) { + policyProviderFactories.add((PolicyProviderFactory)providerFactory); + } + providerFactories.put(providerFactory.getModelType(), providerFactory); + } + + /** + * Remove a provider factory. + * + * @param providerFactory The provider factory + */ + public void removeProviderFactory(ProviderFactory providerFactory) { + if(providerFactory instanceof PolicyProviderFactory) { + policyProviderFactories.remove((PolicyProviderFactory)providerFactory); + } + providerFactories.remove(providerFactory.getModelType()); + } + + /** + * Returns the provider factory associated with the given model type. + * @param modelType A model type + * @return The provider factory associated with the given model type + */ + public ProviderFactory getProviderFactory(Class<?> modelType) { + loadProviderFactories(); + + Class<?>[] classes = modelType.getInterfaces(); + for (Class<?> c : classes) { + ProviderFactory factory = providerFactories.get(c); + if (factory != null) { + return factory; + } + } + return providerFactories.get(modelType); + } + + public List<PolicyProviderFactory> getPolicyProviderFactories() { + loadProviderFactories(); + return policyProviderFactories; + } + + public <P extends ProviderFactory> Collection<P> getProviderFactories(Class<P> factoryType) { + loadProviderFactories(); + List<P> factories = new ArrayList<P>(); + for (ProviderFactory pf : providerFactories.values()) { + if (factoryType.isInstance(pf)) { + factories.add(factoryType.cast(pf)); + } + } + return factories; + } + + /** + * Load provider factories declared under META-INF/services. + * @param registry + */ + private synchronized void loadProviderFactories() { + if (loaded) + return; + + loadProviderFactories(BindingProviderFactory.class); + loadProviderFactories(ImplementationProviderFactory.class); + loadProviderFactories(PolicyProviderFactory.class); + loadProviderFactories(WireFormatProviderFactory.class); + loadProviderFactories(OperationSelectorProviderFactory.class); + + loaded = true; + } + + /** + * Load provider factories declared under META-INF/services. + * @param registry + * @param factoryClass + * @return + */ + private List<ProviderFactory> loadProviderFactories(Class<?> factoryClass) { + + // Get the provider factory service declarations + Collection<ServiceDeclaration> factoryDeclarations; + ServiceDiscovery serviceDiscovery = registry.getServiceDiscovery(); + try { + factoryDeclarations = serviceDiscovery.getServiceDeclarations(factoryClass.getName(), true); + } catch (Exception e) { + throw new IllegalStateException(e); + } + + // Get the target extension point + ProviderFactoryExtensionPoint factoryExtensionPoint = + registry.getExtensionPoint(ProviderFactoryExtensionPoint.class); + List<ProviderFactory> factories = new ArrayList<ProviderFactory>(); + + for (ServiceDeclaration factoryDeclaration : factoryDeclarations) { + Map<String, String> attributes = factoryDeclaration.getAttributes(); + + // Load an implementation provider factory + if (factoryClass == ImplementationProviderFactory.class) { + String modelTypeName = attributes.get("model"); + + // Create a provider factory wrapper and register it + ImplementationProviderFactory factory = + new LazyImplementationProviderFactory(registry, modelTypeName, factoryDeclaration); + factoryExtensionPoint.addProviderFactory(factory); + factories.add(factory); + + } else if (factoryClass == BindingProviderFactory.class) { + + // Load a binding provider factory + String modelTypeName = attributes.get("model"); + + // Create a provider factory wrapper and register it + BindingProviderFactory factory = + new LazyBindingProviderFactory(registry, modelTypeName, factoryDeclaration); + factoryExtensionPoint.addProviderFactory(factory); + factories.add(factory); + } else if (factoryClass == PolicyProviderFactory.class) { + // Load a policy provider factory + String modelTypeName = attributes.get("model"); + + // Create a provider factory wrapper and register it + PolicyProviderFactory factory = + new LazyPolicyProviderFactory(registry, modelTypeName, factoryDeclaration); + factoryExtensionPoint.addProviderFactory(factory); + factories.add(factory); + } else if (factoryClass == WireFormatProviderFactory.class) { + + // Load a wire format provider factory + String modelTypeName = attributes.get("model"); + + // Create a provider factory wrapper and register it + WireFormatProviderFactory factory = + new LazyWireFormatProviderFactory(registry, modelTypeName, factoryDeclaration); + factoryExtensionPoint.addProviderFactory(factory); + factories.add(factory); + } else if (factoryClass == OperationSelectorProviderFactory.class) { + + // Load a wire format provider factory + String modelTypeName = attributes.get("model"); + + // Create a provider factory wrapper and register it + OperationSelectorProviderFactory factory = + new LazyOperationSelectorProviderFactory(registry, modelTypeName, factoryDeclaration); + factoryExtensionPoint.addProviderFactory(factory); + factories.add(factory); + } + } + return factories; + } + + /** + * A wrapper around an implementation provider factory allowing lazy + * loading and initialization of implementation providers. + */ + private static class LazyBindingProviderFactory implements BindingProviderFactory { + + private ExtensionPointRegistry registry; + private String modelTypeName; + private ServiceDeclaration factoryDeclaration; + private BindingProviderFactory factory; + private Class<?> modelType; + + private LazyBindingProviderFactory(ExtensionPointRegistry registry, + String modelTypeName, + ServiceDeclaration factoryDeclaration) { + this.registry = registry; + this.modelTypeName = modelTypeName; + this.factoryDeclaration = factoryDeclaration; + } + + @SuppressWarnings("unchecked") + private BindingProviderFactory getFactory() { + if (factory == null) { + try { + Class<BindingProviderFactory> factoryClass = + (Class<BindingProviderFactory>)factoryDeclaration.loadClass(); + Constructor<BindingProviderFactory> constructor = + factoryClass.getConstructor(ExtensionPointRegistry.class); + factory = constructor.newInstance(registry); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return factory; + } + + @SuppressWarnings("unchecked") + public ReferenceBindingProvider createReferenceBindingProvider(RuntimeEndpointReference endpointReference) { + return getFactory().createReferenceBindingProvider(endpointReference); + } + + @SuppressWarnings("unchecked") + public ServiceBindingProvider createServiceBindingProvider(RuntimeEndpoint endpoint) { + return getFactory().createServiceBindingProvider(endpoint); + } + + public Class<?> getModelType() { + if (modelType == null) { + try { + modelType = factoryDeclaration.loadClass(modelTypeName); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return modelType; + } + + } + + /** + * A wrapper around an implementation provider factory allowing lazy + * loading and initialization of implementation providers. + */ + private class LazyImplementationProviderFactory implements ImplementationProviderFactory { + + private ExtensionPointRegistry registry; + private String modelTypeName; + private ServiceDeclaration providerClass; + private ImplementationProviderFactory factory; + private Class<?> modelType; + + private LazyImplementationProviderFactory(ExtensionPointRegistry registry, + String modelTypeName, + ServiceDeclaration providerClass) { + this.registry = registry; + this.modelTypeName = modelTypeName; + this.providerClass = providerClass; + } + + @SuppressWarnings("unchecked") + private ImplementationProviderFactory getFactory() { + if (factory == null) { + try { + Class<ImplementationProviderFactory> factoryClass = + (Class<ImplementationProviderFactory>)providerClass.loadClass(); + Constructor<ImplementationProviderFactory> constructor = + factoryClass.getConstructor(ExtensionPointRegistry.class); + factory = constructor.newInstance(registry); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return factory; + } + + @SuppressWarnings("unchecked") + public ImplementationProvider createImplementationProvider(RuntimeComponent component, + Implementation Implementation) { + return getFactory().createImplementationProvider(component, Implementation); + } + + public Class<?> getModelType() { + if (modelType == null) { + try { + + modelType = providerClass.loadClass(modelTypeName); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return modelType; + } + + } + + /** + * A wrapper around an policy provider factory allowing lazy + * loading and initialization of policy providers. + */ + private class LazyPolicyProviderFactory implements PolicyProviderFactory { + private ExtensionPointRegistry registry; + private String modelTypeName; + private ServiceDeclaration providerClass; + private PolicyProviderFactory factory; + private Class<?> modelType; + + private LazyPolicyProviderFactory(ExtensionPointRegistry registry, + String modelTypeName, + ServiceDeclaration providerClass) { + this.registry = registry; + this.modelTypeName = modelTypeName; + this.providerClass = providerClass; + } + + @SuppressWarnings("unchecked") + private PolicyProviderFactory getFactory() { + if (factory == null) { + try { + Class<PolicyProviderFactory> factoryClass = (Class<PolicyProviderFactory>)providerClass.loadClass(); + Constructor<PolicyProviderFactory> constructor = + factoryClass.getConstructor(ExtensionPointRegistry.class); + factory = constructor.newInstance(registry); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return factory; + } + + public PolicyProvider createImplementationPolicyProvider(RuntimeComponent component) { + return getFactory().createImplementationPolicyProvider(component); + } + + public PolicyProvider createReferencePolicyProvider(EndpointReference endpointReference) { + return getFactory().createReferencePolicyProvider(endpointReference); + } + + public PolicyProvider createServicePolicyProvider(Endpoint endpoint) { + return getFactory().createServicePolicyProvider(endpoint); + } + + public Class<?> getModelType() { + if (modelType == null) { + try { + modelType = providerClass.loadClass(modelTypeName); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return modelType; + } + } + + /** + * A wrapper around a wire format provider factory allowing lazy + * loading and initialization of wire format providers. + */ + private class LazyWireFormatProviderFactory implements WireFormatProviderFactory { + + private ExtensionPointRegistry registry; + private String modelTypeName; + private ServiceDeclaration providerClass; + private WireFormatProviderFactory factory; + private Class<?> modelType; + + private LazyWireFormatProviderFactory(ExtensionPointRegistry registry, + String modelTypeName, + ServiceDeclaration providerClass) { + this.registry = registry; + this.modelTypeName = modelTypeName; + this.providerClass = providerClass; + } + + @SuppressWarnings("unchecked") + private WireFormatProviderFactory getFactory() { + if (factory == null) { + try { + Class<WireFormatProviderFactory> factoryClass = + (Class<WireFormatProviderFactory>)providerClass.loadClass(); + Constructor<WireFormatProviderFactory> constructor = + factoryClass.getConstructor(ExtensionPointRegistry.class); + factory = constructor.newInstance(registry); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return factory; + } + + public WireFormatProvider createReferenceWireFormatProvider(RuntimeEndpointReference endpointReference){ + return getFactory().createReferenceWireFormatProvider(endpointReference); + } + + public WireFormatProvider createServiceWireFormatProvider(RuntimeEndpoint endpoint){ + return getFactory().createServiceWireFormatProvider(endpoint); + } + + public Class<?> getModelType() { + if (modelType == null) { + try { + + modelType = providerClass.loadClass(modelTypeName); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return modelType; + } + } + + /** + * A wrapper around a operation selector provider factory allowing lazy + * loading and initialization of operation selector providers. + */ + private class LazyOperationSelectorProviderFactory implements OperationSelectorProviderFactory { + + private ExtensionPointRegistry registry; + private String modelTypeName; + private ServiceDeclaration providerClass; + private OperationSelectorProviderFactory factory; + private Class<?> modelType; + + private LazyOperationSelectorProviderFactory(ExtensionPointRegistry registry, + String modelTypeName, + ServiceDeclaration providerClass) { + this.registry = registry; + this.modelTypeName = modelTypeName; + this.providerClass = providerClass; + } + + @SuppressWarnings("unchecked") + private OperationSelectorProviderFactory getFactory() { + if (factory == null) { + try { + Class<OperationSelectorProviderFactory> factoryClass = + (Class<OperationSelectorProviderFactory>)providerClass.loadClass(); + Constructor<OperationSelectorProviderFactory> constructor = + factoryClass.getConstructor(ExtensionPointRegistry.class); + factory = constructor.newInstance(registry); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return factory; + } + + public OperationSelectorProvider createReferenceOperationSelectorProvider(RuntimeEndpointReference endpointReference){ + return getFactory().createReferenceOperationSelectorProvider(endpointReference); + } + + public OperationSelectorProvider createServiceOperationSelectorProvider(RuntimeEndpoint endpoint){ + return getFactory().createServiceOperationSelectorProvider(endpoint); + } + + public Class<?> getModelType() { + if (modelType == null) { + try { + + modelType = providerClass.loadClass(modelTypeName); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + return modelType; + } + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/EndpointProvider.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/EndpointProvider.java new file mode 100644 index 0000000000..a25814234a --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/EndpointProvider.java @@ -0,0 +1,35 @@ +/* + * 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.provider; + + +/** + * Defines the extra operation that service binding providers implement + * to configure the binding chain. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface EndpointProvider extends ServiceBindingProvider { + /** + * Configure the binding invocation chain + */ + void configure(); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/EndpointReferenceProvider.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/EndpointReferenceProvider.java new file mode 100644 index 0000000000..209b057859 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/EndpointReferenceProvider.java @@ -0,0 +1,36 @@ +/* + * 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.provider; + + +/** + * Defines the extra operation that reference binding providers implement + * to configure the binding chain. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public interface EndpointReferenceProvider extends ReferenceBindingProvider { + /** + * Configure the binding invocation chain + */ + void configure(); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/ImplementationProvider.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/ImplementationProvider.java new file mode 100644 index 0000000000..4e9fddb135 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/ImplementationProvider.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.provider; + +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +/** + * A component implementation can implement this interface in order to tie + * into the Tuscany runtime + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public interface ImplementationProvider extends RuntimeProvider { + + /** + * Create an invoker for the component implementation in the invocation + * chain. The invoker will be responsible for calling the implementation + * logic for the given component. + * + * @param service The component service + * @param operation The operation that the interceptor will handle + * @return An invoker that handles the invocation logic, null should be + * returned if no invoker is required + */ + Invoker createInvoker(RuntimeComponentService service, Operation operation); + + /** + * For bindings that invoke one-way callback operations asynchronously, + * there is no need to perform a thread switch before calling the invoker. + * This method indicates whether the binding has this capability. + * + * @return true if the callback invoker is able to invoke one-way operations + * asynchronously, false if all invocations are synchronous + */ + boolean supportsOneWayInvocation(); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/ImplementationProviderFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/ImplementationProviderFactory.java new file mode 100644 index 0000000000..cfb06d9c70 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/ImplementationProviderFactory.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.provider; + +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * An interface for factories that create implementation providers. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public interface ImplementationProviderFactory<M extends Implementation> extends ProviderFactory<M> { + + /** + * Creates a new implementation provider for the given + * component. + * + * @param component The runtime component + * @param Implementation The implementation type + * @return The implementation provider + */ + ImplementationProvider createImplementationProvider(RuntimeComponent component, M Implementation); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/OperationSelectorProvider.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/OperationSelectorProvider.java new file mode 100644 index 0000000000..c0346780d8 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/OperationSelectorProvider.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.provider; + +import org.apache.tuscany.sca.invocation.Interceptor; + +/** + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public interface OperationSelectorProvider { + /** + * Create an interceptor for the operation selector + * @return An interceptor that realize the policySet + */ + Interceptor createInterceptor(); + + /** + * Get the phase that the interceptor should be added + * @return The phase that this interceptor belongs to + */ + String getPhase(); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/OperationSelectorProviderFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/OperationSelectorProviderFactory.java new file mode 100644 index 0000000000..43ea8d171b --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/OperationSelectorProviderFactory.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.provider; + +import org.apache.tuscany.sca.assembly.OperationSelector; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; + +/** + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public interface OperationSelectorProviderFactory<M extends OperationSelector> extends ProviderFactory<M> { + /** + * Create wire format provider for a given reference binding + * @param endpointReference TODO + * @return + */ + OperationSelectorProvider createReferenceOperationSelectorProvider(RuntimeEndpointReference endpointReference); + + /** + * Create policy provider for a given service binding + * @param endpoint TODO + * @return + */ + OperationSelectorProvider createServiceOperationSelectorProvider(RuntimeEndpoint endpoint); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyImplementor.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyImplementor.java new file mode 100644 index 0000000000..f2b59a7c54 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyImplementor.java @@ -0,0 +1,38 @@ +/* + * 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.provider; + +import java.util.List; + +import javax.xml.namespace.QName; + +/** + * This interface can be optionally implemented by the Binding or Implementation providers to + * indicate if they implement the policies in the binding/implementation provider. + * + * @version $Rev$ $Date$ + */ +public interface PolicyImplementor { + /** + * Get a list of policy names that are implemented by this policy implementor + * @return A list of policy names + */ + List<QName> getImplementedPolicies(); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyProvider.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyProvider.java new file mode 100644 index 0000000000..de0b62eecd --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyProvider.java @@ -0,0 +1,55 @@ +/* + * 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.provider; + +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.PhasedInterceptor; + +/** + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface PolicyProvider extends RuntimeProvider { + /** + * Create an interceptor for a given operation + * + * @param operation + * @return An interceptor that realizes the policySet + */ + PhasedInterceptor createInterceptor(Operation operation); + + /** + * Create a binding interceptor. The binding wire is + * not operation specific so an operation parameter + * isn't required + * + * @return An interceptor that realizes the policySet + */ + PhasedInterceptor createBindingInterceptor(); + + /** + * Give the provider an opportunity to affect the + * binding configuration if required + * + * @param configurationContext the configuration context of the + * binding that will be modified + */ + void configureBinding(Object configuration); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyProviderFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyProviderFactory.java new file mode 100644 index 0000000000..134df1c37e --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/PolicyProviderFactory.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.provider; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public interface PolicyProviderFactory<M> extends ProviderFactory<M> { + /** + * Create policy provider for a given reference binding + * @param endpointReference The endpoint reference + * @return A policy provider for the endpoint reference + */ + PolicyProvider createReferencePolicyProvider(EndpointReference endpointReference); + + /** + * Create policy provider for a given service binding + * @param endpoint The endpoint + * @return A policy provider for the endpoint + */ + PolicyProvider createServicePolicyProvider(Endpoint endpoint); + + /** + * Create policy provider for a given component implementation + * @param component + * @return A policy provider for the implementation + */ + PolicyProvider createImplementationPolicyProvider(RuntimeComponent component); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/ProviderFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/ProviderFactory.java new file mode 100644 index 0000000000..2102806881 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/ProviderFactory.java @@ -0,0 +1,36 @@ +/* + * 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.provider; + +/** + * A factory for runtime providers. + * + * @version $Rev$ $Date$ + */ +public interface ProviderFactory<M> { + + /** + * The model type that this factory creates providers for. + * + * @return the model type + */ + Class<M> getModelType(); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/ProviderFactoryExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/ProviderFactoryExtensionPoint.java new file mode 100644 index 0000000000..75c5544aa3 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/ProviderFactoryExtensionPoint.java @@ -0,0 +1,74 @@ +/* + * 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.provider; + +import java.util.Collection; +import java.util.List; + + +/** + * An extension point for provider factories. Holds all of the provider + * factories from loaded extension points. Allows a provider factory + * to be located based on a given model type. Hence the runtime can + * generate runtime artifacts from the in memory assembly model. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface ProviderFactoryExtensionPoint { + + + /** + * Add a provider factory. + * + * @param providerFactory The provider factory + */ + void addProviderFactory(ProviderFactory providerFactory); + + /** + * Remove a provider factory. + * + * @param providerFactory The provider factory + */ + void removeProviderFactory(ProviderFactory providerFactory); + + /** + * Returns the provider factory associated with the given model type. + * @param modelType A model type + * @return The provider factory associated with the given model type + */ + ProviderFactory getProviderFactory(Class<?> modelType); + + /** + * Get a list of registered PolicyProviderFactory + * @return a list of registered PolicyProviderFactory + */ + List<PolicyProviderFactory> getPolicyProviderFactories(); + + /** + * Get a collection of provider factories by the factory type + * @param <P> + * @param factoryType The factory type such as BindingProviderFactory + * @return a collection of provider factories of the factory type + */ + <P extends ProviderFactory> Collection<P> getProviderFactories(Class<P> factoryType); + + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/ReferenceBindingProvider.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/ReferenceBindingProvider.java new file mode 100644 index 0000000000..ab864dba3f --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/ReferenceBindingProvider.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.provider; + +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; + +/** + * A reference binding implementation can options implement this + * interface to tie into the Tuscany SCA runtime + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public interface ReferenceBindingProvider extends RuntimeProvider { + /** + * Create an invoker for the reference binding in the invocation chain. The + * invoker is responsible for making the outbound invocation over the + * binding protocol. + * + * @param operation The operation that the interceptor will handle + * @return An invoker that handles the invocation logic, null should be + * returned if no invoker is required + */ + Invoker createInvoker(Operation operation); + + /** + * Get the effective interface contract imposed by the binding. For example, + * it will be interface contract introspected from the WSDL portType used by + * the endpoint for a WebService binding. + * + * @return The effective interface contract, if null is returned, the + * interface contract for the component reference will be used + */ + InterfaceContract getBindingInterfaceContract(); + + /** + * For bindings that invoke one-way operations asynchronously, there is no + * need to perform a thread switch before calling the invoker. This method + * indicates whether the binding has this capability. + * + * @return true if the binding invoker is able to invoke one-way operations + * asynchronously, false if all invocations are synchronous + */ + boolean supportsOneWayInvocation(); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/RuntimeProvider.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/RuntimeProvider.java new file mode 100644 index 0000000000..2afd44af31 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/RuntimeProvider.java @@ -0,0 +1,35 @@ +/* + * 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.provider; + +/** + * The base interface for runtime providers that can be started or stoppped + */ +public interface RuntimeProvider { + /** + * This method will be invoked when the corresponding SCA component is started. + */ + void start(); + + /** + * This method will be invoked when the corresponding SCA component is stopped + */ + void stop(); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/ServiceBindingProvider.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/ServiceBindingProvider.java new file mode 100644 index 0000000000..e7df45bfa8 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/ServiceBindingProvider.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.provider; + +import org.apache.tuscany.sca.interfacedef.InterfaceContract; + +/** + * A service binding can optionally implement this interface to tie + * into the Tuscany SCA runtime + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public interface ServiceBindingProvider extends RuntimeProvider { + + /** + * Get the effective interface contract imposed by the binding. For example, + * it will be interface contract introspected from the WSDL portType used by + * the endpoint for a WebService binding. + * + * @return The effective interface contract, if null is returned, the + * interface contract for the component service will be used + */ + InterfaceContract getBindingInterfaceContract(); + + /** + * For bindings that invoke one-way callback operations asynchronously, + * there is no need to perform a thread switch before calling the invoker. + * This method indicates whether the binding has this capability. + * + * @return true if the callback invoker is able to invoke one-way operations + * asynchronously, false if all invocations are synchronous + */ + boolean supportsOneWayInvocation(); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/WireFormatProvider.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/WireFormatProvider.java new file mode 100644 index 0000000000..674b708ef8 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/WireFormatProvider.java @@ -0,0 +1,55 @@ +/* + * 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.provider; + +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.invocation.Interceptor; + +/** + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public interface WireFormatProvider { + + /** + * Set up the contract that describes the interface that + * is providing data to or accepting data from the + * wire format interceptor. The wire format's job + * is to translate between this interface contract and the + * format on the wire. The interface contract may be + * configured separately for request and response + * wire formats + * + * @return the wire format interface contract + */ + public InterfaceContract configureWireFormatInterfaceContract(InterfaceContract interfaceContract); + + /** + * Create an interceptor for the wire format + * @return An interceptor that realize the policySet + */ + Interceptor createInterceptor(); + + /** + * Get the phase that the interceptor should be added + * @return The phase that this interceptor belongs to + */ + String getPhase(); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/WireFormatProviderFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/WireFormatProviderFactory.java new file mode 100644 index 0000000000..3f629ddeef --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/provider/WireFormatProviderFactory.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.provider; + +import org.apache.tuscany.sca.assembly.WireFormat; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; + +/** + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public interface WireFormatProviderFactory<M extends WireFormat> extends ProviderFactory<M> { + /** + * Create wire format provider for a given reference binding + * @param endpointReference The endpoint reference + * @return + */ + WireFormatProvider createReferenceWireFormatProvider(RuntimeEndpointReference endpointReference); + + /** + * Create policy provider for a given service binding + * @param endpoint TODO + * @return + */ + WireFormatProvider createServiceWireFormatProvider(RuntimeEndpoint endpoint); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/ActivationException.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/ActivationException.java new file mode 100644 index 0000000000..b015891e93 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/ActivationException.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.runtime; + + +/** + * Denotes an error starting the runtime + * + * @version $Rev$ $Date$ + */ +public class ActivationException extends Exception { + private static final long serialVersionUID = 8612661660934426123L; + + public ActivationException(String message) { + super(message); + } + + public ActivationException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/BaseDomainRegistryFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/BaseDomainRegistryFactory.java new file mode 100644 index 0000000000..4f6a29bbcc --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/BaseDomainRegistryFactory.java @@ -0,0 +1,115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.runtime; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.LifeCycleListener; + +/** + * The utility responsible for finding the endpoint regstry by the scheme and creating instances for the + * given domain + * @tuscany.spi.extension.inheritfrom + */ +public abstract class BaseDomainRegistryFactory implements DomainRegistryFactory, LifeCycleListener { + protected ExtensionPointRegistry registry; + protected Map<Object, EndpointRegistry> endpointRegistries = new ConcurrentHashMap<Object, EndpointRegistry>(); + protected List<EndpointListener> listeners = new ArrayList<EndpointListener>(); + + /** + * @param extensionRegistry + */ + public BaseDomainRegistryFactory(ExtensionPointRegistry registry) { + super(); + this.registry = registry; + } + + public void start() { + } + + public synchronized EndpointRegistry getEndpointRegistry(String endpointRegistryURI, String domainURI) { + if (endpointRegistryURI == null) { + endpointRegistryURI = domainURI; + } + + Object key = getKey(endpointRegistryURI, domainURI); + + EndpointRegistry endpointRegistry = endpointRegistries.get(key); + if (endpointRegistry != null) { + return endpointRegistry; + } + + endpointRegistry = createEndpointRegistry(endpointRegistryURI, domainURI); + + if (endpointRegistry instanceof LifeCycleListener) { + ((LifeCycleListener)endpointRegistry).start(); + } + + for (EndpointListener listener : listeners) { + endpointRegistry.addListener(listener); + } + endpointRegistries.put(key, endpointRegistry); + return endpointRegistry; + } + + protected Object getKey(String endpointRegistryURI, String domainURI) { + return endpointRegistryURI + "," + domainURI; + } + + protected abstract EndpointRegistry createEndpointRegistry(String endpointRegistryURI, String domainURI); + + public void stop() { + for (EndpointRegistry endpointRegistry : endpointRegistries.values()) { + if (endpointRegistry instanceof LifeCycleListener) { + ((LifeCycleListener)endpointRegistry).stop(); + } + } + endpointRegistries.clear(); + listeners.clear(); + } + + public synchronized Collection<EndpointRegistry> getEndpointRegistries() { + return new ArrayList<EndpointRegistry>(endpointRegistries.values()); + } + + public synchronized void addListener(EndpointListener listener) { + listeners.add(listener); + for (EndpointRegistry registry : endpointRegistries.values()) { + registry.addListener(listener); + } + } + + public synchronized List<EndpointListener> getListeners() { + return listeners; + } + + public synchronized void removeListener(EndpointListener listener) { + listeners.remove(listener); + for (EndpointRegistry registry : endpointRegistries.values()) { + registry.removeListener(listener); + } + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/BaseEndpointRegistry.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/BaseEndpointRegistry.java new file mode 100644 index 0000000000..0b6b93edc0 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/BaseEndpointRegistry.java @@ -0,0 +1,141 @@ +/* + * 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.runtime; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.LifeCycleListener; + +/** + * A replicated EndpointRegistry based on Apache Tomcat Tribes + * @tuscany.spi.extension.inheritfrom + */ +public abstract class BaseEndpointRegistry implements EndpointRegistry, LifeCycleListener { + protected final static Logger logger = Logger.getLogger(BaseEndpointRegistry.class.getName()); + + protected String domainRegistryURI; + protected String domainURI; + + protected List<EndpointReference> endpointreferences = new CopyOnWriteArrayList<EndpointReference>(); + protected List<EndpointListener> listeners = new CopyOnWriteArrayList<EndpointListener>(); + protected ExtensionPointRegistry registry; + protected Map<String, String> attributes; + + public BaseEndpointRegistry(ExtensionPointRegistry registry, + Map<String, String> attributes, + String domainRegistryURI, + String domainURI) { + this.registry = registry; + this.domainURI = domainURI; + this.domainRegistryURI = domainRegistryURI; + this.attributes = attributes; + } + + public abstract void addEndpoint(Endpoint endpoint); + + public void addEndpointReference(EndpointReference endpointReference) { + endpointreferences.add(endpointReference); + logger.fine("Add endpoint reference - " + endpointReference); + } + + public void addListener(EndpointListener listener) { + listeners.add(listener); + } + + protected void endpointAdded(Endpoint endpoint) { + ((RuntimeEndpoint)endpoint).bind(registry, this); + for (EndpointListener listener : listeners) { + listener.endpointAdded(endpoint); + } + } + + protected void endpointRemoved(Endpoint endpoint) { + ((RuntimeEndpoint)endpoint).bind(registry, this); + for (EndpointListener listener : listeners) { + listener.endpointRemoved(endpoint); + } + } + + protected void endpointUpdated(Endpoint oldEp, Endpoint newEp) { + ((RuntimeEndpoint)newEp).bind(registry, this); + for (EndpointListener listener : listeners) { + listener.endpointUpdated(oldEp, newEp); + } + } + + public List<Endpoint> findEndpoint(EndpointReference endpointReference) { + logger.fine("Find endpoint for reference - " + endpointReference); + + if (endpointReference.getReference() != null) { + Endpoint targetEndpoint = endpointReference.getTargetEndpoint(); + String uri = targetEndpoint.getURI(); + // [rfeng] This is a workaround to deal with the case that the endpoint URI doesn't have the + // service name to avoid confusion between structural URIs and service URIs + if (uri.indexOf('#') == -1) { + uri = uri + "#service()"; + } + return findEndpoint(uri); + } + + return new ArrayList<Endpoint>(); + } + + public abstract List<Endpoint> findEndpoint(String uri); + + public List<EndpointReference> findEndpointReference(Endpoint endpoint) { + return endpointreferences; + } + + public abstract Endpoint getEndpoint(String uri); + + public List<EndpointReference> getEndpointReferences() { + return endpointreferences; + } + + public abstract Collection<Endpoint> getEndpoints(); + + public List<EndpointListener> getListeners() { + return listeners; + } + + public abstract void removeEndpoint(Endpoint endpoint); + + public void removeEndpointReference(EndpointReference endpointReference) { + endpointreferences.remove(endpointReference); + logger.fine("Remove endpoint reference - " + endpointReference); + } + + public void removeListener(EndpointListener listener) { + listeners.remove(listener); + } + + public String getDomainURI() { + return domainURI; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/CompositeActivator.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/CompositeActivator.java new file mode 100644 index 0000000000..d9bdc2b6f6 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/CompositeActivator.java @@ -0,0 +1,159 @@ +/* + * 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.runtime; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.context.CompositeContext; + +/** + * Start/stop a composite + * + * @version $Rev$ $Date$ + */ +public interface CompositeActivator { + /** + * Activate a composite + * @param compositeContext The context of the Node + * @param composite + */ + void activate(CompositeContext compositeContext, Composite composite) throws ActivationException; + + /** + * Activate a component reference + * @param compositeContext The context of the Node + * @param component + * @param ref + */ + void activate(CompositeContext compositeContext, RuntimeComponent component, RuntimeComponentReference ref); + + /** + * Activate a component reference + * @param compositeContext The context of the Node + * @param component + * @param ref + */ + void activate(CompositeContext compositeContext, RuntimeComponent component, RuntimeComponentService service); + + /** + * De-activate a component reference + * @param component + * @param ref + */ + void deactivate(RuntimeComponent component, RuntimeComponentReference ref); + + /** + * De-activate a component reference + * @param component + * @param ref + */ + void deactivate(RuntimeComponent component, RuntimeComponentService service); + + /** + * Stop a composite + * @param composite + */ + void deactivate(Composite composite) throws ActivationException; + + /** + * Start a component reference + * @param compositeContext The context of the Node + * @param component + * @param ref + */ + void start(CompositeContext compositeContext, RuntimeComponent component, RuntimeComponentReference ref); + + + /** + * Start a component + * @param component + */ + void start(CompositeContext compositeContext, Component component) throws ActivationException; + + /** + * Stop a component + * @param component + */ + void stop(CompositeContext compositeContext, Component component) throws ActivationException; + + /** + * Start components in a composite + * @param composite + */ + void start(CompositeContext compositeContext, Composite composite) throws ActivationException; + + /** + * Stop components in a composite + * @param composite + */ + void stop(CompositeContext compositeContext, Composite composite) throws ActivationException; + + /** + * Activate an endpoint + * @param compositeContext + * @param endpoint + */ + void activate(CompositeContext compositeContext, RuntimeEndpoint endpoint); + + /** + * Activate an endpoint reference + * @param compositeContext + * @param endpointReference + */ + void activate(CompositeContext compositeContext, RuntimeEndpointReference endpointReference); + + /** + * Deactivate an endpoint + * @param endpoint + */ + void deactivate(RuntimeEndpoint endpoint); + + /** + * Deactivate an endpoint reference + * @param endpointReference + */ + void deactivate(RuntimeEndpointReference endpointReference); + + /** + * Start an endpoint + * @param compositeContext + * @param endpoint + */ + void start(CompositeContext compositeContext, RuntimeEndpoint endpoint); + + /** + * Start an endpoint reference + * @param compositeContext + * @param endpointReference + */ + void start(CompositeContext compositeContext, RuntimeEndpointReference endpointReference); + + /** + * Stop an endpoint + * @param endpoint + */ + void stop(RuntimeEndpoint endpoint); + + /** + * Stop an endpoint reference + * @param endpointReference + */ + void stop(RuntimeEndpointReference endpointReference); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/DefaultDomainRegistryFactoryExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/DefaultDomainRegistryFactoryExtensionPoint.java new file mode 100644 index 0000000000..f74d80b882 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/DefaultDomainRegistryFactoryExtensionPoint.java @@ -0,0 +1,103 @@ +/* + * 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.runtime; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.LifeCycleListener; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceHelper; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * Default implementation of DomainRegistryFactoryExtensionPoint + */ +public class DefaultDomainRegistryFactoryExtensionPoint implements DomainRegistryFactoryExtensionPoint, + LifeCycleListener { + private ExtensionPointRegistry registry; + private boolean loaded; + private List<DomainRegistryFactory> factories = new ArrayList<DomainRegistryFactory>(); + private Map<String, String> domainRegistryMapping = new HashMap<String, String>(); + + /** + * @param registry + */ + public DefaultDomainRegistryFactoryExtensionPoint(ExtensionPointRegistry registry, Map<String, String> attributes) { + super(); + this.registry = registry; + // Populate the domainRegistryMapping + domainRegistryMapping.putAll(attributes); + domainRegistryMapping.remove("class"); + domainRegistryMapping.remove("ranking"); + } + + public void addDomainRegistryFactory(DomainRegistryFactory factory) { + ServiceHelper.start(factory); + factories.add(factory); + } + + public List<DomainRegistryFactory> getDomainRegistryFactories() { + load(); + return factories; + } + + private synchronized void load() { + if (loaded) { + return; + } + try { + Collection<ServiceDeclaration> declarations = + registry.getServiceDiscovery().getServiceDeclarations(DomainRegistryFactory.class, true); + for (ServiceDeclaration declaration : declarations) { + DomainRegistryFactory factory = ServiceHelper.newInstance(registry, declaration); + addDomainRegistryFactory(factory); + } + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } finally { + loaded = true; + } + } + + public void removeDomainRegistryFactory(DomainRegistryFactory factory) { + if (factories.remove(factory)) { + ServiceHelper.stop(factory); + } + + } + + public void start() { + // Empty + } + + public void stop() { + ServiceHelper.stop(factories); + } + + public Map<String, String> getDomainRegistryMapping() { + return domainRegistryMapping; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/DefaultWireProcessorExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/DefaultWireProcessorExtensionPoint.java new file mode 100644 index 0000000000..283d1d1a8b --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/DefaultWireProcessorExtensionPoint.java @@ -0,0 +1,127 @@ +/* + * 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.runtime; + +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.LifeCycleListener; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.extensibility.ServiceDiscovery; + +/** + * The default implementation of a <code>WireProcessorExtensionPoint</code> + * + * @version $Rev$ $Date$ + */ +public class DefaultWireProcessorExtensionPoint implements RuntimeWireProcessorExtensionPoint, LifeCycleListener { + private ExtensionPointRegistry registry; + private boolean loaded; + + /** + * @param registry + */ + public DefaultWireProcessorExtensionPoint(ExtensionPointRegistry registry) { + super(); + this.registry = registry; + } + + /** + * The list of WireProcessors available to the runtime + */ + private final List<RuntimeWireProcessor> processors = new ArrayList<RuntimeWireProcessor>(); + + /** + * Registers a wire-processor in the runtime + * + * @param processor The processor to register + */ + public void addWireProcessor(RuntimeWireProcessor processor) { + processors.add(processor); + if (processor instanceof LifeCycleListener) { + ((LifeCycleListener)processor).start(); + } + } + + /** + * De-registers a wire-processor in the runtime + * + * @param processor The processor to de-register + */ + public void removeWireProcessor(RuntimeWireProcessor processor) { + boolean found = processors.remove(processor); + if (found && (processor instanceof LifeCycleListener)) { + ((LifeCycleListener)processor).stop(); + } + } + + /** + * Returns a list of registered wire-processors. + * + * @return The list of wire processors + */ + public List<RuntimeWireProcessor> getWireProcessors() { + loadWireProcessors(); + return processors; + } + + private synchronized void loadWireProcessors() { + if (loaded) { + return; + } + try { + Collection<ServiceDeclaration> sds = + registry.getServiceDiscovery().getServiceDeclarations(RuntimeWireProcessor.class, true); + for (ServiceDeclaration sd : sds) { + Class type = sd.loadClass(); + Constructor constructor = null; + RuntimeWireProcessor processor = null; + try { + constructor = type.getConstructor(ExtensionPointRegistry.class); + processor = (RuntimeWireProcessor)constructor.newInstance(registry); + + } catch (NoSuchMethodException e) { + constructor = type.getConstructor(); + processor = (RuntimeWireProcessor)constructor.newInstance(); + } + if (processor != null) { + addWireProcessor(processor); + } + } + loaded = true; + } catch (Throwable e) { + throw new IllegalStateException(e); + } + } + + public void start() { + } + + public void stop() { + for (RuntimeWireProcessor processor : processors) { + if ((processor instanceof LifeCycleListener)) { + ((LifeCycleListener)processor).stop(); + } + } + processors.clear(); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/DomainRegistryFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/DomainRegistryFactory.java new file mode 100644 index 0000000000..c79fab1f47 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/DomainRegistryFactory.java @@ -0,0 +1,61 @@ +/* + * 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.runtime; + +import java.util.Collection; + +/** + * A DomainRegistryFactory is responsible for creating an instance of the DomainRegistry for a given + * registry URI and domain URI + */ +public interface DomainRegistryFactory { + /** + * Get the EndpointRegistry for the given registry URI and domain URI + * @param endpointRegistryURI A URI can be used to connect to the registry, such as vm://localhost + * or multicast://200.0.100.200:50000/... + * @param domainURI The domain URI + * @return + */ + EndpointRegistry getEndpointRegistry(String endpointRegistryURI, String domainURI); + + /** + * Return all active endpoint registries + * @return + */ + Collection<EndpointRegistry> getEndpointRegistries(); + + /** + * Add an EndpointListener + * @param listener + */ + void addListener(EndpointListener listener); + + /** + * Remove an EndpointListener + * @param listener + */ + void removeListener(EndpointListener listener); + + /** + * Return an array of schemes that this factory supports + * @return + */ + String[] getSupportedSchemes(); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/DomainRegistryFactoryExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/DomainRegistryFactoryExtensionPoint.java new file mode 100644 index 0000000000..f1582c3d70 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/DomainRegistryFactoryExtensionPoint.java @@ -0,0 +1,51 @@ +/* + * 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.runtime; + +import java.util.List; +import java.util.Map; + +/** + * Extension point for DomainRegistryFactory + */ +public interface DomainRegistryFactoryExtensionPoint { + /** + * Return a mapping between domain URI and domain registry URI + * @return A mutable map + */ + Map<String, String> getDomainRegistryMapping(); + + /** + * Add a DomainRegistryFactory + * @param factory + */ + void addDomainRegistryFactory(DomainRegistryFactory factory); + + /** + * Remove a DomainRegistryFactory + * @param factory + */ + void removeDomainRegistryFactory(DomainRegistryFactory factory); + + /** + * @return A list of DomainRegistryFactory + */ + List<DomainRegistryFactory> getDomainRegistryFactories(); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/DomainRegistryURI.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/DomainRegistryURI.java new file mode 100644 index 0000000000..6de0878383 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/DomainRegistryURI.java @@ -0,0 +1,168 @@ +/* + * 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.runtime; + +import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +/** + * Utility to parse the config uri string. + * + * tuscany:[domainName]?listen=[port|ip:port]]&password=abc&multicast=[off|port|ip:port]&remotes=ip:port,ip:port,... + + * listen - defines the local bind address and port, it defaults to all network interfaces on port 14820 and if that port in use it will try incrementing by one till a free port is found. + * password - is the password other nodes must use to connect to this domain. The default is 'tuscany'. + * multicast - defines if multicast discovery is used and if so what multicast ip group and port is used. + * The default is multicast is off if remotes= is specified (only for now due to a Hazelcast limitation that is planned to be fixed), + * otherwise if remotes= is not specified then multicast defaults to 224.5.12.10:51482 + * remotes - a list of ipAddress:port for remote nodes + * + * @tuscany.spi.extension.asclient + * + */ +public class DomainRegistryURI { + + private String domainName = "default"; + private String bindAddress = null; // null means all network adapters + private int listenPort = 14820; + private String password = "tuscany"; + private boolean multicastDisabled = false; + private String multicastAddress = "224.5.12.10"; + private int multicastPort = 51482; + private List<String> remotes = new ArrayList<String>(); + private String uri; + + public DomainRegistryURI(String uri) { + this.uri = uri; + parseURI(uri); + } + + private void parseURI(String uri) { + if (uri.startsWith("tuscanyclient:")) { + uri = uri.replace("tuscanyclient:", "tuscany:"); + } + + if (!uri.startsWith("tuscany:")) { + throw new IllegalArgumentException("Config URI must start with 'tuscany:'"); + } + + // make it a URI so java.net.URI can be used to parse it + int i = uri.indexOf(":"); + if (uri.charAt("tuscany:".length()) != '/') { + uri = uri.replaceFirst(":", ":/"); + } + if (uri.charAt("tuscany:".length()+1) != '/') { + uri = uri.replaceFirst(":/", "://"); + } + URI configURI = URI.create(uri); + + this.domainName = configURI.getHost(); + + String query = configURI.getQuery(); + if (query != null && query.length() > 0) { + String[] params = query.split("&"); + Map<String, String> paramMap = new HashMap<String, String>(); + for (String param : params) { + paramMap.put(param.split("=")[0], param.split("=")[1]); + } + for (String name : paramMap.keySet()) { + String value = paramMap.get(name); + if ("listen".equals(name)) { + if (value.indexOf(":") == -1) { + this.listenPort = Integer.parseInt(value); + } else { + String[] addr = value.split(":"); + this.bindAddress = addr[0]; + this.listenPort = Integer.parseInt(addr[1]); + } + } else if ("multicast".equals(name)) { + if ("off".equalsIgnoreCase(value)) { + this.multicastDisabled = true; + } else { + if (value.indexOf(":") == -1) { + this.multicastAddress = value; + } else { + String[] addr = value.split(":"); + this.multicastAddress = addr[0]; + this.multicastPort = Integer.parseInt(addr[1]); + } + } + } else if ("password".equals(name)) { + this.password = value; + } else if ("remotes".equals(name)) { + String[] ips = value.split(","); + for (String ip : ips) { + if (ip.indexOf(":") == -1) { + remotes.add(ip + ":14820"); + } else { + remotes.add(ip); + } + } + if (paramMap.containsKey("multicast")) { +// throw new IllegalArgumentException("Cannot have multicast and remotes (for now)"); + } else { + this.multicastDisabled = true; + } + } + } + } + } + + public String getDomainName() { + return domainName; + } + + public String getBindAddress() { + return bindAddress; + } + + public int getListenPort() { + return listenPort; + } + + public String getPassword() { + return password; + } + + public boolean isMulticastDisabled() { + return multicastDisabled; + } + + public String getMulticastAddress() { + return multicastAddress; + } + + public int getMulticastPort() { + return multicastPort; + } + + public List<String> getRemotes() { + return remotes; + } + + public String toString() { + return uri; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointListener.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointListener.java new file mode 100644 index 0000000000..13d193c464 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointListener.java @@ -0,0 +1,46 @@ +/* + * 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.runtime; + +import java.util.EventListener; + +import org.apache.tuscany.sca.assembly.Endpoint; + +/** + * A listener for endpoint events + */ +public interface EndpointListener extends EventListener { + /** + * The method is invoked when a new endpoint is added to the registry + * @param endpoint + */ + void endpointAdded(Endpoint endpoint); + /** + * The method is invoked when an endpoint is removed the registry + * @param endpoint + */ + void endpointRemoved(Endpoint endpoint); + /** + * The method is invoked when an endpoint is updated in the registry + * @param oldEndpoint + * @param newEndpoint + */ + void endpointUpdated(Endpoint oldEndpoint, Endpoint newEndpoint); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointReferenceBinder.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointReferenceBinder.java new file mode 100644 index 0000000000..b2ce3f5b7b --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointReferenceBinder.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.runtime; + +import org.apache.tuscany.sca.assembly.EndpointReference; + +/** + * A utility responsible for resolving the endpoint reference against a matching endpoint published + * to the EndpointRegistry + */ +public interface EndpointReferenceBinder { + + /** + * @param endpointRegistry + * @param endpointReference + * @return + */ + void bindBuildTime(EndpointRegistry endpointRegistry, EndpointReference endpointReference); + + + /** + * @param endpointRegistry + * @param endpointReference + * @return + */ + void bindRunTime(EndpointRegistry endpointRegistry, EndpointReference endpointReference); + + /** + * + * @param endpointRegistry + * @param endpointReference + * @return + */ + boolean isOutOfDate(EndpointRegistry endpointRegistry, EndpointReference endpointReference); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointRegistry.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointRegistry.java new file mode 100644 index 0000000000..2c01eb115a --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointRegistry.java @@ -0,0 +1,71 @@ +/* + * 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.runtime; + +import java.util.Collection; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; + +/** + * The EndpointRegistry holds the active service endpoints for the SCA domain + * @tuscany.spi.extension.inheritfrom + */ +public interface EndpointRegistry { + /** + * Add an enpoint to the registry. If the endpoint URI is the same as an existing endpoint in the registry, + * the existing one will be updated + * @param endpoint + */ + void addEndpoint(Endpoint endpoint); + + /** + * Remove an enpoint from the registry + * @param endpoint + */ + void removeEndpoint(Endpoint endpoint); + + /** + * Look up an enpoint from the registry + * @param uri The endpoint URI + * @return + */ + Endpoint getEndpoint(String uri); + + /** + * Get all endpoints in the registry + * @return + */ + Collection<Endpoint> getEndpoints(); + + List<Endpoint> findEndpoint(String uri); + List<Endpoint> findEndpoint(EndpointReference endpointReference); + + void addEndpointReference(EndpointReference endpointReference); + void removeEndpointReference(EndpointReference endpointReference); + // List<EndpointReference> findEndpointReference(Endpoint endpoint); + List<EndpointReference> getEndpointReferences(); + + void addListener(EndpointListener listener); + void removeListener(EndpointListener listener); + + String getDomainURI(); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointSerializer.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointSerializer.java new file mode 100644 index 0000000000..981872fdfa --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/EndpointSerializer.java @@ -0,0 +1,36 @@ +/* + * 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.runtime; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; + +/** + * A utility to seralize/deserialize Endpoint/EndpointReference objects + */ +public interface EndpointSerializer { + EndpointReference readEndpointReference(String xml); + + String write(EndpointReference endpointReference); + + Endpoint readEndpoint(String xml); + + String write(Endpoint endpoint); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/ExtensibleDomainRegistryFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/ExtensibleDomainRegistryFactory.java new file mode 100644 index 0000000000..d1d0fb2b29 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/ExtensibleDomainRegistryFactory.java @@ -0,0 +1,133 @@ +/* + * 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.runtime; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * A delegating DomainRegistryFactory + */ +public class ExtensibleDomainRegistryFactory implements DomainRegistryFactory { + private final DomainRegistryFactoryExtensionPoint factories; + private String[] allSchemes; + private String defaultScheme = "tuscany"; + + public ExtensibleDomainRegistryFactory(ExtensionPointRegistry registry) { + this.factories = registry.getExtensionPoint(DomainRegistryFactoryExtensionPoint.class); + RuntimeProperties ps = registry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(RuntimeProperties.class); + if (ps.getProperties().containsKey("defaultScheme")) { + defaultScheme = ps.getProperties().getProperty("defaultScheme"); + } + + } + + public ExtensibleDomainRegistryFactory(DomainRegistryFactoryExtensionPoint factories) { + this.factories = factories; + } + + public static ExtensibleDomainRegistryFactory getInstance(ExtensionPointRegistry registry) { + UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class); + return utilities.getUtility(ExtensibleDomainRegistryFactory.class); + } + + public void addListener(EndpointListener listener) { + for (DomainRegistryFactory factory : factories.getDomainRegistryFactories()) { + factory.addListener(listener); + } + } + + public Collection<EndpointRegistry> getEndpointRegistries() { + List<EndpointRegistry> registries = new ArrayList<EndpointRegistry>(); + for (DomainRegistryFactory factory : factories.getDomainRegistryFactories()) { + registries.addAll(factory.getEndpointRegistries()); + } + return registries; + } + + public EndpointRegistry getEndpointRegistry(String endpointRegistryURI, String domainURI) { + if (endpointRegistryURI == null) { + endpointRegistryURI = factories.getDomainRegistryMapping().get(domainURI); + if (endpointRegistryURI == null) { + endpointRegistryURI = domainURI; + } + } + + String scheme = endpointRegistryURI == null ? null : URI.create(endpointRegistryURI).getScheme(); + if (scheme == null) { + + // See if there is a previously created registry for that domain + for (DomainRegistryFactory factory : factories.getDomainRegistryFactories()) { + for (EndpointRegistry endpointRegistry : factory.getEndpointRegistries()) { + if (endpointRegistry.getDomainURI().equals(domainURI)) { + return endpointRegistry; + } + } + } + + scheme = defaultScheme; + endpointRegistryURI = scheme + ":" + endpointRegistryURI; + } else { + scheme = scheme.toLowerCase(); + } + for (DomainRegistryFactory factory : factories.getDomainRegistryFactories()) { + String[] schemes = factory.getSupportedSchemes(); + if (schemes != null && Arrays.asList(schemes).contains(scheme)) { + EndpointRegistry endpointRegistry = factory.getEndpointRegistry(endpointRegistryURI, domainURI); + if (endpointRegistry == null) { + continue; + } else { + return endpointRegistry; + } + } + } + throw new ServiceRuntimeException("No EndpointRegistry can support " + endpointRegistryURI); + } + + public void removeListener(EndpointListener listener) { + for (DomainRegistryFactory factory : factories.getDomainRegistryFactories()) { + factory.removeListener(listener); + } + } + + public synchronized String[] getSupportedSchemes() { + if (allSchemes == null) { + Set<String> supportedSchemes = new HashSet<String>(); + for (DomainRegistryFactory factory : factories.getDomainRegistryFactories()) { + String[] schemes = factory.getSupportedSchemes(); + if (schemes != null) { + supportedSchemes.addAll(Arrays.asList(schemes)); + } + } + allSchemes = supportedSchemes.toArray(new String[supportedSchemes.size()]); + } + return allSchemes; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/Invocable.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/Invocable.java new file mode 100644 index 0000000000..2df1761aec --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/Invocable.java @@ -0,0 +1,137 @@ +/* + * 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.runtime; + +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.Contract; +import org.apache.tuscany.sca.context.CompositeContext; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.provider.PolicyProvider; + +/** + * The abstraction of an invocable model that contains invocation chains + * @tuscany.spi.extension.asclient + */ +public interface Invocable { + /** + * Bind the invocable to the composite context + * @param context + */ + void bind(CompositeContext context); + + /** + * Bind the invocable to the extension point registry and endpoint registry. This is typically + * called after the endpoint or endpoint reference is deserialized + * @param registry + * @param endpointRegistry + */ + void bind(ExtensionPointRegistry registry, EndpointRegistry endpointRegistry); + + /** + * Get the associated composite context + * @return + */ + CompositeContext getCompositeContext(); + + /** + * Unbind the invocable from the composite context + */ + void unbind(); + + /** + * Get the component + * @return + */ + Component getComponent(); + + /** + * Get the service or reference (contract) + * @return + */ + Contract getContract(); + + /** + * Get the binding + * @return + */ + Binding getBinding(); + + /** + * Returns the invocation chains for service operations associated with the + * wire + * + * @return the invocation chains for service operations associated with the + * wire + */ + List<InvocationChain> getInvocationChains(); + + /** + * Lookup the invocation chain by operation + * @param operation The operation + * @return The invocation chain for the given operation + */ + InvocationChain getInvocationChain(Operation operation); + + /** + * Get the invocation chain for the binding-specific handling + * @return The binding invocation chain + */ + InvocationChain getBindingInvocationChain(); + + /** + * This invoke method assumes that the binding invocation chain is in force + * and that there will be an operation selector element there to + * determine which operation to call + * @param msg The request message + * @return The response message + */ + Message invoke(Message msg); + + /** + * Invoke an operation with given arguments + * @param operation The operation + * @param args The arguments + * @return The result + * @throws InvocationTargetException + */ + Object invoke(Operation operation, Object[] args) throws InvocationTargetException; + + /** + * Invoke an operation with a context message + * @param operation The operation + * @param msg The request message + * @return The response message + * @throws InvocationTargetException + */ + Message invoke(Operation operation, Message msg); + + /** + * Get a list of policy providers + * @return + */ + List<PolicyProvider> getPolicyProviders(); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/ReferenceParameters.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/ReferenceParameters.java new file mode 100644 index 0000000000..928c77fd04 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/ReferenceParameters.java @@ -0,0 +1,59 @@ +/* + * 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.runtime; + +import org.apache.tuscany.sca.assembly.EndpointReference; + +/** + * Parameters for the EndPointReference + * + * @version $Rev$ $Date$ + */ +public interface ReferenceParameters extends Cloneable { + /** + * Get the callback ID + * @return the callbackID + */ + Object getCallbackID(); + + /** + * Set the callback ID + * @param callbackID the callbackID to set + */ + void setCallbackID(Object callbackID); + + /** + * Get the ID for the non-ServiceReference callback object + * @return + */ + Object getCallbackObjectID(); + + /** + * Set the ID for the non-ServiceReference callback object + * @param callbackObjectID + */ + void setCallbackObjectID(Object callbackObjectID); + + EndpointReference getCallbackReference(); + + void setCallbackReference(EndpointReference callback); + + Object clone() throws CloneNotSupportedException; +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponent.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponent.java new file mode 100644 index 0000000000..efc4b278b3 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponent.java @@ -0,0 +1,84 @@ +/* + * 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.runtime; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.PolicyProvider; + +/** + * The runtime component interface. Provides the bridge between the + * assembly model representation of a component and its runtime + * realization. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface RuntimeComponent extends Component { + /** + * Set the implementation-specific configuration for this component + * @param implementationProvider The object that manages the component implementation + */ + void setImplementationProvider(ImplementationProvider implementationProvider); + + /** + * Get the implementation-specific configuration for this component + * @return The implementation provider for this component + */ + ImplementationProvider getImplementationProvider(); + + /** + * Get the associated component context + * @return + */ + RuntimeComponentContext getComponentContext(); + + /** + * Set the associated component context + * @param context + */ + void setComponentContext(RuntimeComponentContext context); + + /** + * Tests if the RuntimeComponent is started + * @return true if the RuntimeComponent is started otherwise false + */ + boolean isStarted(); + + /** + * Sets the RuntimeComponent started state + * @param started the state to set + */ + void setStarted(boolean started); + + /** + * Add a policy provider to the component + * @param policyProvider + */ + void addPolicyProvider(PolicyProvider policyProvider); + + /** + * Get a list of policy providers configured for this component + * @return + */ + List<PolicyProvider> getPolicyProviders(); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentContext.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentContext.java new file mode 100644 index 0000000000..861ca2d6f9 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentContext.java @@ -0,0 +1,70 @@ +/* + * 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.runtime; + +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.context.CompositeContext; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.oasisopen.sca.ComponentContext; +import org.oasisopen.sca.ServiceReference; + +/** + * @version $Rev$ $Date$ + */ +public interface RuntimeComponentContext extends ComponentContext { + /** + * Activate the reference (creating runtime wires) + * @param reference + */ + void start(RuntimeComponentReference reference); + + /** + * Get the CallableReference for a given component reference + * @param <B> + * @param businessInterface The business interface + * @param endpointReference The endpointReference to be used + * @return A service reference representing the wire + */ + <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, + RuntimeEndpointReference endpointReference); + + + /** + * Create a CallableReference for the given component service + * @param <B> + * @param businessInterface + * @param component + * @param service + * @return + */ + <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, RuntimeEndpoint endpoint); + + /** + * @param <B> + * @param businessInterface + * @param service + * @return + */ + <B> ServiceReference<B> createSelfReference(Class<B> businessInterface, ComponentService service); + + ExtensionPointRegistry getExtensionPointRegistry(); + + CompositeContext getCompositeContext(); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentReference.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentReference.java new file mode 100644 index 0000000000..8abecee0bf --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentReference.java @@ -0,0 +1,38 @@ +/* + * 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.runtime; + +import org.apache.tuscany.sca.assembly.ComponentReference; + +/** + * The runtime component reference. Provides the bridge between the + * assembly model representation of a component reference and its runtime + * realization + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface RuntimeComponentReference extends ComponentReference { + /** + * Set the owning component + * @param component + */ + void setComponent(RuntimeComponent component); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentService.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentService.java new file mode 100644 index 0000000000..1eefdc978e --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeComponentService.java @@ -0,0 +1,33 @@ +/* + * 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.runtime; + +import org.apache.tuscany.sca.assembly.ComponentService; + +/** + * The runtime component service. Provides the bridge between the + * assembly model representation of a component service and its runtime + * realization + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface RuntimeComponentService extends ComponentService { +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeEndpoint.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeEndpoint.java new file mode 100644 index 0000000000..f4411d749f --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeEndpoint.java @@ -0,0 +1,75 @@ +/* + * 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.runtime; + +import java.io.Serializable; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.context.CompositeContext; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.provider.ServiceBindingProvider; + +/** + * The runtime representation of a service endpoint + * @tuscany.spi.extension.asclient + */ +public interface RuntimeEndpoint extends Endpoint, Invocable, Serializable { + /** + * Attach the service binding provider + * @param provider + */ + void setBindingProvider(ServiceBindingProvider provider); + + /** + * Get the service binding provider + * @return + */ + ServiceBindingProvider getBindingProvider(); + + /** + * Get the interface contract for the binding. This represents the data types that the binding + * protocol stack can process. + * @return The binding interface contract + */ + InterfaceContract getBindingInterfaceContract(); + + /** + * Get the interface contract of the service of the target component type, i.e., the + * componentType.service.interfaceContract. This represents the data types that the implementation + * code can process. + * @return The target component type service interface contract + */ + InterfaceContract getComponentTypeServiceInterfaceContract(); + + + /** + * Check that endpoint has compatible interface at the component and binding ends. + * The user can specify the interfaces at both ends so there is a danger that they won't be compatible. + */ + void validateServiceInterfaceCompatibility(); + + /** + * Get the composite context for the composite that contains this endpoint. This + * is useful for accessing various composite level objects from within the + * runtime code + */ + CompositeContext getCompositeContext(); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeEndpointReference.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeEndpointReference.java new file mode 100644 index 0000000000..197a46bf24 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeEndpointReference.java @@ -0,0 +1,72 @@ +/* + * 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.runtime; + +import java.io.Serializable; + +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.provider.ReferenceBindingProvider; + +/** + * The runtime representation of an endpoint reference + * @tuscany.spi.extension.asclient + */ +public interface RuntimeEndpointReference extends EndpointReference, Invocable, Serializable { + /** + * Set the reference binding provider for the endpoint reference + * @param provider The binding provider + */ + void setBindingProvider(ReferenceBindingProvider provider); + + /** + * Get the reference binding provider for the endpoint reference + * @return The binding provider + */ + ReferenceBindingProvider getBindingProvider(); + + /** + * Get the interface contract for the binding. This represents the data types that the binding + * protocol stack can process. + * @return The binding interface contract + */ + InterfaceContract getBindingInterfaceContract(); + + + /** + * Get the interface contract of the reference of the source component type, i.e., the + * componentType.reference.interfaceContract. This represents the data types that the + * implementation code uses to make the outbound call. + * @return The source component type reference interface contract + */ + InterfaceContract getComponentTypeReferenceInterfaceContract(); + + /** + * Check that endpoint reference has compatible interface at the component and binding ends. + * The user can specify the interfaces at both ends so there is a danger that they won't be compatible. + * There is checking in the activator but of course endpoint references may not have a binding assigned + * until final resolution. + */ + public void validateReferenceInterfaceCompatibility(); + + boolean isOutOfDate(); + void rebuild(); + boolean isStarted(); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeProperties.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeProperties.java new file mode 100644 index 0000000000..c413276b37 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeProperties.java @@ -0,0 +1,31 @@ +/* + * 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.runtime; + +import java.util.Properties; +/** + * + * @tuscany.spi.extension.asclient + * + */ +public interface RuntimeProperties { + Properties getProperties(); + void setProperties(Properties properties); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeWireProcessor.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeWireProcessor.java new file mode 100644 index 0000000000..997e170b22 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeWireProcessor.java @@ -0,0 +1,39 @@ +/* + * 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.runtime; + +/** + * Implementations are called after wires are decorated with policy and before they are connected. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public interface RuntimeWireProcessor { + /** + * Configure the runtime endpoint + * @param endpoint + */ + void process(RuntimeEndpoint endpoint); + + /** + * Configure the runtime endpoint reference + * @param endpointReference + */ + void process(RuntimeEndpointReference endpointReference); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeWireProcessorExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeWireProcessorExtensionPoint.java new file mode 100644 index 0000000000..4b2c71b397 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/RuntimeWireProcessorExtensionPoint.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.runtime; + +import java.util.List; + +/** + * Acts as a delegating <code>WireProcessorExtensionPoint</code>, delegating + * processing of wires after policies have been applied and source and targets + * have been connected. + * + * @version $Rev$ $Date$ + */ +public interface RuntimeWireProcessorExtensionPoint { + + /** + * Registers a wire-processor in the runtime + * + * @param processor The processor to register + */ + void addWireProcessor(RuntimeWireProcessor processor); + + /** + * De-registers a wire-processor in the runtime + * + * @param processor The processor to de-register + */ + void removeWireProcessor(RuntimeWireProcessor processor); + + /** + * Returns a list of registered wire-processors. + * + * @return The list of wire processors + */ + List<RuntimeWireProcessor> getWireProcessors(); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/Version.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/Version.java new file mode 100644 index 0000000000..5d3ed1ce41 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/runtime/Version.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.runtime; + +import java.util.ResourceBundle; + +public class Version { + + public static final String VERSION; + public static final String REVISION; + public static final String BUILDTIME; + static { + ResourceBundle rb = ResourceBundle.getBundle("org/apache/tuscany/sca/runtime/revision"); + VERSION = rb.getString("version"); + REVISION = rb.getString("revision"); + BUILDTIME = rb.getString("buildtime"); + } + + public static String getVersion() { + return VERSION; + } + + public static String getRevsion() { + return REVISION; + } + + public static String getBuildTime() { + return BUILDTIME; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/work/NotificationListener.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/work/NotificationListener.java new file mode 100644 index 0000000000..d32af450ff --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/work/NotificationListener.java @@ -0,0 +1,67 @@ +/* + * 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.work; + +/** + * A callback interface that can be optionally used for registering + * interest in status of asynchronously scheduled unit of work. + * + * @version $Rev$ $Date$ + */ +public interface NotificationListener<T extends Runnable> { + + /** + * Callback method when the unit of work is accepted. + * + * @param work Work that was accepted. + */ + void workAccepted(T work); + + /** + * Callback method when the unit of work is successfully completed. + * + * @param work Work that was successfully completed. + */ + void workCompleted(T work); + + /** + * Callback when the unit of work is started. + * + * @param work Unit of work that was started. + */ + void workStarted(T work); + + /** + * Callback when the unit of work is rejected. + * + * @param work Unit of work that was rejected. + */ + void workRejected(T work); + + /** + * Callback when the unit of work fails to complete. + * + * @param work Unit of work that failed to complete. + * @param error Error that caused the unit of work to fail. + */ + void workFailed(T work, Throwable error); + + + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/work/WorkScheduler.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/work/WorkScheduler.java new file mode 100644 index 0000000000..2c5fb556bc --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/work/WorkScheduler.java @@ -0,0 +1,54 @@ +/* + * 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.work; + +/** + * Defines the contract for scheduling asynchronous units of work. + * + * <p> + * Units of work can be scheduled with an optional <code>NotificationListener</code>. + * If a notification listener is specified, the caller will be notified regarding the + * status of the work. The unit of work can either be completed, rejected or completed + * with an error. If the work completed with an error, the caller is notified with the + * error details. + * </p> + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface WorkScheduler { + + /** + * Schedules a unit of work for future execution. The notification listener + * is used to register interest in callbacks regarding the status of the work. + * + * @param work The unit of work that needs to be asynchronously executed. + * @param listener Notification listener for callbacks. + */ + <T extends Runnable>void scheduleWork(T work, NotificationListener<T> listener); + + /** + * Schedules a unit of work for future execution. The notification listener + * is used to register interest in callbacks regarding the status of the work. + * + * @param work The unit of work that needs to be asynchronously executed. + */ + <T extends Runnable>void scheduleWork(T work); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/work/WorkSchedulerException.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/work/WorkSchedulerException.java new file mode 100644 index 0000000000..18ec2dfeaa --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/java/org/apache/tuscany/sca/work/WorkSchedulerException.java @@ -0,0 +1,59 @@ +/* + * 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.work; + + +/** + * Exception thrown by the work scheduler in case of unexpected exceptions. + * + * @version $Rev$ $Date$ + * + * @version $Rev$ $Date$ + */ +public class WorkSchedulerException extends RuntimeException { + private static final long serialVersionUID = 1L; + + /** + * {@inheritDoc} + */ + public WorkSchedulerException() { + super(); + } + + /** + * {@inheritDoc} + */ + public WorkSchedulerException(String message, Throwable cause) { + super(message, cause); + } + + /** + * {@inheritDoc} + */ + public WorkSchedulerException(String message) { + super(message); + } + + /** + * {@inheritDoc} + */ + public WorkSchedulerException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.ContextFactoryExtensionPoint b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.ContextFactoryExtensionPoint new file mode 100644 index 0000000000..454d1796cc --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.ContextFactoryExtensionPoint @@ -0,0 +1,19 @@ +# 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. + +org.apache.tuscany.sca.context.DefaultContextFactoryExtensionPoint +
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint new file mode 100644 index 0000000000..19cf2a444f --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint @@ -0,0 +1,19 @@ +# 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. + +org.apache.tuscany.sca.provider.DefaultProviderFactoryExtensionPoint +
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.DomainRegistryFactoryExtensionPoint b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.DomainRegistryFactoryExtensionPoint new file mode 100644 index 0000000000..be585a1e03 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.DomainRegistryFactoryExtensionPoint @@ -0,0 +1,17 @@ +# 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.
+org.apache.tuscany.sca.runtime.DefaultDomainRegistryFactoryExtensionPoint
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint new file mode 100644 index 0000000000..1ab308cc71 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint @@ -0,0 +1,19 @@ +# 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. + +org.apache.tuscany.sca.runtime.DefaultWireProcessorExtensionPoint +
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/resources/org/apache/tuscany/sca/runtime/revision.properties b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/resources/org/apache/tuscany/sca/runtime/revision.properties new file mode 100644 index 0000000000..9018bd1a1b --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/main/resources/org/apache/tuscany/sca/runtime/revision.properties @@ -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.
+#
+#
+
+#-- Don't edit these. They're updated from the build, see the
+# buildnumber-maven-plugin in this modules pom.xml
+version=@version@
+revision=@svnRevision@
+buildtime=@buildtime@
+#----------------------
+
+
+
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/test/java/org/apache/tuscany/sca/context/DefaultContextFactoryExtensionPointTestCase.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/test/java/org/apache/tuscany/sca/context/DefaultContextFactoryExtensionPointTestCase.java new file mode 100644 index 0000000000..6486a5ed4f --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/test/java/org/apache/tuscany/sca/context/DefaultContextFactoryExtensionPointTestCase.java @@ -0,0 +1,207 @@ +/* + * 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.context; + +import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.junit.Assert; +import org.junit.Test; + +/** + * This test case will test the class + * org.apache.tuscany.sca.context.DefaultContextFactoryExtensionPoint + * + * $Date$ $Rev$ + */ +public class DefaultContextFactoryExtensionPointTestCase { + + /** + * Tests adding/getting/removing a factory with no interfaces + */ + @Test + public void testFactoryWithNoInterfaces() { + Object factory = new FactoryWithNoInterfaces(); + Class<?>[] ifaces = {}; + addGetRemoveFactory(factory, ifaces); + } + + /** + * Tests adding/getting/removing a factory with one interface + */ + @Test + public void testFactoryWithOneInterface() { + Object factory = new FactoryWithOneInterface(); + Class<?>[] ifaces = { FactoryOneInterface.class }; + addGetRemoveFactory(factory, ifaces); + } + + /** + * Tests adding/getting/removing a factory with two interfaces + */ + @Test + public void testFactoryWithTwoInterfaces() { + Object factory = new FactoryWithTwoInterfaces(); + Class<?>[] ifaces = { FactoryTwoInterfacesA.class, FactoryTwoInterfacesB.class }; + addGetRemoveFactory(factory, ifaces); + } + + /** + * Tests having multiple factories registered + */ + @Test + public void testMultipleFactories() { + // Create new factories + FactoryWithOneInterface factory1 = new FactoryWithOneInterface(); + FactoryWithTwoInterfaces factory2 = new FactoryWithTwoInterfaces(); + + ExtensionPointRegistry registry = new DefaultExtensionPointRegistry(); + + // Register the factories + DefaultContextFactoryExtensionPoint ctxFactory = new DefaultContextFactoryExtensionPoint(registry); + ctxFactory.addFactory(factory1); + ctxFactory.addFactory(factory2); + + // Re-get each of the factories + FactoryOneInterface regotFactory1 = ctxFactory.getFactory(FactoryOneInterface.class); + Assert.assertNotNull(regotFactory1); + Assert.assertSame(factory1, regotFactory1); + FactoryTwoInterfacesA regotFactory2A = ctxFactory.getFactory(FactoryTwoInterfacesA.class); + Assert.assertNotNull(regotFactory2A); + Assert.assertSame(factory2, regotFactory2A); + FactoryTwoInterfacesB regotFactory2B = ctxFactory.getFactory(FactoryTwoInterfacesB.class); + Assert.assertNotNull(regotFactory1); + Assert.assertSame(factory2, regotFactory2B); + } + + /** + * Tests passing in null to addFactory() + */ + @Test + public void testAddingNullFactory() { + + ExtensionPointRegistry registry = new DefaultExtensionPointRegistry(); + DefaultContextFactoryExtensionPoint ctxFactory = new DefaultContextFactoryExtensionPoint(registry); + try { + ctxFactory.addFactory(null); + Assert.fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException ex) { + // As expected + } + } + + /** + * Test passing in null to removeFactory() + */ + @Test + public void testRemovingNullFactory() { + ExtensionPointRegistry registry = new DefaultExtensionPointRegistry(); + DefaultContextFactoryExtensionPoint ctxFactory = new DefaultContextFactoryExtensionPoint(registry); + try { + ctxFactory.removeFactory(null); + Assert.fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException ex) { + // As expected + } + } + + /** + * Test passing in null to getFactory() + */ + @Test + public void testGetNullFactory() { + ExtensionPointRegistry registry = new DefaultExtensionPointRegistry(); + DefaultContextFactoryExtensionPoint ctxFactory = new DefaultContextFactoryExtensionPoint(registry); + try { + ctxFactory.getFactory(null); + Assert.fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException ex) { + // As expected + } + } + + /** + * Utility method for testing adding and removing a factory + * + * @param factory The factory class to test + * @param factoryInterfaces The list of interfaces implemented by the factory + */ + private void addGetRemoveFactory(Object factory, Class<?>[] factoryInterfaces) { + ExtensionPointRegistry registry = new DefaultExtensionPointRegistry(); + DefaultContextFactoryExtensionPoint ctxFactory = new DefaultContextFactoryExtensionPoint(registry); + + // Make sure factory not already present + for (Class<?> iface : factoryInterfaces) { + Assert.assertNull(ctxFactory.getFactory(iface)); + } + + // Add the factory + ctxFactory.addFactory(factory); + + // Make sure we can get the factory recently registered factory + for (Class<?> iface : factoryInterfaces) { + Object regot = ctxFactory.getFactory(iface); + Assert.assertNotNull(regot); + Assert.assertSame(factory, regot); + } + + // Remove the factory + ctxFactory.removeFactory(factory); + + // Make sure factory is no longer registered + for (Class<?> iface : factoryInterfaces) { + Assert.assertNull(ctxFactory.getFactory(iface)); + } + } + + /** + * Simple factory with no interfaces + */ + private class FactoryWithNoInterfaces { + } + + /** + * Simple interface for the factory with one interface + */ + private interface FactoryOneInterface { + } + + /** + * Simple factory with one interface + */ + private class FactoryWithOneInterface implements FactoryOneInterface { + } + + /** + * Simple interface for the factory with two interfaces + */ + private interface FactoryTwoInterfacesA { + } + + /** + * Simple interface for the factory with two interfaces + */ + private interface FactoryTwoInterfacesB { + } + + /** + * Simple factory with two interfaces + */ + private class FactoryWithTwoInterfaces implements FactoryTwoInterfacesA, FactoryTwoInterfacesB { + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/test/java/org/apache/tuscany/sca/runtime/ConfigURITestCase.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/test/java/org/apache/tuscany/sca/runtime/ConfigURITestCase.java new file mode 100644 index 0000000000..b7e96a8b28 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/test/java/org/apache/tuscany/sca/runtime/ConfigURITestCase.java @@ -0,0 +1,107 @@ +/* + * 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.runtime; + +import java.net.UnknownHostException; + +import junit.framework.Assert; + +import org.apache.tuscany.sca.runtime.DomainRegistryURI; +import org.junit.Test; + +public class ConfigURITestCase { + + @Test + public void testInvalidPrefix() throws UnknownHostException { + try { + new DomainRegistryURI("foo"); + Assert.fail(); + } catch (IllegalArgumentException e) { + // expected + } + } + + @Test + public void testDomainName() throws UnknownHostException { + DomainRegistryURI configURI = new DomainRegistryURI("tuscany:myDomain"); + Assert.assertEquals("myDomain", configURI.getDomainName()); + Assert.assertFalse(configURI.isMulticastDisabled()); + } + + @Test + public void testListenAddr() throws UnknownHostException { + DomainRegistryURI configURI = new DomainRegistryURI("tuscany:myDomain?listen=4321"); + Assert.assertEquals("myDomain", configURI.getDomainName()); + Assert.assertFalse(configURI.isMulticastDisabled()); + Assert.assertEquals(4321, configURI.getListenPort()); + Assert.assertNull(configURI.getBindAddress()); + } + @Test + public void testListenAddr2() throws UnknownHostException { + DomainRegistryURI configURI = new DomainRegistryURI("tuscany:myDomain?listen=1.1.1.1:4321"); + Assert.assertEquals("myDomain", configURI.getDomainName()); + Assert.assertFalse(configURI.isMulticastDisabled()); + Assert.assertEquals(4321, configURI.getListenPort()); + Assert.assertEquals("1.1.1.1", configURI.getBindAddress()); + } + + @Test + public void testMulticase1() throws UnknownHostException { + DomainRegistryURI configURI = new DomainRegistryURI("tuscany:myDomain?multicast=off"); + Assert.assertEquals("myDomain", configURI.getDomainName()); + Assert.assertTrue(configURI.isMulticastDisabled()); + } + + @Test + public void testMulticase2() throws UnknownHostException { + DomainRegistryURI configURI = new DomainRegistryURI("tuscany:myDomain?multicast=1.2.3.4:67"); + Assert.assertEquals("myDomain", configURI.getDomainName()); + Assert.assertFalse(configURI.isMulticastDisabled()); + Assert.assertEquals("1.2.3.4", configURI.getMulticastAddress()); + Assert.assertEquals(67, configURI.getMulticastPort()); + } + + @Test + public void testMulticase3() throws UnknownHostException { + DomainRegistryURI configURI = new DomainRegistryURI("tuscany:myDomain?multicast=1.2.3.4"); + Assert.assertEquals("myDomain", configURI.getDomainName()); + Assert.assertFalse(configURI.isMulticastDisabled()); + Assert.assertEquals("1.2.3.4", configURI.getMulticastAddress()); + Assert.assertEquals(51482, configURI.getMulticastPort()); + } + + @Test + public void testPassword() { + DomainRegistryURI configURI = new DomainRegistryURI("tuscany:myDomain?password=bla"); + Assert.assertEquals("myDomain", configURI.getDomainName()); + Assert.assertEquals("bla", configURI.getPassword()); + } + + @Test + public void testRemotes() throws UnknownHostException { + DomainRegistryURI configURI = new DomainRegistryURI("tuscany:myDomain?remotes=1.1.1.1:23,2.2.2.2"); + Assert.assertEquals("myDomain", configURI.getDomainName()); + Assert.assertTrue(configURI.isMulticastDisabled()); + Assert.assertEquals(2, configURI.getRemotes().size()); + Assert.assertEquals("1.1.1.1:23", configURI.getRemotes().get(0)); + Assert.assertEquals("2.2.2.2:14820", configURI.getRemotes().get(1)); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/test/java/org/apache/tuscany/sca/runtime/VersionTestCase.java b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/test/java/org/apache/tuscany/sca/runtime/VersionTestCase.java new file mode 100644 index 0000000000..89ca99484c --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core-spi/src/test/java/org/apache/tuscany/sca/runtime/VersionTestCase.java @@ -0,0 +1,36 @@ +/* + * 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.runtime; + +import org.junit.Test; +import org.junit.Ignore; + +/** + */ +@Ignore +public class VersionTestCase { + + @Test + public void testRevision() { + // Doesn't test much, just that it has been initilized to a number + System.out.println(Version.getVersion() + " " + Version.getRevsion() + " " + Version.getBuildTime()); + Integer.parseInt(Version.getRevsion()); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/LICENSE b/sca-java-2.x/branches/2.0-Beta1/modules/core/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/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/sca-java-2.x/branches/2.0-Beta1/modules/core/META-INF/MANIFEST.MF b/sca-java-2.x/branches/2.0-Beta1/modules/core/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..62fc183f20 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/META-INF/MANIFEST.MF @@ -0,0 +1,66 @@ +Manifest-Version: 1.0
+Export-Package: org.apache.tuscany.sca.core.assembly;version="2.0.0";uses:="org.apache.tuscany.sca.assembly,org.apache.tuscany.sca.core",
+ org.apache.tuscany.sca.core.context;version="2.0.0";
+ uses:="javax.xml.stream,
+ org.apache.tuscany.sca.runtime,
+ org.apache.tuscany.sca.assembly,
+ org.apache.tuscany.sca.context,
+ org.oasisopen.sca,
+ org.apache.tuscany.sca.core",
+ org.apache.tuscany.sca.core.factory;version="2.0.0",
+ org.apache.tuscany.sca.core.invocation;version="2.0.0";
+ uses:="org.apache.tuscany.sca.invocation,
+ org.apache.tuscany.sca.runtime,
+ org.apache.tuscany.sca.assembly,
+ org.oasisopen.sca,
+ org.apache.tuscany.sca.work,
+ org.apache.tuscany.sca.core.factory,
+ org.apache.tuscany.sca.core.context.impl,
+ org.apache.tuscany.sca.core,
+ org.apache.tuscany.sca.interfacedef",
+ org.apache.tuscany.sca.core.scope;version="2.0.0";
+ uses:="org.apache.tuscany.sca.runtime,
+ org.apache.tuscany.sca.provider,
+ org.apache.tuscany.sca.core.scope.impl,
+ org.apache.tuscany.sca.core.factory"
+SCA-Version: 1.1
+Bundle-Name: Apache Tuscany SCA Core Runtime
+Bundle-Vendor: The Apache Software Foundation
+Bundle-Version: 2.0.0
+Bundle-ManifestVersion: 2
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-Description: Apache Tuscany SCA Core Runtime
+Import-Package: javax.security.auth,
+ javax.xml.namespace,
+ javax.xml.stream,
+ net.sf.cglib.proxy;resolution:=optional,
+ org.apache.tuscany.sca.assembly;version="2.0.0",
+ org.apache.tuscany.sca.assembly.builder;version="2.0.0",
+ org.apache.tuscany.sca.assembly.impl;version="2.0.0",
+ org.apache.tuscany.sca.common.java.collection;version="2.0.0",
+ org.apache.tuscany.sca.context;version="2.0.0",
+ org.apache.tuscany.sca.contribution.processor;version="2.0.0",
+ org.apache.tuscany.sca.contribution.resolver;version="2.0.0",
+ org.apache.tuscany.sca.core;version="2.0.0",
+ org.apache.tuscany.sca.core.assembly;version="2.0.0",
+ org.apache.tuscany.sca.core.context;version="2.0.0",
+ org.apache.tuscany.sca.core.factory;version="2.0.0",
+ org.apache.tuscany.sca.core.invocation;version="2.0.0",
+ org.apache.tuscany.sca.core.scope;version="2.0.0",
+ org.apache.tuscany.sca.definitions;version="2.0.0",
+ org.apache.tuscany.sca.extensibility;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef.impl;version="2.0.0";resolution:=optional,
+ org.apache.tuscany.sca.interfacedef.java;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef.util;version="2.0.0",
+ org.apache.tuscany.sca.invocation;version="2.0.0",
+ org.apache.tuscany.sca.monitor;version="2.0.0",
+ org.apache.tuscany.sca.policy;version="2.0.0",
+ org.apache.tuscany.sca.provider;version="2.0.0",
+ org.apache.tuscany.sca.runtime;version="2.0.0",
+ org.apache.tuscany.sca.work;version="2.0.0",
+ org.oasisopen.sca;version="2.0.0",
+ org.oasisopen.sca.annotation;version="2.0.0"
+Bundle-SymbolicName: org.apache.tuscany.sca.core
+Bundle-DocURL: http://www.apache.org/
+Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/NOTICE b/sca-java-2.x/branches/2.0-Beta1/modules/core/NOTICE new file mode 100644 index 0000000000..ad2ba40961 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2010 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/pom.xml b/sca-java-2.x/branches/2.0-Beta1/modules/core/pom.xml new file mode 100644 index 0000000000..64b8152cf8 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/pom.xml @@ -0,0 +1,89 @@ +<?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>2.0-Beta1-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-core</artifactId> + <name>Apache Tuscany SCA Core Runtime</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-extensibility</artifactId> + <version>2.0-Beta1-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core-spi</artifactId> + <version>2.0-Beta1-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-contribution</artifactId> + <version>2.0-Beta1-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-interface-java</artifactId> + <version>2.0-Beta1-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.geronimo.specs</groupId> + <artifactId>geronimo-stax-api_1.0_spec</artifactId> + <version>1.0.1</version> + </dependency> + + <dependency> + <groupId>org.codehaus.woodstox</groupId> + <artifactId>wstx-asl</artifactId> + <version>3.2.4</version> + <scope>runtime</scope> + <exclusions> + <exclusion> + <groupId>stax</groupId> + <artifactId>stax-api</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>cglib</groupId> + <artifactId>cglib</artifactId> + <version>2.2</version> + </dependency> + + <dependency> + <groupId>asm</groupId> + <artifactId>asm</artifactId> + <version>3.1</version> + </dependency> + + </dependencies> + +</project> diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.java new file mode 100644 index 0000000000..790cc6ec98 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/RuntimeAssemblyFactory.java @@ -0,0 +1,75 @@ +/* + * 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.core.assembly; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.assembly.impl.RuntimeComponentImpl; +import org.apache.tuscany.sca.core.assembly.impl.RuntimeComponentReferenceImpl; +import org.apache.tuscany.sca.core.assembly.impl.RuntimeComponentServiceImpl; +import org.apache.tuscany.sca.core.assembly.impl.RuntimeEndpointImpl; +import org.apache.tuscany.sca.core.assembly.impl.RuntimeEndpointReferenceImpl; + + +/** + * The runtime version of assembly factory + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public class RuntimeAssemblyFactory extends DefaultAssemblyFactory implements AssemblyFactory { + + public RuntimeAssemblyFactory(ExtensionPointRegistry registry) { + super(registry); + } + + @Override + public Component createComponent() { + return new RuntimeComponentImpl(); + } + + @Override + public ComponentReference createComponentReference() { + return new RuntimeComponentReferenceImpl(); + } + + @Override + public ComponentService createComponentService() { + return new RuntimeComponentServiceImpl(); + } + + @Override + public Endpoint createEndpoint() { + // Create an instance of EndpointImpl that can be serialized/deserialized using the Tuscany + // runtime extension points and extensions + return new RuntimeEndpointImpl(registry); + } + + @Override + public EndpointReference createEndpointReference() { + return new RuntimeEndpointReferenceImpl(registry); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/CompositeActivatorImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/CompositeActivatorImpl.java new file mode 100644 index 0000000000..db345826d1 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/CompositeActivatorImpl.java @@ -0,0 +1,607 @@ +/* + * 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.core.assembly.impl; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Composite; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.context.CompositeContext; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.ScopeRegistry; +import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.ImplementationProviderFactory; +import org.apache.tuscany.sca.provider.PolicyProvider; +import org.apache.tuscany.sca.provider.PolicyProviderFactory; +import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint; +import org.apache.tuscany.sca.provider.ReferenceBindingProvider; +import org.apache.tuscany.sca.provider.RuntimeProvider; +import org.apache.tuscany.sca.provider.ServiceBindingProvider; +import org.apache.tuscany.sca.runtime.ActivationException; +import org.apache.tuscany.sca.runtime.CompositeActivator; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; + +/** + * @version $Rev$ $Date$ + */ +public class CompositeActivatorImpl implements CompositeActivator { + final Logger logger = Logger.getLogger(CompositeActivatorImpl.class.getName()); + + private final ScopeRegistry scopeRegistry; + private final ProviderFactoryExtensionPoint providerFactories; + + public CompositeActivatorImpl(ExtensionPointRegistry extensionPoints) { + UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class); + this.scopeRegistry = utilities.getUtility(ScopeRegistry.class); + this.providerFactories = extensionPoints.getExtensionPoint(ProviderFactoryExtensionPoint.class); + } + + //========================================================================= + // Activation + //========================================================================= + + // Composite activation/deactivation + + public void activate(CompositeContext compositeContext, Composite composite) throws ActivationException { + try { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Activating composite: " + composite.getName()); + } + for (Component component : composite.getComponents()) { + activateComponent(compositeContext, component); + } + } catch (Exception e) { + throw new ActivationException(e); + } + } + + public void deactivate(Composite composite) throws ActivationException { + try { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Deactivating composite: " + composite.getName()); + } + for (Component component : composite.getComponents()) { + deactivateComponent(component); + } + } catch (Exception e) { + throw new ActivationException(e); + } + } + + // Component activation/deactivation + + public void activateComponent(CompositeContext compositeContext, Component component) + throws ActivationException { + try { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Activating component: " + component.getURI()); + } + + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + activate(compositeContext, (Composite) implementation); + } else if (implementation != null) { + addImplementationProvider((RuntimeComponent) component, + implementation); + addScopeContainer(component); + } + + for (ComponentService service : component.getServices()) { + activate(compositeContext, + (RuntimeComponent) component, (RuntimeComponentService) service); + } + + for (ComponentReference reference : component.getReferences()) { + activate(compositeContext, + (RuntimeComponent) component, (RuntimeComponentReference) reference); + } + } catch (Exception e) { + throw new ActivationException(e); + } + } + + public void deactivateComponent(Component component) + throws ActivationException { + try { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Deactivating component: " + component.getURI()); + } + for (ComponentService service : component.getServices()) { + deactivate((RuntimeComponent) component, + (RuntimeComponentService) service); + } + + for (ComponentReference reference : component.getReferences()) { + deactivate((RuntimeComponent) component, + (RuntimeComponentReference) reference); + } + + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + deactivate((Composite) implementation); + } else if (implementation != null) { + removeImplementationProvider((RuntimeComponent) component); + removeScopeContainer(component); + } + } catch (Exception e) { + throw new ActivationException(e); + } + } + + // add/remove artifacts required to get the implementation going + + private void addImplementationProvider(RuntimeComponent component, Implementation implementation) { + ImplementationProviderFactory providerFactory = + (ImplementationProviderFactory)providerFactories.getProviderFactory(implementation.getClass()); + if (providerFactory != null) { + @SuppressWarnings("unchecked") + ImplementationProvider implementationProvider = + providerFactory.createImplementationProvider(component, implementation); + if (implementationProvider != null) { + component.setImplementationProvider(implementationProvider); + } + } else { + throw new IllegalStateException("Provider factory not found for class: " + implementation.getClass() + .getName()); + } + for (PolicyProviderFactory f : providerFactories.getPolicyProviderFactories()) { + PolicyProvider policyProvider = f.createImplementationPolicyProvider(component); + if (policyProvider != null) { + component.addPolicyProvider(policyProvider); + } + } + + } + + private void removeImplementationProvider(RuntimeComponent component) { + component.setImplementationProvider(null); + component.getPolicyProviders().clear(); + } + + private void addScopeContainer(Component component) { + if (!(component instanceof ScopedRuntimeComponent)) { + return; + } + ScopedRuntimeComponent runtimeComponent = (ScopedRuntimeComponent)component; + ScopeContainer scopeContainer = scopeRegistry.getScopeContainer(runtimeComponent); + runtimeComponent.setScopeContainer(scopeContainer); + } + + private void removeScopeContainer(Component component) { + if (!(component instanceof ScopedRuntimeComponent)) { + return; + } + ScopedRuntimeComponent runtimeComponent = (ScopedRuntimeComponent)component; + ScopeContainer scopeContainer = runtimeComponent.getScopeContainer(); + runtimeComponent.setScopeContainer(null); + } + + + // Service activation/deactivation + + public void activate(CompositeContext compositeContext, RuntimeComponent component, RuntimeComponentService service) { + if (service.getService() == null) { + if (logger.isLoggable(Level.WARNING)) { + logger.warning("Skipping component service not defined in the component type: " + component.getURI() + + "#" + + service.getName()); + } + return; + } + + if (logger.isLoggable(Level.FINE)) { + logger.fine("Activating component service: " + component.getURI() + "#" + service.getName()); + } + + // Add a wire for each service Endpoint + for ( Endpoint endpoint : service.getEndpoints()){ + RuntimeEndpoint ep = (RuntimeEndpoint) endpoint; + activate(compositeContext, ep); + + // create the interface contract for the binding and service ends of the wire + // that are created as forward only contracts + // FIXME: [rfeng] We might need a better way to get the impl interface contract + Service targetService = service.getService(); + if (targetService == null) { + targetService = service; + } + // endpoint.setInterfaceContract(targetService.getInterfaceContract().makeUnidirectional(false)); + } + } + + public void activate(CompositeContext compositeContext, RuntimeEndpoint ep) { + ep.bind(compositeContext); + + // Check that the service binding interface is compatible with the + // service interface + ep.validateServiceInterfaceCompatibility(); + } + + public void deactivate(RuntimeComponent component, RuntimeComponentService service) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Deactivating component service: " + component.getURI() + "#" + service.getName()); + } + for(Endpoint ep: service.getEndpoints()) { + if(ep instanceof RuntimeEndpoint) { + deactivate((RuntimeEndpoint) ep); + } + } + } + + public void deactivate(RuntimeEndpoint ep) { + ep.unbind(); + } + + // Reference activation/deactivation + + public void activate(CompositeContext compositeContext, RuntimeComponent component, RuntimeComponentReference reference) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Activating component reference: " + component.getURI() + "#" + reference.getName()); + } + + // set the parent component onto the reference. It's used at start time when the + // reference is asked to return it's runtime wires. If there are none the reference + // asks the component context to start the reference which creates the wires + reference.setComponent(component); + for(EndpointReference epr: reference.getEndpointReferences()) { + activate(compositeContext, (RuntimeEndpointReference) epr); + } + + } + + public void deactivate(RuntimeComponent component, RuntimeComponentReference reference) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Deactivating component reference: " + component.getURI() + "#" + reference.getName()); + } + for(EndpointReference endpointReference: reference.getEndpointReferences()) { + deactivate((RuntimeEndpointReference)endpointReference); + } + } + + public void activate(CompositeContext compositeContext, RuntimeEndpointReference epr) { + // create the wire + // null endpoint passed in here as the endpoint reference may + // not be resolved yet + epr.bind(compositeContext); + + ComponentReference reference = epr.getReference(); + InterfaceContract sourceContract = epr.getComponentTypeReferenceInterfaceContract(); + + // TODO - EPR - interface contract seems to be null in the implementation.web + // case. Not introspecting the CT properly? + if (sourceContract == null){ + // TODO - Can't do this with move of matching to wire + // take the contract from the service to which the reference is connected + sourceContract = ((RuntimeEndpoint) epr.getTargetEndpoint()).getComponentTypeServiceInterfaceContract(); + reference.setInterfaceContract(sourceContract); + } + + // endpointReference.setInterfaceContract(sourceContract.makeUnidirectional(false)); + + // if the reference already has a binding we can check the reference binding interface + // and reference interfaces for compatibility. If we can't check now compatibility + // will be checked when the endpoint reference is resolved. + if (epr.getStatus() == EndpointReference.Status.RESOLVED_BINDING){ + epr.validateReferenceInterfaceCompatibility(); + } + } + + public void deactivate(RuntimeEndpointReference endpointReference) { + endpointReference.unbind(); + } + + //========================================================================= + // Start + //========================================================================= + + // Composite start/stop + + public void start(CompositeContext compositeContext, Composite composite) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Starting composite: " + composite.getName()); + } + for (Component component : composite.getComponents()) { + start(compositeContext, component); + } + + for (Component component : composite.getComponents()) { + if (component instanceof ScopedRuntimeComponent) { + start(compositeContext, (ScopedRuntimeComponent)component); + } + } + } + + public void stop(CompositeContext compositeContext, Composite composite) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Stopping composite: " + composite.getName()); + } + for (final Component component : composite.getComponents()) { + stop(compositeContext, component); + } + } + + // Component start/stop + + public void start(CompositeContext compositeContext, Component component) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Starting component: " + component.getURI()); + } + RuntimeComponent runtimeComponent = ((RuntimeComponent)component); + if(runtimeComponent.isStarted()) { + return; + } + + compositeContext.bindComponent(runtimeComponent); + Implementation implementation = component.getImplementation(); + + List<RuntimeProvider> providers = new ArrayList<RuntimeProvider>(); + try { + + if (implementation instanceof Composite) { + try { + start(compositeContext, (Composite)implementation); + } catch (Throwable e) { + try { + stop(compositeContext, (Composite) implementation); + } catch (Throwable e1) { + logger.log(Level.SEVERE, e1.getMessage(), e1); + } + rethrow(e); + } + } else { + for (PolicyProvider policyProvider : runtimeComponent.getPolicyProviders()) { + policyProvider.start(); + providers.add(policyProvider); + } + ImplementationProvider implementationProvider = runtimeComponent.getImplementationProvider(); + if (implementationProvider != null) { + implementationProvider.start(); + providers.add(implementationProvider); + } + } + + // Reference bindings aren't started until the wire is first used although this may + // happen when the scope container is started in the case of @EagerInit + + for (ComponentService service : component.getServices()) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Starting component service: " + component.getURI() + "#" + service.getName()); + } + for (Endpoint endpoint : service.getEndpoints()) { + RuntimeEndpoint ep = (RuntimeEndpoint)endpoint; + startEndpoint(compositeContext, ep, providers); + } + } + } catch (Throwable e) { + for (int i = providers.size() - 1; i >= 0; i--) { + try { + providers.get(i).stop(); + } catch (Throwable e1) { + logger.log(Level.SEVERE, e1.getMessage(), e1); + } + } + rethrow(e); + } finally { + providers.clear(); + } + + runtimeComponent.setStarted(true); + } + + private void rethrow(Throwable e) throws Error { + if(e instanceof RuntimeException) { + throw (RuntimeException) e; + } else if(e instanceof Error) { + throw (Error) e; + } + } + + public void start(CompositeContext compositeContext, RuntimeEndpoint ep) { + startEndpoint(compositeContext, ep, null); + } + + private void startEndpoint(CompositeContext compositeContext, RuntimeEndpoint ep, final List<RuntimeProvider> providers) { + // FIXME: Should the policy providers be started before the endpoint is started? + for (PolicyProvider policyProvider : ep.getPolicyProviders()) { + policyProvider.start(); + if (providers != null) { + providers.add(policyProvider); + } + } + + final ServiceBindingProvider bindingProvider = ep.getBindingProvider(); + if (bindingProvider != null) { + // bindingProvider.start(); + // Allow bindings to add shutdown hooks. Requires RuntimePermission shutdownHooks in policy. + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + bindingProvider.start(); + if (providers != null) { + providers.add(bindingProvider); + } + return null; + } + }); + compositeContext.getEndpointRegistry().addEndpoint(ep); + } + } + + public void stop(CompositeContext compositeContext, Component component) { + if (!((RuntimeComponent)component).isStarted()) { + return; + } + if (logger.isLoggable(Level.FINE)) { + logger.fine("Stopping component: " + component.getURI()); + } + for (ComponentService service : component.getServices()) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Stopping component service: " + component.getURI() + "#" + service.getName()); + } + for (Endpoint endpoint : service.getEndpoints()) { + RuntimeEndpoint ep = (RuntimeEndpoint) endpoint; + stop(ep); + } + } + for (ComponentReference reference : component.getReferences()) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Stopping component reference: " + component.getURI() + "#" + reference.getName()); + } + + for (EndpointReference endpointReference : reference.getEndpointReferences()) { + RuntimeEndpointReference epr = (RuntimeEndpointReference) endpointReference; + stop(epr); + } + } + Implementation implementation = component.getImplementation(); + if (implementation instanceof Composite) { + stop(compositeContext, (Composite)implementation); + } else { + final ImplementationProvider implementationProvider = ((RuntimeComponent)component).getImplementationProvider(); + if (implementationProvider != null) { + // Allow bindings to read properties. Requires PropertyPermission read in security policy. + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + implementationProvider.stop(); + return null; + } + }); + } + for (PolicyProvider policyProvider : ((RuntimeComponent)component).getPolicyProviders()) { + policyProvider.stop(); + } + } + + if (component instanceof ScopedRuntimeComponent) { + ScopedRuntimeComponent runtimeComponent = (ScopedRuntimeComponent)component; + if (runtimeComponent.getScopeContainer() != null && + runtimeComponent.getScopeContainer().getLifecycleState() != ScopeContainer.STOPPED) { + runtimeComponent.getScopeContainer().stop(); + } + } + + ((RuntimeComponent)component).setStarted(false); + } + + public void stop(RuntimeEndpoint ep) { + ep.getCompositeContext().getEndpointRegistry().removeEndpoint(ep); + final ServiceBindingProvider bindingProvider = ep.getBindingProvider(); + if (bindingProvider != null) { + // Allow bindings to read properties. Requires PropertyPermission read in security policy. + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + bindingProvider.stop(); + return null; + } + }); + } + for (PolicyProvider policyProvider : ep.getPolicyProviders()) { + policyProvider.stop(); + } + } + + // Scope container start/stop + // separate off from component start that all endpoints are + // registered before any @EagerInit takes place + public void start(CompositeContext compositeContext, ScopedRuntimeComponent scopedRuntimeComponent) { + if (scopedRuntimeComponent.getScopeContainer() != null) { + scopedRuntimeComponent.getScopeContainer().start(); + } + } + + // Service start/stop + + // done as part of the component start above + + // Reference start/stop + // Used by component context start + + public void start(CompositeContext compositeContext, RuntimeComponent component, RuntimeComponentReference componentReference) { + synchronized (componentReference) { + + if (!(componentReference instanceof RuntimeComponentReference)) { + return; + } + + // create a wire for each endpoint reference. An endpoint reference says either that + // - a target has been specified and hence the reference has been wired in some way. + // - an unwired binding ha been specified + // and endpoint reference representing a wired reference may not at this point + // be resolved (the service to which it points may not be present in the + // current composite). Endpoint reference resolution takes place when the wire + // is first used (when the chains are created) + for (EndpointReference endpointReference : componentReference.getEndpointReferences()){ + // addReferenceWire(compositeContext, endpointReference); + start(compositeContext, (RuntimeEndpointReference) endpointReference); + } + + } + } + + public void start(CompositeContext compositeContext, RuntimeEndpointReference endpointReference) { + compositeContext.getEndpointRegistry().addEndpointReference(endpointReference); + } + + public void stop(Component component, ComponentReference reference) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("Stopping component reference: " + component.getURI() + "#" + reference.getName()); + } + RuntimeComponentReference runtimeRef = ((RuntimeComponentReference)reference); + for ( EndpointReference endpointReference : runtimeRef.getEndpointReferences()){ + RuntimeEndpointReference epr = (RuntimeEndpointReference) endpointReference; + stop(epr); + } + } + + public void stop(RuntimeEndpointReference epr) { + if (epr.isStarted()) { + CompositeContext compositeContext = epr.getCompositeContext(); + if (compositeContext == null) { + throw new IllegalStateException("The endpoint reference is not bound"); + } + compositeContext.getEndpointRegistry().removeEndpointReference(epr); + ReferenceBindingProvider bindingProvider = epr.getBindingProvider(); + if (bindingProvider != null) { + bindingProvider.stop(); + } + for (PolicyProvider policyProvider : epr.getPolicyProviders()) { + policyProvider.stop(); + } + } + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointRegistryImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointRegistryImpl.java new file mode 100644 index 0000000000..aa1a4001a4 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointRegistryImpl.java @@ -0,0 +1,119 @@ +/* + * 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.core.assembly.impl; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.LifeCycleListener; +import org.apache.tuscany.sca.runtime.BaseEndpointRegistry; +import org.apache.tuscany.sca.runtime.EndpointListener; +import org.apache.tuscany.sca.runtime.EndpointRegistry; + +/** + * A EndpointRegistry implementation that sees registrations from the same JVM + */ +public class EndpointRegistryImpl extends BaseEndpointRegistry implements EndpointRegistry, LifeCycleListener { + private final Logger logger = Logger.getLogger(EndpointRegistryImpl.class.getName()); + + private List<Endpoint> endpoints = new ArrayList<Endpoint>(); + + public EndpointRegistryImpl(ExtensionPointRegistry extensionPoints, String endpointRegistryURI, String domainURI) { + super(extensionPoints, null, endpointRegistryURI, domainURI); + } + + public synchronized void addEndpoint(Endpoint endpoint) { + endpoints.add(endpoint); + for (EndpointListener listener : listeners) { + listener.endpointAdded(endpoint); + } + logger.info("Add endpoint - " + endpoint.toString()); + } + + public List<Endpoint> findEndpoint(String uri) { + List<Endpoint> foundEndpoints = new ArrayList<Endpoint>(); + for (Endpoint endpoint : endpoints) { + if (endpoint.matches(uri)) { + foundEndpoints.add(endpoint); + logger.fine("Found endpoint with matching service - " + endpoint); + } + // else the service name doesn't match + } + return foundEndpoints; + } + + public synchronized void removeEndpoint(Endpoint endpoint) { + endpoints.remove(endpoint); + endpointRemoved(endpoint); + logger.info("Remove endpoint - " + endpoint.toString()); + } + + public synchronized List<Endpoint> getEndpoints() { + return endpoints; + } + + public synchronized Endpoint getEndpoint(String uri) { + for (Endpoint ep : endpoints) { + String epURI = + ep.getComponent().getURI() + "#" + ep.getService().getName() + "/" + ep.getBinding().getName(); + if (epURI.equals(uri)) { + return ep; + } + if (ep.getBinding().getName() == null || ep.getBinding().getName().equals(ep.getService().getName())) { + epURI = ep.getComponent().getURI() + "#" + ep.getService().getName(); + if (epURI.equals(uri)) { + return ep; + } + } + } + return null; + + } + + public synchronized void updateEndpoint(String uri, Endpoint endpoint) { + Endpoint oldEndpoint = getEndpoint(uri); + if (oldEndpoint == null) { + throw new IllegalArgumentException("Endpoint is not found: " + uri); + } + endpoints.remove(oldEndpoint); + endpoints.add(endpoint); + for (EndpointListener listener : listeners) { + listener.endpointUpdated(oldEndpoint, endpoint); + } + } + + public synchronized void start() { + } + + public synchronized void stop() { + for (Iterator<Endpoint> i = endpoints.iterator(); i.hasNext();) { + Endpoint ep = i.next(); + i.remove(); + endpointRemoved(ep); + } + endpointreferences.clear(); + listeners.clear(); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointSerializerImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointSerializerImpl.java new file mode 100644 index 0000000000..4e5275058e --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/EndpointSerializerImpl.java @@ -0,0 +1,106 @@ +/* + * 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.core.assembly.impl; + +import java.io.StringReader; +import java.io.StringWriter; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.runtime.EndpointSerializer; +import org.oasisopen.sca.ServiceRuntimeException; + +public class EndpointSerializerImpl implements EndpointSerializer { + private ExtensionPointRegistry registry; + private XMLInputFactory inputFactory; + private XMLOutputFactory outputFactory; + private StAXArtifactProcessor<Endpoint> processor; + private StAXArtifactProcessor<EndpointReference> refProcessor; + + public EndpointSerializerImpl(ExtensionPointRegistry registry) { + this.registry = registry; + FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class); + inputFactory = factories.getFactory(XMLInputFactory.class); + outputFactory = factories.getFactory(XMLOutputFactory.class); + StAXArtifactProcessorExtensionPoint processors = + registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + processor = processors.getProcessor(Endpoint.class); + refProcessor = processors.getProcessor(EndpointReference.class); + } + + public Endpoint readEndpoint(String xml) { + try { + XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(xml)); + Endpoint result = processor.read(reader, new ProcessorContext(registry)); + result.setRemote(true); + reader.close(); + return result; + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public String write(Endpoint endpoint) { + StringWriter sw = new StringWriter(); + try { + XMLStreamWriter writer = outputFactory.createXMLStreamWriter(sw); + processor.write(endpoint, writer, new ProcessorContext(registry)); + writer.flush(); + writer.close(); + return sw.toString(); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public EndpointReference readEndpointReference(String xml) { + try { + XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(xml)); + EndpointReference result = refProcessor.read(reader, new ProcessorContext(registry)); + reader.close(); + return result; + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public String write(EndpointReference endpointReference) { + StringWriter sw = new StringWriter(); + try { + XMLStreamWriter writer = outputFactory.createXMLStreamWriter(sw); + refProcessor.write(endpointReference, writer, new ProcessorContext(registry)); + writer.flush(); + writer.close(); + return sw.toString(); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/LocalDomainRegistryFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/LocalDomainRegistryFactory.java new file mode 100644 index 0000000000..b7d83e754a --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/LocalDomainRegistryFactory.java @@ -0,0 +1,49 @@ +/* + * 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.core.assembly.impl; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.runtime.BaseDomainRegistryFactory; +import org.apache.tuscany.sca.runtime.EndpointRegistry; + +/** + * The utility responsible for finding the endpoint regstry by the scheme and creating instances for the + * given domain + */ +public class LocalDomainRegistryFactory extends BaseDomainRegistryFactory { + private final static String[] schemes = new String[] {"local", "vm"}; + + /** + * @param extensionRegistry + */ + public LocalDomainRegistryFactory(ExtensionPointRegistry registry) { + super(registry); + } + + protected EndpointRegistry createEndpointRegistry(String endpointRegistryURI, String domainURI) { + EndpointRegistry endpointRegistry = + new EndpointRegistryImpl(registry, endpointRegistryURI, domainURI); + return endpointRegistry; + } + + public String[] getSupportedSchemes() { + return schemes; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParameterProcessor.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParameterProcessor.java new file mode 100644 index 0000000000..4d6a98ca5f --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParameterProcessor.java @@ -0,0 +1,98 @@ +/* + * 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.core.assembly.impl; + +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.ContributionReadException; +import org.apache.tuscany.sca.contribution.processor.ContributionResolveException; +import org.apache.tuscany.sca.contribution.processor.ContributionWriteException; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.runtime.ReferenceParameters; + +/** + * Artifact processor for reference parameters. + * + * @version $Rev$ $Date$ + */ +public class ReferenceParameterProcessor implements StAXArtifactProcessor<ReferenceParameters> { + private static final QName REFERENCE_PARAMETERS = + new QName("http://tuscany.apache.org/xmlns/sca/1.1", "referenceParameters", "tuscany"); + + /** + * Constructs a new processor. + * + * @param modelFactories + */ + public ReferenceParameterProcessor(FactoryExtensionPoint modelFactories) { + } + + /** + * @see org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor#getArtifactType() + */ + public QName getArtifactType() { + return REFERENCE_PARAMETERS; + } + + /** + * @see org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor#read(javax.xml.stream.XMLStreamReader, ProcessorContext) + */ + public ReferenceParameters read(XMLStreamReader reader, ProcessorContext context) throws ContributionReadException, XMLStreamException { + ReferenceParameters parameters = new ReferenceParametersImpl(); + parameters.setCallbackID(reader.getAttributeValue(null, "callbackID")); + return parameters; + } + + /** + * @see org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor#write(java.lang.Object, javax.xml.stream.XMLStreamWriter, ProcessorContext) + */ + public void write(ReferenceParameters model, XMLStreamWriter writer, ProcessorContext context) throws ContributionWriteException, + XMLStreamException { + writer.writeStartElement(REFERENCE_PARAMETERS.getPrefix(), + REFERENCE_PARAMETERS.getLocalPart(), + REFERENCE_PARAMETERS.getNamespaceURI()); + writer.writeNamespace(REFERENCE_PARAMETERS.getPrefix(), REFERENCE_PARAMETERS.getNamespaceURI()); + + if (model.getCallbackID() != null) { + writer.writeAttribute("callbackID", model.getCallbackID().toString()); + } + writer.writeEndElement(); + } + + /** + * @see org.apache.tuscany.sca.contribution.processor.ArtifactProcessor#getModelType() + */ + public Class<ReferenceParameters> getModelType() { + return ReferenceParameters.class; + } + + /** + * @see org.apache.tuscany.sca.contribution.processor.ArtifactProcessor#resolve(java.lang.Object, org.apache.tuscany.sca.contribution.resolver.ModelResolver, ProcessorContext) + */ + public void resolve(ReferenceParameters model, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParametersImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParametersImpl.java new file mode 100644 index 0000000000..7bd56271a5 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/ReferenceParametersImpl.java @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly.impl; + +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.runtime.ReferenceParameters; + +/** + * @version $Rev$ $Date$ + */ +public class ReferenceParametersImpl implements ReferenceParameters { + private Object callbackID; + private EndpointReference callbackReference; + private Object callbackObjectID; + + /** + * @return the callbackID + */ + public Object getCallbackID() { + return callbackID; + } + /** + * @param callbackID the callbackID to set + */ + public void setCallbackID(Object callbackID) { + this.callbackID = callbackID; + } + + /** + * @see org.apache.tuscany.sca.runtime.ReferenceParameters#getCallbackReference() + */ + public EndpointReference getCallbackReference() { + return callbackReference; + } + /** + * @see org.apache.tuscany.sca.runtime.ReferenceParameters#setCallback(java.lang.Object) + */ + public void setCallbackReference(EndpointReference callback) { + this.callbackReference = callback; + } + + /** + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + /** + * @return the callbackObjectID + */ + public Object getCallbackObjectID() { + return callbackObjectID; + } + /** + * @param callbackObjectID the callbackObjectID to set + */ + public void setCallbackObjectID(Object callbackObjectID) { + this.callbackObjectID = callbackObjectID; + } + /** + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((callbackID == null) ? 0 : callbackID.hashCode()); + result = prime * result + ((callbackObjectID == null) ? 0 : callbackObjectID.hashCode()); + result = prime * result + ((callbackReference == null) ? 0 : callbackReference.hashCode()); + return result; + } + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof ReferenceParametersImpl)) + return false; + final ReferenceParametersImpl other = (ReferenceParametersImpl)obj; + if (callbackID == null) { + if (other.callbackID != null) + return false; + } else if (!callbackID.equals(other.callbackID)) + return false; + if (callbackObjectID == null) { + if (other.callbackObjectID != null) + return false; + } else if (!callbackObjectID.equals(other.callbackObjectID)) + return false; + if (callbackReference == null) { + if (other.callbackReference != null) + return false; + } else if (!callbackReference.equals(other.callbackReference)) + return false; + + return true; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentImpl.java new file mode 100644 index 0000000000..6032005b9a --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentImpl.java @@ -0,0 +1,111 @@ +/* + * 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.core.assembly.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.assembly.impl.ComponentImpl; +import org.apache.tuscany.sca.contribution.resolver.ModelResolver; +import org.apache.tuscany.sca.contribution.resolver.ResolverExtension; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.PolicyProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentContext; + +/** + * @version $Rev$ $Date$ + */ +public class RuntimeComponentImpl extends ComponentImpl implements RuntimeComponent, + ScopedRuntimeComponent, ResolverExtension { + protected RuntimeComponentContext componentContext; + protected ImplementationProvider implementationProvider; + protected List<PolicyProvider> policyProviders = new ArrayList<PolicyProvider>(); + protected ScopeContainer scopeContainer; + protected boolean started; + protected ModelResolver modelResolver; + + /** + */ + public RuntimeComponentImpl() { + super(); + } + + public ImplementationProvider getImplementationProvider() { + return implementationProvider; + } + + public void setImplementationProvider(ImplementationProvider provider) { + this.implementationProvider = provider; + } + + public ScopeContainer getScopeContainer() { + return scopeContainer; + } + + public void setScopeContainer(ScopeContainer scopeContainer) { + this.scopeContainer = scopeContainer; + } + + public boolean isStarted() { + return started; + } + + public void setStarted(boolean started) { + this.started = started; + } + + /** + * @return the componentContext + */ + public RuntimeComponentContext getComponentContext() { + return componentContext; + } + + /** + * @param componentContext the componentContext to set + */ + public void setComponentContext(RuntimeComponentContext componentContext) { + this.componentContext = componentContext; + } + + public void addPolicyProvider(PolicyProvider policyProvider) { + policyProviders.add(policyProvider); + } + + public List<PolicyProvider> getPolicyProviders() { + return policyProviders; + } + + public ModelResolver getModelResolver() { + return modelResolver; + } + + public void setModelResolver(ModelResolver modelResolver) { + this.modelResolver = modelResolver; + } + + @Override + public String toString() { + return getName(); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentReferenceImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentReferenceImpl.java new file mode 100644 index 0000000000..2eea60ccea --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentReferenceImpl.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly.impl; + +import org.apache.tuscany.sca.assembly.impl.ComponentReferenceImpl; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; + +/** + * Implementation of a Component Reference. + * + * @version $Rev$ $Date$ + */ +public class RuntimeComponentReferenceImpl extends ComponentReferenceImpl implements RuntimeComponentReference { + + private RuntimeComponent component; + + public RuntimeComponentReferenceImpl() { + super(); + } + + /** + * @return the component + */ + public RuntimeComponent getComponent() { + return component; + } + + /** + * @param component the component to set + */ + public void setComponent(RuntimeComponent component) { + this.component = component; + } + + /** + * @see org.apache.tuscany.sca.assembly.impl.ComponentReferenceImpl#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + RuntimeComponentReferenceImpl ref = (RuntimeComponentReferenceImpl)super.clone(); + return ref; + } + + @Override + public String toString() { + return getName(); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentServiceImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentServiceImpl.java new file mode 100644 index 0000000000..bc7e6df878 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeComponentServiceImpl.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.assembly.impl; + +import org.apache.tuscany.sca.assembly.impl.ComponentServiceImpl; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +/** + * Implementation of a Component Service. + * + * @version $Rev$ $Date$ + */ +public class RuntimeComponentServiceImpl extends ComponentServiceImpl implements RuntimeComponentService { + + public RuntimeComponentServiceImpl() { + super(); + } + + @Override + public String toString() { + return getName(); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointImpl.java new file mode 100644 index 0000000000..fe9e437650 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointImpl.java @@ -0,0 +1,820 @@ +/* + * 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.core.assembly.impl; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.StringReader; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.transform.stream.StreamSource; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.CompositeReference; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.Contract; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.assembly.builder.BindingBuilder; +import org.apache.tuscany.sca.assembly.builder.BuilderContext; +import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint; +import org.apache.tuscany.sca.assembly.impl.EndpointImpl; +import org.apache.tuscany.sca.context.CompositeContext; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ValidatingXMLInputFactory; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.assembly.RuntimeAssemblyFactory; +import org.apache.tuscany.sca.core.invocation.AsyncResponseHandler; +import org.apache.tuscany.sca.core.invocation.ExtensibleWireProcessor; +import org.apache.tuscany.sca.core.invocation.NonBlockingInterceptor; +import org.apache.tuscany.sca.core.invocation.RuntimeInvoker; +import org.apache.tuscany.sca.core.invocation.impl.InvocationChainImpl; +import org.apache.tuscany.sca.core.invocation.impl.PhaseManager; +import org.apache.tuscany.sca.interfacedef.Compatibility; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.invocation.Interceptor; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.invocation.Phase; +import org.apache.tuscany.sca.provider.BindingProviderFactory; +import org.apache.tuscany.sca.provider.EndpointProvider; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.PolicyProvider; +import org.apache.tuscany.sca.provider.PolicyProviderFactory; +import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint; +import org.apache.tuscany.sca.provider.ServiceBindingProvider; +import org.apache.tuscany.sca.runtime.EndpointRegistry; +import org.apache.tuscany.sca.runtime.EndpointSerializer; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessor; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint; +import org.apache.tuscany.sca.work.WorkScheduler; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * Runtime model for Endpoint that supports java serialization + */ +public class RuntimeEndpointImpl extends EndpointImpl implements RuntimeEndpoint, Externalizable { + private static final long serialVersionUID = 1L; + private transient CompositeContext compositeContext; + private transient RuntimeWireProcessor wireProcessor; + private transient ProviderFactoryExtensionPoint providerFactories; + private transient InterfaceContractMapper interfaceContractMapper; + private transient WorkScheduler workScheduler; + private transient PhaseManager phaseManager; + private transient MessageFactory messageFactory; + private transient RuntimeInvoker invoker; + private transient EndpointSerializer serializer; + + private transient List<InvocationChain> chains; + private transient Map<Operation, InvocationChain> invocationChainMap = + new ConcurrentHashMap<Operation, InvocationChain>(); + private transient InvocationChain bindingInvocationChain; + + private transient ServiceBindingProvider bindingProvider; + private transient List<PolicyProvider> policyProviders; + private String xml; + + protected InterfaceContract bindingInterfaceContract; + protected InterfaceContract serviceInterfaceContract; + + /** + * No-arg constructor for Java serialization + */ + public RuntimeEndpointImpl() { + super(null); + } + + public RuntimeEndpointImpl(ExtensionPointRegistry registry) { + super(registry); + } + + protected void copyFrom(RuntimeEndpointImpl copy) { + this.xml = copy.xml; + + this.component = copy.component; + this.service = copy.service; + this.interfaceContract = copy.interfaceContract; + this.serviceInterfaceContract = copy.serviceInterfaceContract; + + this.binding = copy.binding; + this.bindingInterfaceContract = copy.interfaceContract; + this.bindingInvocationChain = copy.bindingInvocationChain; + + this.callbackEndpointReferences = copy.callbackEndpointReferences; + + this.requiredIntents = copy.requiredIntents; + this.policySets = copy.policySets; + + this.uri = copy.uri; + this.remote = copy.remote; + this.unresolved = copy.unresolved; + + this.chains = copy.chains; + this.invocationChainMap = copy.invocationChainMap; + this.bindingProvider = copy.bindingProvider; + this.policyProviders = copy.policyProviders; + + if (this.compositeContext == null && copy.compositeContext != null) { + bind(copy.compositeContext); + } + } + + public void bind(CompositeContext compositeContext) { + this.compositeContext = compositeContext; + bind(compositeContext.getExtensionPointRegistry(), compositeContext.getEndpointRegistry()); + } + + public void bind(ExtensionPointRegistry registry, EndpointRegistry endpointRegistry) { + if (compositeContext == null) { + compositeContext = new CompositeContext(registry, endpointRegistry); + } + this.registry = registry; + UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class); + this.interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class); + this.workScheduler = utilities.getUtility(WorkScheduler.class); + this.wireProcessor = + new ExtensibleWireProcessor(registry.getExtensionPoint(RuntimeWireProcessorExtensionPoint.class)); + + this.messageFactory = registry.getExtensionPoint(FactoryExtensionPoint.class).getFactory(MessageFactory.class); + this.invoker = new RuntimeInvoker(this.messageFactory, this); + + this.phaseManager = utilities.getUtility(PhaseManager.class); + this.serializer = utilities.getUtility(EndpointSerializer.class); + this.providerFactories = registry.getExtensionPoint(ProviderFactoryExtensionPoint.class); + this.builders = registry.getExtensionPoint(BuilderExtensionPoint.class); + this.contractBuilder = builders.getContractBuilder(); + } + + public void unbind() { + compositeContext = null; + bindingInvocationChain = null; + chains = null; + bindingProvider = null; + policyProviders = null; + invocationChainMap.clear(); + } + + public synchronized List<InvocationChain> getInvocationChains() { + if (chains == null) { + initInvocationChains(); + } + return chains; + } + + public synchronized InvocationChain getBindingInvocationChain() { + if (bindingInvocationChain == null) { + bindingInvocationChain = new InvocationChainImpl(null, null, false, phaseManager); + initServiceBindingInvocationChains(); + } + return bindingInvocationChain; + } + + /** + * A dummy invocation chain representing null as ConcurrentHashMap doesn't allow null values + */ + private static final InvocationChain NULL_CHAIN = new InvocationChainImpl(null, null, false, null); + + public InvocationChain getInvocationChain(Operation operation) { + InvocationChain cached = invocationChainMap.get(operation); + if (cached == null) { + for (InvocationChain chain : getInvocationChains()) { + Operation op = chain.getTargetOperation(); + + // We used to check compatibility here but this is now validated when the + // chain is created. As the chain operations are the real interface types + // they may be incompatible just because they are described in different + // IDLs + if (operation.getInterface().isRemotable()) { + if (operation.getName().equals(op.getName())) { + invocationChainMap.put(operation, chain); + return chain; + } + } else { + // [rfeng] We need to run the compatibility check for local operations as they + // can be overloaded + if (interfaceContractMapper.isCompatible(operation, op, Compatibility.SUBSET)) { + invocationChainMap.put(operation, chain); + return chain; + } + } + } + // Cache it with the NULL_CHAIN to avoid NPE + invocationChainMap.put(operation, NULL_CHAIN); + return null; + } else { + if (cached == NULL_CHAIN) { + cached = null; + } + return cached; + } + } + + public Message invoke(Message msg) { + // Deal with async callback + // Ensure invocation chains are built... + getInvocationChains(); + if ( !this.getCallbackEndpointReferences().isEmpty() ) { + RuntimeEndpointReference asyncEPR = (RuntimeEndpointReference) this.getCallbackEndpointReferences().get(0); + // Place a link to the callback EPR into the message headers... + msg.getHeaders().put("ASYNC_CALLBACK", asyncEPR ); + } + // end of async callback handling + return invoker.invokeBinding(msg); + } + + public Object invoke(Operation operation, Object[] args) throws InvocationTargetException { + return invoker.invoke(operation, args); + } + + public Message invoke(Operation operation, Message msg) { + return invoker.invoke(operation, msg); + } + + /** + * Navigate the component/componentType inheritence chain to find the leaf contract + * @param contract + * @return + */ + private Contract getLeafContract(Contract contract) { + Contract prev = null; + Contract current = contract; + while (current != null) { + prev = current; + if (current instanceof ComponentReference) { + current = ((ComponentReference)current).getReference(); + } else if (current instanceof CompositeReference) { + current = ((CompositeReference)current).getPromotedReferences().get(0); + } else if (current instanceof ComponentService) { + current = ((ComponentService)current).getService(); + } else if (current instanceof CompositeService) { + current = ((CompositeService)current).getPromotedService(); + } else { + break; + } + if (current == null) { + return prev; + } + } + return current; + } + + /** + * Initialize the invocation chains + */ + private void initInvocationChains() { + chains = new ArrayList<InvocationChain>(); + InterfaceContract sourceContract = getBindingInterfaceContract(); + + // It's the service wire + RuntimeComponentService service = (RuntimeComponentService)getService(); + RuntimeComponent serviceComponent = (RuntimeComponent)getComponent(); + + //InterfaceContract targetContract = getInterfaceContract(); + // TODO - EPR - why is this looking at the component types. The endpoint should have the right interface contract by this time + InterfaceContract targetContract = getComponentTypeServiceInterfaceContract(); + // setInterfaceContract(targetContract); + validateServiceInterfaceCompatibility(); + for (Operation operation : sourceContract.getInterface().getOperations()) { + Operation targetOperation = interfaceContractMapper.map(targetContract.getInterface(), operation); + if (targetOperation == null) { + throw new ServiceRuntimeException("No matching operation for " + operation.getName() + + " is found in service " + + serviceComponent.getURI() + + "#" + + service.getName()); + } + InvocationChain chain = new InvocationChainImpl(operation, targetOperation, false, phaseManager); + if (operation.isNonBlocking()) { + addNonBlockingInterceptor(chain); + } + addServiceBindingInterceptor(chain, operation); + addImplementationInterceptor(serviceComponent, service, chain, targetOperation); + chains.add(chain); + + // Handle cases where the operation is an async server + if( targetOperation.isAsyncServer() ) { + createAsyncServerCallback( this, operation ); + } // end if + } + + wireProcessor.process(this); + } + + /** + * Creates the async callback for the supplied Endpoint and Operation, if it does not already exist + * and stores it into the Endpoint + * @param endpoint - the Endpoint + * @param operation - the Operation + */ + private void createAsyncServerCallback( RuntimeEndpoint endpoint, Operation operation ) { + // Check to see if the callback already exists + if( asyncCallbackExists( endpoint ) ) return; + + RuntimeEndpointReference asyncEPR = createAsyncEPR( endpoint ); + + // Store the new callback EPR into the Endpoint + endpoint.getCallbackEndpointReferences().add(asyncEPR); + } // end method createAsyncServerCallback + + /** + * Creates the Endpoint object for the async callback + * @param endpoint - the endpoint which has the async server operations + * @return the EndpointReference object representing the callback + */ + private RuntimeEndpointReference createAsyncEPR( RuntimeEndpoint endpoint ){ + CompositeContext compositeContext = endpoint.getCompositeContext(); + RuntimeAssemblyFactory assemblyFactory = getAssemblyFactory( compositeContext ); + RuntimeEndpointReference epr = (RuntimeEndpointReference)assemblyFactory.createEndpointReference(); + epr.bind( compositeContext ); + + // Create pseudo-reference + ComponentReference reference = assemblyFactory.createComponentReference(); + ExtensionPointRegistry registry = compositeContext.getExtensionPointRegistry(); + FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class); + JavaInterfaceFactory javaInterfaceFactory = (JavaInterfaceFactory)modelFactories.getFactory(JavaInterfaceFactory.class); + JavaInterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract(); + try { + interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(AsyncResponseHandler.class)); + } catch (InvalidInterfaceException e1) { + // Nothing to do here - will not happen + } // end try + reference.setInterfaceContract(interfaceContract); + String referenceName = endpoint.getService().getName() + "_asyncCallback"; + reference.setName(referenceName); + reference.setForCallback(true); + epr.setReference(reference); + + // Create a binding + Binding binding = createMatchingBinding( endpoint.getBinding(), (RuntimeComponent)endpoint.getComponent(), reference, registry ); + epr.setBinding(binding); + + // Need to establish policies here (binding has some...) + epr.getRequiredIntents().addAll( endpoint.getRequiredIntents() ); + epr.getPolicySets().addAll( endpoint.getPolicySets() ); + String eprURI = endpoint.getComponent().getName() + "#reference-binding(" + referenceName + "/" + referenceName + ")"; + epr.setURI(eprURI); + + // Attach a dummy endpoint to the epr + RuntimeEndpoint ep = (RuntimeEndpoint)assemblyFactory.createEndpoint(); + ep.setUnresolved(false); + epr.setTargetEndpoint(ep); + //epr.setStatus(EndpointReference.Status.RESOLVED_BINDING); + epr.setStatus(EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED); + epr.setUnresolved(false); + + return epr; + } // end method RuntimeEndpointReference + + private boolean asyncCallbackExists( RuntimeEndpoint endpoint ) { + if( endpoint.getCallbackEndpointReferences().isEmpty() ) return false; + return true; + } // end method asyncCallbackExists + + /** + * Create a matching binding to a supplied binding + * - the matching binding has the same binding type, but is for the supplied component and service + * @param matchBinding - the binding to match + * @param component - the component + * @param service - the service + * @param registry - registry for extensions + * @return - the matching binding, or null if it could not be created + */ + @SuppressWarnings("unchecked") + private Binding createMatchingBinding( Binding matchBinding, RuntimeComponent component, + ComponentReference reference, ExtensionPointRegistry registry ) { + // Since there is no simple way to obtain a Factory for a binding where the type is not known ahead of + // time, the process followed here is to generate the <binding.xxx/> XML element from the binding type QName + // and then read the XML using the processor for that XML... + QName bindingName = matchBinding.getType(); + String bindingXML = "<ns1:" + bindingName.getLocalPart() + " xmlns:ns1='" + bindingName.getNamespaceURI() + "'/>"; + + StAXArtifactProcessorExtensionPoint processors = registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + StAXArtifactProcessor<?> processor = (StAXArtifactProcessor<?>)processors.getProcessor(bindingName); + + FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class); + ValidatingXMLInputFactory inputFactory = modelFactories.getFactory(ValidatingXMLInputFactory.class); + StreamSource source = new StreamSource( new StringReader(bindingXML) ); + + ProcessorContext context = new ProcessorContext(); + try { + XMLStreamReader reader = inputFactory.createXMLStreamReader(source); + reader.next(); + Binding newBinding = (Binding) processor.read(reader, context ); + newBinding.setName("asyncCallback"); + + // Create a URI address for the callback based on the Component_Name/Reference_Name pattern + String callbackURI = "/" + component.getName() + "/" + reference.getName(); + //newBinding.setURI(callbackURI); + + BuilderExtensionPoint builders = registry.getExtensionPoint(BuilderExtensionPoint.class); + BindingBuilder builder = builders.getBindingBuilder(newBinding.getType()); + if (builder != null) { + org.apache.tuscany.sca.assembly.builder.BuilderContext builderContext = new BuilderContext(registry); + builder.build(component, reference, newBinding, builderContext, true); + } // end if + + return newBinding; + } catch (ContributionReadException e) { + e.printStackTrace(); + } catch (XMLStreamException e) { + e.printStackTrace(); + } + + return null; + } // end method createMatchingBinding + + /** + * Gets a RuntimeAssemblyFactory from the CompositeContext + * @param compositeContext + * @return the RuntimeAssemblyFactory + */ + private RuntimeAssemblyFactory getAssemblyFactory( CompositeContext compositeContext ) { + ExtensionPointRegistry registry = compositeContext.getExtensionPointRegistry(); + FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class); + return (RuntimeAssemblyFactory)modelFactories.getFactory(AssemblyFactory.class); + } // end method RuntimeAssemblyFactory + + /** + * Check that endpoint has compatible interface at the component and binding ends. + * The user can specify the interfaces at both ends so there is a danger that they won't be compatible. + */ + public void validateServiceInterfaceCompatibility() { + + InterfaceContract serviceContract = getComponentServiceInterfaceContract(); + InterfaceContract bindingContract = getBindingInterfaceContract(); + + if ((serviceContract != null) && + (bindingContract != null)){ + + boolean bindingHasCallback = bindingContract.getCallbackInterface() != null; + + try { + if ((serviceContract.getClass() != bindingContract.getClass()) && + (serviceContract instanceof JavaInterfaceContract)) { + interfaceContractMapper.checkCompatibility(getGeneratedWSDLContract(serviceContract), + bindingContract, + Compatibility.SUBSET, + !bindingHasCallback, // ignore callbacks if binding doesn't have one + false); + } else { + interfaceContractMapper.checkCompatibility(serviceContract, + bindingContract, + Compatibility.SUBSET, + !bindingHasCallback, // ignore callbacks if binding doesn't have one + false); + } + } catch (Exception ex){ + throw new ServiceRuntimeException("Component " + + this.getComponent().getName() + + " Service " + + getService().getName() + + " interface is incompatible with the interface of the reference binding - " + + getBinding().getName() + + " - " + + ex.getMessage() + + " - [" + this.toString() + "]"); + } + } + + } + + private void initServiceBindingInvocationChains() { + + // add the binding interceptors to the service binding wire + ServiceBindingProvider provider = getBindingProvider(); + if ((provider != null) && (provider instanceof EndpointProvider)) { + ((EndpointProvider)provider).configure(); + } + + // add the policy interceptors to the service binding wire + List<PolicyProvider> pps = getPolicyProviders(); + if (pps != null) { + for (PolicyProvider p : pps) { + Interceptor interceptor = p.createBindingInterceptor(); + if (interceptor != null) { + bindingInvocationChain.addInterceptor(interceptor); + } + } + + } + + // TODO - add something on the end of the wire to invoke the + // invocation chain. Need to split out the runtime + // wire invoker into conversation, callback interceptors etc + bindingInvocationChain.addInvoker(invoker); + + } + + /** + * Add the interceptor for a binding + * + * @param reference + * @param binding + * @param chain + * @param operation + */ + private void addServiceBindingInterceptor(InvocationChain chain, Operation operation) { + List<PolicyProvider> pps = getPolicyProviders(); + if (pps != null) { + for (PolicyProvider p : pps) { + Interceptor interceptor = p.createInterceptor(operation); + if (interceptor != null) { + chain.addInterceptor(interceptor); + } + } + } + } + + /** + * Add a non-blocking interceptor if the service binding needs it + * + * @param service + * @param binding + * @param chain + */ + private void addNonBlockingInterceptor(InvocationChain chain) { + ServiceBindingProvider provider = getBindingProvider(); + if (provider != null) { + if (!provider.supportsOneWayInvocation()) { + chain.addInterceptor(Phase.SERVICE, new NonBlockingInterceptor(workScheduler)); + } + } + } + + /** + * Add the interceptor for a component implementation + * + * @param component + * @param service + * @param chain + * @param operation + */ + private void addImplementationInterceptor(Component component, + ComponentService service, + InvocationChain chain, + Operation operation) { + + if (service.getService() instanceof CompositeService) { + CompositeService compositeService = (CompositeService)service.getService(); + component = getPromotedComponent(compositeService); + service = getPromotedComponentService(compositeService); + } + + ImplementationProvider provider = ((RuntimeComponent)component).getImplementationProvider(); + + if (provider != null) { + Invoker invoker = null; + invoker = provider.createInvoker((RuntimeComponentService)service, operation); + chain.addInvoker(invoker); + } + // TODO - EPR - don't we need to get the policy from the right level in the + // model rather than the leafmost level + List<PolicyProvider> pps = ((RuntimeComponent)component).getPolicyProviders(); + if (pps != null) { + for (PolicyProvider p : pps) { + Interceptor interceptor = p.createInterceptor(operation); + if (interceptor != null) { + //chain.addInterceptor(p.createInterceptor(operation)); + chain.addInterceptor(interceptor); + } + } + } + } + + /** + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + RuntimeEndpointImpl copy = (RuntimeEndpointImpl)super.clone(); + copy.invoker = new RuntimeInvoker(copy.messageFactory, copy); + return copy; + } + + /** + * Follow a service promotion chain down to the inner most (non composite) + * component service. + * + * @param topCompositeService + * @return + */ + private ComponentService getPromotedComponentService(CompositeService compositeService) { + ComponentService componentService = compositeService.getPromotedService(); + if (componentService != null) { + Service service = componentService.getService(); + if (componentService.getName() != null && service instanceof CompositeService) { + + // Continue to follow the service promotion chain + return getPromotedComponentService((CompositeService)service); + + } else { + + // Found a non-composite service + return componentService; + } + } else { + + // No promoted service + return null; + } + } + + /** + * Follow a service promotion chain down to the innermost (non-composite) component. + * + * @param compositeService + * @return + */ + private Component getPromotedComponent(CompositeService compositeService) { + ComponentService componentService = compositeService.getPromotedService(); + if (componentService != null) { + Service service = componentService.getService(); + if (componentService.getName() != null && service instanceof CompositeService) { + + // Continue to follow the service promotion chain + return getPromotedComponent((CompositeService)service); + + } else { + + // Found a non-composite service + return compositeService.getPromotedComponent(); + } + } else { + + // No promoted service + return null; + } + } + + public synchronized ServiceBindingProvider getBindingProvider() { + resolve(); + if (bindingProvider == null) { + BindingProviderFactory factory = + (BindingProviderFactory)providerFactories.getProviderFactory(getBinding().getClass()); + if (factory == null) { + throw new ServiceRuntimeException("No provider factory is registered for binding " + getBinding() + .getType()); + } + this.bindingProvider = factory.createServiceBindingProvider(this); + } + return bindingProvider; + } + + public synchronized List<PolicyProvider> getPolicyProviders() { + resolve(); + if (policyProviders == null) { + policyProviders = new ArrayList<PolicyProvider>(); + for (PolicyProviderFactory factory : providerFactories.getPolicyProviderFactories()) { + PolicyProvider provider = factory.createServicePolicyProvider(this); + if (provider != null) { + policyProviders.add(provider); + } + } + } + return policyProviders; + } + + public void setBindingProvider(ServiceBindingProvider provider) { + this.bindingProvider = provider; + } + + public Contract getContract() { + return getService(); + } + + public CompositeContext getCompositeContext() { + return compositeContext; + } + + @Override + protected void reset() { + super.reset(); + this.xml = null; + } + + @Override + protected synchronized void resolve() { + if (xml != null && component == null) { + if (compositeContext == null) { + compositeContext = CompositeContext.getCurrentCompositeContext(); + if (compositeContext != null) { + bind(compositeContext); + } + } + if (serializer != null) { + RuntimeEndpointImpl ep = (RuntimeEndpointImpl)serializer.readEndpoint(xml); + copyFrom(ep); + } else { + // FIXME: [rfeng] What should we do here? + } + } + super.resolve(); + } + + public InterfaceContract getBindingInterfaceContract() { + resolve(); + if (bindingInterfaceContract != null) { + return bindingInterfaceContract; + } + bindingInterfaceContract = getBindingProvider().getBindingInterfaceContract(); + if (bindingInterfaceContract == null) { + bindingInterfaceContract = getComponentServiceInterfaceContract(); + } + if (bindingInterfaceContract == null) { + bindingInterfaceContract = getComponentTypeServiceInterfaceContract(); + } + return bindingInterfaceContract; + } + + public InterfaceContract getComponentTypeServiceInterfaceContract() { + resolve(); + if (serviceInterfaceContract != null) { + return serviceInterfaceContract; + } + if (service == null) { + return getComponentServiceInterfaceContract(); + } + serviceInterfaceContract = getLeafContract(service).getInterfaceContract(); + if (serviceInterfaceContract == null) { + serviceInterfaceContract = getComponentServiceInterfaceContract(); + } + return serviceInterfaceContract; + } + + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + this.uri = in.readUTF(); + this.xml = in.readUTF(); + } + + public void writeExternal(ObjectOutput out) throws IOException { + out.writeUTF(getURI()); + if (serializer == null && xml != null) { + out.writeUTF(xml); + } else { + if (serializer != null) { + out.writeUTF(serializer.write(this)); + } else { + throw new IllegalStateException("No serializer is configured"); + } + } + } + public InterfaceContract getGeneratedWSDLContract(InterfaceContract interfaceContract) { + + if ( interfaceContract.getNormalizedWSDLContract() == null){ + if (getComponentServiceInterfaceContract() instanceof JavaInterfaceContract){ + if (contractBuilder == null){ + throw new ServiceRuntimeException("Contract builder not found while calculating WSDL contract for " + this.toString()); + } + contractBuilder.build(getComponentServiceInterfaceContract(), null); + } + } + + return interfaceContract.getNormalizedWSDLContract(); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointReferenceImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointReferenceImpl.java new file mode 100644 index 0000000000..3873185e6b --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/assembly/impl/RuntimeEndpointReferenceImpl.java @@ -0,0 +1,617 @@ +/* + * 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.core.assembly.impl; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.lang.reflect.InvocationTargetException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.CompositeReference; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.Contract; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint; +import org.apache.tuscany.sca.assembly.builder.ContractBuilder; +import org.apache.tuscany.sca.assembly.impl.EndpointReferenceImpl; +import org.apache.tuscany.sca.context.CompositeContext; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.invocation.ExtensibleWireProcessor; +import org.apache.tuscany.sca.core.invocation.NonBlockingInterceptor; +import org.apache.tuscany.sca.core.invocation.RuntimeInvoker; +import org.apache.tuscany.sca.core.invocation.impl.InvocationChainImpl; +import org.apache.tuscany.sca.core.invocation.impl.PhaseManager; +import org.apache.tuscany.sca.interfacedef.Compatibility; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.invocation.Interceptor; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.invocation.Phase; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.provider.BindingProviderFactory; +import org.apache.tuscany.sca.provider.EndpointReferenceProvider; +import org.apache.tuscany.sca.provider.PolicyProvider; +import org.apache.tuscany.sca.provider.PolicyProviderFactory; +import org.apache.tuscany.sca.provider.ProviderFactoryExtensionPoint; +import org.apache.tuscany.sca.provider.ReferenceBindingProvider; +import org.apache.tuscany.sca.runtime.EndpointReferenceBinder; +import org.apache.tuscany.sca.runtime.EndpointRegistry; +import org.apache.tuscany.sca.runtime.EndpointSerializer; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessor; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint; +import org.apache.tuscany.sca.work.WorkScheduler; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * Runtime model for Endpoint that supports java serialization + */ +public class RuntimeEndpointReferenceImpl extends EndpointReferenceImpl implements RuntimeEndpointReference, Externalizable { + private transient CompositeContext compositeContext; + private transient RuntimeWireProcessor wireProcessor; + private transient InterfaceContractMapper interfaceContractMapper; + private transient WorkScheduler workScheduler; + private transient PhaseManager phaseManager; + private transient MessageFactory messageFactory; + private transient RuntimeInvoker invoker; + private transient EndpointRegistry endpointRegistry; + + private transient List<InvocationChain> chains; + private transient Map<Operation, InvocationChain> invocationChainMap = + new ConcurrentHashMap<Operation, InvocationChain>(); + private transient InvocationChain bindingInvocationChain; + + private transient EndpointReferenceBinder eprBinder; + private transient ReferenceBindingProvider bindingProvider; + private transient ProviderFactoryExtensionPoint providerFactories; + private transient List<PolicyProvider> policyProviders; + private transient EndpointSerializer serializer; + + protected InterfaceContract bindingInterfaceContract; + protected InterfaceContract referenceInterfaceContract; + + //protected InterfaceContract generatedReferenceWSDLInterfaceContract; + + private String xml; + + private boolean started; + + /** + * No-arg constructor for Java serilization + */ + public RuntimeEndpointReferenceImpl() { + super(null); + } + + public RuntimeEndpointReferenceImpl(ExtensionPointRegistry registry) { + super(registry); + } + + protected void copyFrom(RuntimeEndpointReferenceImpl copy) { + this.xml = copy.xml; + + this.component = copy.component; + this.reference = copy.reference; + this.interfaceContract = copy.interfaceContract; + this.referenceInterfaceContract = copy.referenceInterfaceContract; + this.callbackEndpoint = copy.callbackEndpoint; + this.targetEndpoint = copy.targetEndpoint; + + this.binding = copy.binding; + this.bindingInterfaceContract = copy.interfaceContract; + this.bindingInvocationChain = copy.bindingInvocationChain; + + this.requiredIntents = copy.requiredIntents; + this.policySets = copy.policySets; + + this.uri = copy.uri; + this.unresolved = copy.unresolved; + this.status = copy.status; + + this.chains = copy.chains; + this.invocationChainMap = copy.invocationChainMap; + this.bindingProvider = copy.bindingProvider; + this.policyProviders = copy.policyProviders; + + if (this.compositeContext == null && copy.compositeContext != null) { + bind(copy.compositeContext); + } + } + + public void bind(CompositeContext compositeContext) { + this.compositeContext = compositeContext; + bind(compositeContext.getExtensionPointRegistry(), compositeContext.getEndpointRegistry()); + } + + public void bind(ExtensionPointRegistry registry, EndpointRegistry endpointRegistry) { + if (compositeContext == null) { + compositeContext = new CompositeContext(registry, endpointRegistry); + } + this.registry = registry; + this.endpointRegistry = endpointRegistry; + UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class); + this.eprBinder = utilities.getUtility(EndpointReferenceBinder.class); + this.interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class); + this.workScheduler = utilities.getUtility(WorkScheduler.class); + this.wireProcessor = + new ExtensibleWireProcessor(registry.getExtensionPoint(RuntimeWireProcessorExtensionPoint.class)); + + this.messageFactory = registry.getExtensionPoint(FactoryExtensionPoint.class).getFactory(MessageFactory.class); + this.invoker = new RuntimeInvoker(this.messageFactory, this); + + this.phaseManager = utilities.getUtility(PhaseManager.class); + this.serializer = utilities.getUtility(EndpointSerializer.class); + this.providerFactories = registry.getExtensionPoint(ProviderFactoryExtensionPoint.class); + + this.builders = registry.getExtensionPoint(BuilderExtensionPoint.class); + this.contractBuilder = builders.getContractBuilder(); + } + + public synchronized List<InvocationChain> getInvocationChains() { + if (chains == null) { + initInvocationChains(); + } + return chains; + } + + public synchronized InvocationChain getBindingInvocationChain() { + if (bindingInvocationChain == null) { + bindingInvocationChain = new InvocationChainImpl(null, null, true, phaseManager); + initReferenceBindingInvocationChains(); + } + return bindingInvocationChain; + } + + public InvocationChain getInvocationChain(Operation operation) { + InvocationChain cached = invocationChainMap.get(operation); + if (cached == null) { + for (InvocationChain chain : getInvocationChains()) { + Operation op = chain.getSourceOperation(); + + // We used to check compatibility here but this is now validated when the + // chain is created. As the chain operations are the real interface types + // they may be incompatible just because they are described in different + // IDLs + if (operation.getName().equals(op.getName())) { + invocationChainMap.put(operation, chain); + return chain; + } + } + invocationChainMap.put(operation, null); + return null; + } else { + return cached; + } + } + + public Message invoke(Message msg) { + return invoker.invoke(msg); + } + + public Object invoke(Operation operation, Object[] args) throws InvocationTargetException { + return invoker.invoke(operation, args); + } + + public Message invoke(Operation operation, Message msg) { + return invoker.invoke(operation, msg); + } + + /** + * Navigate the component/componentType inheritence chain to find the leaf contract + * @param contract + * @return + */ + private Contract getLeafContract(Contract contract) { + Contract prev = null; + Contract current = contract; + while (current != null) { + prev = current; + if (current instanceof ComponentReference) { + current = ((ComponentReference)current).getReference(); + } else if (current instanceof CompositeReference) { + current = ((CompositeReference)current).getPromotedReferences().get(0); + } else if (current instanceof ComponentService) { + current = ((ComponentService)current).getService(); + } else if (current instanceof CompositeService) { + current = ((CompositeService)current).getPromotedService(); + } else { + break; + } + if (current == null) { + return prev; + } + } + return current; + } + + /** + * Initialize the invocation chains + */ + private void initInvocationChains() { + InterfaceContract sourceContract = getComponentTypeReferenceInterfaceContract(); + // TODO - EPR why is this looking at the component types. The endpoint reference should have the right interface contract by this time + //InterfaceContract sourceContract = getLeafInterfaceContract(endpointReference); + + // It's the reference wire + resolveEndpointReference(); + + InterfaceContract targetContract = getBindingInterfaceContract(); + // TODO - EPR why is this looking at the component types. The endpoint should have the right interface contract by this time + //InterfaceContract targetContract = getLeafInterfaceContract(endpoint); + + if (sourceContract == null && targetContract != null) { + // TODO: until the web component introspection is brought up + try { + sourceContract = (InterfaceContract)targetContract.clone(); + } catch (CloneNotSupportedException e) { + throw new IllegalStateException(e); + } + } + + validateReferenceInterfaceCompatibility(); + + List<InvocationChain> chainList = new ArrayList<InvocationChain>(); + if(sourceContract != null && targetContract != null) { + RuntimeComponentReference reference = (RuntimeComponentReference)getReference(); + for (Operation operation : sourceContract.getInterface().getOperations()) { + Operation targetOperation = interfaceContractMapper.map(targetContract.getInterface(), operation); + if (targetOperation == null) { + throw new ServiceRuntimeException("No matching operation for " + operation.getName() + + " is found in reference " + + getComponent().getURI() + + "#" + + reference.getName()); + } + InvocationChain chain = new InvocationChainImpl(operation, targetOperation, true, phaseManager); + if (operation.isNonBlocking()) { + addNonBlockingInterceptor(chain); + } + chainList.add(chain); + addReferenceBindingInterceptor(chain, operation); + } + } + + // Set the chains until it's fully populated. If we initialize too early, any exeception could + // leave this endpoint reference in a wrong state with an empty chain. + chains = chainList; + wireProcessor.process(this); + } + + /** + * Check that endpoint reference has compatible interface at the component and binding ends. + * The user can specify the interfaces at both ends so there is a danger that they won't be compatible. + * There is checking in the activator but of course endpoint references may not have a binding assigned + * until final resolution. + */ + public void validateReferenceInterfaceCompatibility() { + + InterfaceContract referenceContract = getComponentReferenceInterfaceContract(); + InterfaceContract bindingContract = getBindingInterfaceContract(); + + if ((referenceContract != null) && + (bindingContract != null)){ + + boolean bindingHasCallback = bindingContract.getCallbackInterface() != null; + + try { + + if ((referenceContract.getClass() != bindingContract.getClass()) && + (referenceContract instanceof JavaInterfaceContract)) { + interfaceContractMapper.checkCompatibility(getGeneratedWSDLContract(referenceContract), + bindingContract, + Compatibility.SUBSET, + !bindingHasCallback, // ignore callbacks if binding doesn't have one + false); + } else { + interfaceContractMapper.checkCompatibility(referenceContract, + bindingContract, + Compatibility.SUBSET, + !bindingHasCallback, // ignore callbacks if binding doesn't have one + false); + } + + } catch (Exception ex){ + throw new ServiceRuntimeException("Component " + + this.getComponent().getName() + + " Reference " + + getReference().getName() + + " interface is incompatible with the interface of the reference binding " + + getBinding().getName() + + " - " + + ex.getMessage() + + " - [" + this.toString() + "]"); + } + } + } + + /** + * This code used to be in the activator but has moved here as + * the endpoint reference may not now be resolved until the wire + * is first used + */ + private void resolveEndpointReference() { + resolve(); + + eprBinder.bindRunTime(endpointRegistry, this); + + // start the binding provider + final ReferenceBindingProvider bindingProvider = getBindingProvider(); + + if (bindingProvider != null) { + // Allow bindings to add shutdown hooks. Requires RuntimePermission shutdownHooks in policy. + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + bindingProvider.start(); + return null; + } + }); + } + for (PolicyProvider policyProvider : getPolicyProviders()) { + policyProvider.start(); + } + + started = true; + // InterfaceContract bindingContract = getBindingInterfaceContract(); + // endpoint.setInterfaceContract(bindingContract); + } + + private void initReferenceBindingInvocationChains() { + + // add the binding interceptors to the reference binding wire + ReferenceBindingProvider provider = getBindingProvider(); + if ((provider != null) && (provider instanceof EndpointReferenceProvider)) { + ((EndpointReferenceProvider)provider).configure(); + } + + // add the policy interceptors to the service binding wire + // find out which policies are active + for (PolicyProvider p : getPolicyProviders()) { + Interceptor interceptor = p.createBindingInterceptor(); + if (interceptor != null) { + bindingInvocationChain.addInterceptor(interceptor); + } + } + } + + public void rebuild() { + // TODO - can we use the idea of setTarget to rebuild the wire? + // used at the moment by binding.sca when it resets the + // source interface contract for local wires + this.chains = null; + + if (getStatus() == EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED){ + setStatus(EndpointReference.Status.NOT_CONFIGURED); + } + + // TODO - cheating here as I fixed the RuntimeComponentService code + // to call this when it resets the interface contract + //endpointReference.setInterfaceContract(epr.getInterfaceContract()); + } + + /** + * Add the interceptor for a reference binding + * + * @param reference + * @param binding + * @param chain + * @param operation + */ + private void addReferenceBindingInterceptor(InvocationChain chain, Operation operation) { + ReferenceBindingProvider provider = getBindingProvider(); + if (provider != null) { + Invoker invoker = provider.createInvoker(operation); + if (invoker != null) { + chain.addInvoker(invoker); + } + } + List<PolicyProvider> pps = getPolicyProviders(); + if (pps != null) { + for (PolicyProvider p : pps) { + Interceptor interceptor = p.createBindingInterceptor(); + if (interceptor != null) { + chain.addInterceptor(interceptor); + } + } + } + } + + /** + * Add a non-blocking interceptor if the reference binding needs it + * + * @param reference + * @param binding + * @param chain + */ + private void addNonBlockingInterceptor(InvocationChain chain) { + ReferenceBindingProvider provider = getBindingProvider(); + if (provider != null) { + boolean supportsOneWayInvocation = provider.supportsOneWayInvocation(); + if (!supportsOneWayInvocation) { + chain.addInterceptor(Phase.REFERENCE, new NonBlockingInterceptor(workScheduler)); + } + } + } + + /** + * @see java.lang.Object#clone() + */ + @Override + public Object clone() throws CloneNotSupportedException { + RuntimeEndpointReferenceImpl copy = (RuntimeEndpointReferenceImpl)super.clone(); + copy.invoker = new RuntimeInvoker(copy.messageFactory, copy); + return copy; + } + + public boolean isOutOfDate() { + resolve(); + return eprBinder.isOutOfDate(endpointRegistry, this); + } + + public synchronized ReferenceBindingProvider getBindingProvider() { + resolve(); + // For the case that binding.sca is implemented by another binding + if (binding == null) { + return null; + } + if (bindingProvider == null) { + BindingProviderFactory factory = + (BindingProviderFactory)providerFactories.getProviderFactory(getBinding().getClass()); + if (factory == null) { + throw new ServiceRuntimeException("No provider factory is registered for binding " + getBinding() + .getType()); + } + this.bindingProvider = factory.createReferenceBindingProvider(this); + } + return bindingProvider; + } + + public void setBindingProvider(ReferenceBindingProvider bindingProvider) { + this.bindingProvider = bindingProvider; + } + + public synchronized List<PolicyProvider> getPolicyProviders() { + resolve(); + if (policyProviders == null) { + policyProviders = new ArrayList<PolicyProvider>(); + for (PolicyProviderFactory factory : providerFactories.getPolicyProviderFactories()) { + PolicyProvider provider = factory.createReferencePolicyProvider(this); + if (provider != null) { + policyProviders.add(provider); + } + } + } + return policyProviders; + } + + public void unbind() { + bindingInvocationChain = null; + chains = null; + bindingProvider = null; + policyProviders = null; + invocationChainMap.clear(); + } + + public Contract getContract() { + return getReference(); + } + + public CompositeContext getCompositeContext() { + return compositeContext; + } + + public InterfaceContract getBindingInterfaceContract() { + resolve(); + if (bindingInterfaceContract != null) { + return bindingInterfaceContract; + } + bindingInterfaceContract = getBindingProvider().getBindingInterfaceContract(); + if (bindingInterfaceContract == null) { + bindingInterfaceContract = getComponentReferenceInterfaceContract(); + } + if (bindingInterfaceContract == null) { + bindingInterfaceContract = getComponentTypeReferenceInterfaceContract(); + } + return bindingInterfaceContract; + } + + public InterfaceContract getComponentTypeReferenceInterfaceContract() { + resolve(); + if (referenceInterfaceContract != null) { + return referenceInterfaceContract; + } + if (reference == null) { + return getComponentReferenceInterfaceContract(); + } + referenceInterfaceContract = getLeafContract(reference).getInterfaceContract(); + if (referenceInterfaceContract == null) { + referenceInterfaceContract = getComponentReferenceInterfaceContract(); + } + return referenceInterfaceContract; + } + + @Override + protected synchronized void resolve() { + if (xml != null && component == null) { + if (compositeContext == null) { + compositeContext = CompositeContext.getCurrentCompositeContext(); + if (compositeContext != null) { + bind(compositeContext); + } + } + RuntimeEndpointReferenceImpl epr = (RuntimeEndpointReferenceImpl)serializer.readEndpointReference(xml); + copyFrom(epr); + } + super.resolve(); + } + + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + this.uri = in.readUTF(); + this.xml = in.readUTF(); + } + + public void writeExternal(ObjectOutput out) throws IOException { + out.writeUTF(getURI()); + if (serializer == null && xml != null) { + out.writeUTF(xml); + } else { + if (serializer != null) { + out.writeUTF(serializer.write(this)); + } else { + throw new IllegalStateException("No serializer is configured"); + } + } + } + + public boolean isStarted() { + return started; + } + + public InterfaceContract getGeneratedWSDLContract(InterfaceContract interfaceContract) { + + if ( interfaceContract.getNormalizedWSDLContract() == null){ + if (getComponentReferenceInterfaceContract() instanceof JavaInterfaceContract){ + if (contractBuilder == null){ + throw new ServiceRuntimeException("Contract builder not found while calculating WSDL contract for " + this.toString()); + } + contractBuilder.build(getComponentReferenceInterfaceContract(), null); + } + } + + return interfaceContract.getNormalizedWSDLContract(); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultComponentContextFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultComponentContextFactory.java new file mode 100644 index 0000000000..2de52bebb2 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultComponentContextFactory.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.context; + +import org.apache.tuscany.sca.context.ComponentContextFactory; +import org.apache.tuscany.sca.context.CompositeContext; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.context.impl.ComponentContextImpl; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.oasisopen.sca.ComponentContext; + +/** + * @version $Rev$ $Date$ + */ +public class DefaultComponentContextFactory implements ComponentContextFactory { + private final ExtensionPointRegistry registry; + + public DefaultComponentContextFactory(ExtensionPointRegistry registry) { + this.registry = registry; + } + + public ComponentContext createComponentContext(CompositeContext compositeContext, RuntimeComponent component) { + return new ComponentContextImpl(registry, compositeContext, component); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultRequestContextFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultRequestContextFactory.java new file mode 100644 index 0000000000..ace4dc48e1 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/DefaultRequestContextFactory.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.context; + +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.context.impl.RequestContextImpl; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.oasisopen.sca.RequestContext; + +/** + * Default implementation of RequestContextFactory + */ +public class DefaultRequestContextFactory implements RequestContextFactory { + + public DefaultRequestContextFactory(ExtensionPointRegistry registry) { + } + + public RequestContext createRequestContext(RuntimeComponent component) { + return new RequestContextImpl(component); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/ServiceReferenceExt.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/ServiceReferenceExt.java new file mode 100644 index 0000000000..5206f0945e --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/ServiceReferenceExt.java @@ -0,0 +1,41 @@ +/* + * 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.core.context; + +import java.io.Externalizable; + +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; +import org.oasisopen.sca.ServiceReference; + +/** + * Extended ServiceReference + */ +public interface ServiceReferenceExt<B> extends ServiceReference<B>, Externalizable { + + /** + * Return the EndpointReference that sits behind this service reference + * @return endpoint reference + */ + RuntimeEndpointReference getEndpointReference(); + + B getProxy(); + void setProxy(B proxy); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/CallbackServiceReferenceImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/CallbackServiceReferenceImpl.java new file mode 100644 index 0000000000..542a80f926 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/CallbackServiceReferenceImpl.java @@ -0,0 +1,124 @@ +/* + * 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.core.context.impl; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.context.CompositeContext; +import org.apache.tuscany.sca.context.ThreadMessageContext; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; +import org.oasisopen.sca.ServiceRuntimeException; + +public class CallbackServiceReferenceImpl<B> extends ServiceReferenceImpl<B> { + private RuntimeEndpointReference callbackEPR; + private List<? extends EndpointReference> callbackEPRs; + private Endpoint resolvedEndpoint; + + /* + * Public constructor for Externalizable serialization/deserialization + */ + public CallbackServiceReferenceImpl() { + super(); + } + + public CallbackServiceReferenceImpl(Class<B> interfaze, + List<? extends EndpointReference> callbackEPRs) { + super(interfaze, null, getCompositeContext(callbackEPRs)); + this.callbackEPRs = callbackEPRs; + init(); + } + + private static CompositeContext getCompositeContext(List<? extends EndpointReference> callbackEPRs) { + if(!callbackEPRs.isEmpty()) { + RuntimeEndpointReference epr = (RuntimeEndpointReference) callbackEPRs.get(0); + return epr.getCompositeContext(); + } + return null; + } + + public void init() { + Message msgContext = ThreadMessageContext.getMessageContext(); + callbackEPR = selectCallbackEPR(msgContext); + if (callbackEPR == null) { + throw new ServiceRuntimeException("No callback binding found for " + msgContext.getTo().toString()); + } + resolvedEndpoint = msgContext.getFrom().getCallbackEndpoint(); + } + + @Override + protected B createProxy() throws Exception { + return proxyFactory.createCallbackProxy(this); + } + + public RuntimeEndpointReference getCallbackEPR() { + if (resolvedEndpoint == null) { + return null; + } else { + return cloneAndBind(callbackEPR); + } + } + + public Endpoint getResolvedEndpoint() { + return resolvedEndpoint; + } + + private RuntimeEndpointReference selectCallbackEPR(Message msgContext) { + // look for callback binding with same name as service binding + Endpoint to = msgContext.getTo(); + if (to == null) { + //FIXME: need better exception + throw new ServiceRuntimeException("Destination for forward call is not available"); + } + for (EndpointReference epr : callbackEPRs) { + if (epr.getBinding().getName().equals(to.getBinding().getName())) { + return (RuntimeEndpointReference) epr; + } + } + + // if no match, look for callback binding with same type as service binding + for (EndpointReference epr : callbackEPRs) { + if (epr.getBinding().getType().equals(to.getBinding().getType())) { + return (RuntimeEndpointReference) epr; + } + } + + // no suitable callback wire was found + return null; + } + + private RuntimeEndpointReference cloneAndBind(RuntimeEndpointReference endpointReference) { + if (resolvedEndpoint != null) { + + try { + RuntimeEndpointReference epr = (RuntimeEndpointReference)endpointReference.clone(); + epr.setTargetEndpoint(resolvedEndpoint); + return epr; + } catch (CloneNotSupportedException e) { + // will not happen + throw new ServiceRuntimeException(e); + } + } else { + return null; + } + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ComponentContextImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ComponentContextImpl.java new file mode 100644 index 0000000000..999854a822 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ComponentContextImpl.java @@ -0,0 +1,494 @@ +/* + * 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.core.context.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.Component; +import org.apache.tuscany.sca.assembly.ComponentProperty; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.assembly.SCABinding; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.context.CompositeContext; +import org.apache.tuscany.sca.context.ContextFactoryExtensionPoint; +import org.apache.tuscany.sca.context.PropertyValueFactory; +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.runtime.CompositeActivator; +import org.apache.tuscany.sca.runtime.EndpointReferenceBinder; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentContext; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; +import org.oasisopen.sca.RequestContext; +import org.oasisopen.sca.ServiceReference; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * Implementation of ComponentContext that delegates to a ComponentContextProvider. + * + * @version $Rev$ $Date$ + */ +public class ComponentContextImpl implements RuntimeComponentContext { + private final RuntimeComponent component; + + private final CompositeContext compositeContext; + private final CompositeActivator compositeActivator; + private final RequestContextFactory requestContextFactory; + private final ProxyFactory proxyFactory; + private final AssemblyFactory assemblyFactory; + private final JavaInterfaceFactory javaInterfaceFactory; + private final PropertyValueFactory propertyFactory; + private final EndpointReferenceBinder eprBinder; + + public ComponentContextImpl(ExtensionPointRegistry registry, + CompositeContext compositeContext, + RuntimeComponent component) { + this.component = component; + FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class); + this.assemblyFactory = factories.getFactory(AssemblyFactory.class); + this.javaInterfaceFactory = factories.getFactory(JavaInterfaceFactory.class); + + UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class); + this.compositeContext = compositeContext; + + this.compositeActivator = utilities.getUtility(CompositeActivator.class); + + this.requestContextFactory = + registry.getExtensionPoint(ContextFactoryExtensionPoint.class).getFactory(RequestContextFactory.class); + this.proxyFactory = ExtensibleProxyFactory.getInstance(registry); + this.propertyFactory = factories.getFactory(PropertyValueFactory.class); + + this.eprBinder = utilities.getUtility(EndpointReferenceBinder.class); + + } + + public String getURI() { + return component.getURI(); + } + + public <B> ServiceReference<B> cast(B target) throws IllegalArgumentException { + return proxyFactory.cast(target); + } + + public <B> B getService(Class<B> businessInterface, String referenceName) { + ServiceReference<B> serviceRef = getServiceReference(businessInterface, referenceName); + return serviceRef.getService(); + } + + public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, String referenceName) { + + for (ComponentReference ref : component.getReferences()) { + if (referenceName.equals(ref.getName())) { + Multiplicity multiplicity = ref.getMultiplicity(); + if (multiplicity == Multiplicity.ZERO_N || multiplicity == Multiplicity.ONE_N) { + throw new IllegalArgumentException("Reference " + referenceName + + " has multiplicity " + + multiplicity); + } + return getServiceReference(businessInterface, (RuntimeEndpointReference)getEndpointReference(ref)); + } + } + throw new ServiceRuntimeException("Reference not found: " + referenceName); + + } + + /** + * Select an endpoint reference from the component reference + * @param ref + * @return + */ + private EndpointReference getEndpointReference(ComponentReference ref) { + List<EndpointReference> eprs = ref.getEndpointReferences(); + if (eprs.size() == 1) { + // Return 1st one + return eprs.get(0); + } else { + for (EndpointReference epr : eprs) { + // Try to see if there is an EPR using binding.sca + if (epr.getBinding().getType().equals(SCABinding.TYPE)) { + return epr; + } + } + return eprs.get(0); + } + } + + /** + * Select an endpoint reference from the component reference + * @param ref + * @return + */ + private Endpoint getEndpoint(ComponentService service, String bindingName) { + if (bindingName == null) { + // The default binding name is the name of the promoted service + bindingName = getPromotedService(service).getName(); + } + Endpoint returnEp = null; + List<Endpoint> eps = service.getEndpoints(); + for (Endpoint ep : eps) { + Binding binding = ep.getBinding(); + if (bindingName.equals(binding.getName()) || binding.getName() == null) { + returnEp = ep; + break; + } + } + //TUSCANY-3543 + if(returnEp == null) { + returnEp = eps.get(0); + } + + return returnEp; + } + + private ComponentService getPromotedService(ComponentService componentService) { + Service service = componentService.getService(); + if (service instanceof CompositeService) { + return getPromotedService(((CompositeService)service).getPromotedService()); + } else { + return componentService; + } + + } + + /** + * Gets the value for the specified property with the specified type. + * + * @param type The type of the property value we are getting + * @param propertyName The name of the property we are getting + * @param B The class of the property value we are getting + * + * @throws ServiceRuntimeException If a Property for the specified propertyName + * is not found + * + * @see #setPropertyValueFactory(PropertyValueFactory) + */ + public <B> B getProperty(Class<B> type, String propertyName) { + for (ComponentProperty p : component.getProperties()) { + if (propertyName.equals(p.getName())) { + return propertyFactory.createPropertyValue(p, type); + } + } + throw new ServiceRuntimeException("Property not found: " + propertyName); + } + + /** + * @param component + */ + public static ComponentService getSingleService(Component component) { + ComponentService targetService; + List<ComponentService> services = component.getServices(); + List<ComponentService> regularServices = new ArrayList<ComponentService>(); + for (ComponentService service : services) { + if (service.isForCallback()) { + continue; + } + String name = service.getName(); + if (!name.startsWith("$") || name.startsWith("$dynamic$")) { + regularServices.add(service); + } + } + if (regularServices.size() == 0) { + throw new ServiceRuntimeException("No service is declared on component " + component.getURI()); + } + if (regularServices.size() != 1) { + throw new ServiceRuntimeException("More than one service is declared on component " + component.getURI() + + ". Service name is required to get the service."); + } + targetService = regularServices.get(0); + return targetService; + } + + public <B> ServiceReference<B> createSelfReference(Class<B> businessInterface) { + ComponentService service = getSingleService(component); + try { + return createSelfReference(businessInterface, service); + } catch (Exception e) { + throw new ServiceRuntimeException(e.getMessage(), e); + } + } + + public <B> ServiceReference<B> createSelfReference(Class<B> businessInterface, String serviceName) { + if (serviceName == null) { + return createSelfReference(businessInterface); + } + try { + String bindingName = null; + int index = serviceName.indexOf('/'); + if (index != -1) { + bindingName = serviceName.substring(index + 1); + serviceName = serviceName.substring(0, index); + } + for (ComponentService service : component.getServices()) { + if (serviceName.equals(service.getName())) { + Endpoint endpoint = getEndpoint(service, bindingName); + if (endpoint == null) { + break; + } + return getServiceReference(businessInterface, (RuntimeEndpoint)endpoint); + } + } + throw new ServiceRuntimeException("Service not found: " + serviceName); + } catch (ServiceRuntimeException e) { + throw e; + } catch (Exception e) { + throw new ServiceRuntimeException(e.getMessage(), e); + } + } + + /** + * @param <B> + * @param businessInterface + * @param service + * @return + */ + public <B> ServiceReference<B> createSelfReference(Class<B> businessInterface, ComponentService service) { + try { + RuntimeEndpointReference ref = + (RuntimeEndpointReference)createEndpointReference(component, service, null, businessInterface); + ref.setComponent(component); + return getServiceReference(businessInterface, ref); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public RequestContext getRequestContext() { + if (requestContextFactory != null) { + return requestContextFactory.createRequestContext(component); + } else { + return new RequestContextImpl(component); + } + } + + /** + * @param businessInterface + * @param reference + * @return + * @throws CloneNotSupportedException + * @throws InvalidInterfaceException + */ + public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, + RuntimeEndpointReference endpointReference) { + try { + InterfaceContract interfaceContract = endpointReference.getComponentTypeReferenceInterfaceContract(); + if (businessInterface == null) { + businessInterface = (Class<B>)((JavaInterface)interfaceContract.getInterface()).getJavaClass(); + } + RuntimeComponentReference ref = (RuntimeComponentReference)endpointReference.getReference(); + InterfaceContract refInterfaceContract = getInterfaceContract(interfaceContract, businessInterface); + if (refInterfaceContract != interfaceContract) { + ref = (RuntimeComponentReference)ref.clone(); + if (interfaceContract != null) { + ref.setInterfaceContract(interfaceContract); + } else { + ref.setInterfaceContract(refInterfaceContract); + } + } + ref.setComponent(component); + return new ServiceReferenceImpl<B>(businessInterface, endpointReference, component.getComponentContext() + .getCompositeContext()); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public <B> ServiceReference<B> getServiceReference(Class<B> businessInterface, RuntimeEndpoint endpoint) { + try { + if (businessInterface == null) { + InterfaceContract contract = endpoint.getComponentTypeServiceInterfaceContract(); + businessInterface = (Class<B>)((JavaInterface)contract.getInterface()).getJavaClass(); + } + RuntimeEndpointReference ref = + (RuntimeEndpointReference)createEndpointReference(endpoint, businessInterface); + ref.setComponent(component); + return new ServiceReferenceImpl<B>(businessInterface, ref, compositeContext); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + /** + * Create a self-reference for a component service + * @param component + * @param service + * @throws CloneNotSupportedException + * @throws InvalidInterfaceException + */ + private EndpointReference createEndpointReference(Component component, + ComponentService service, + String bindingName, + Class<?> businessInterface) throws CloneNotSupportedException, + InvalidInterfaceException { + + Endpoint endpoint = getEndpoint(service, bindingName); + return createEndpointReference(endpoint, businessInterface); + } + + private EndpointReference createEndpointReference(Endpoint endpoint, Class<?> businessInterface) + throws CloneNotSupportedException, InvalidInterfaceException { + Component component = endpoint.getComponent(); + ComponentService service = endpoint.getService(); + ComponentReference componentReference = assemblyFactory.createComponentReference(); + componentReference.setName("$self$." + service.getName()); + + componentReference.setCallback(service.getCallback()); + componentReference.getTargets().add(service); + componentReference.getPolicySets().addAll(service.getPolicySets()); + componentReference.getRequiredIntents().addAll(service.getRequiredIntents()); + componentReference.getBindings().add(endpoint.getBinding()); + + InterfaceContract interfaceContract = service.getInterfaceContract(); + Service componentTypeService = service.getService(); + if (componentTypeService != null && componentTypeService.getInterfaceContract() != null) { + interfaceContract = componentTypeService.getInterfaceContract(); + } + interfaceContract = getInterfaceContract(interfaceContract, businessInterface); + componentReference.setInterfaceContract(interfaceContract); + componentReference.setMultiplicity(Multiplicity.ONE_ONE); + // component.getReferences().add(componentReference); + + // create endpoint reference + EndpointReference endpointReference = assemblyFactory.createEndpointReference(); + endpointReference.setComponent(component); + endpointReference.setReference(componentReference); + endpointReference.setBinding(endpoint.getBinding()); + endpointReference.setUnresolved(false); + endpointReference.setStatus(EndpointReference.Status.WIRED_TARGET_FOUND_READY_FOR_MATCHING); + + endpointReference.setTargetEndpoint(endpoint); + + componentReference.getEndpointReferences().add(endpointReference); + ((RuntimeComponentReference)componentReference).setComponent((RuntimeComponent)component); + ((RuntimeEndpointReference)endpointReference).bind(compositeContext); + + return endpointReference; + } + + /** + * @param interfaceContract + * @param businessInterface + * @return + * @throws CloneNotSupportedException + * @throws InvalidInterfaceException + */ + private InterfaceContract getInterfaceContract(InterfaceContract interfaceContract, Class<?> businessInterface) + throws CloneNotSupportedException, InvalidInterfaceException { + if (businessInterface == null) { + return interfaceContract; + } + boolean compatible = false; + if (interfaceContract != null && interfaceContract.getInterface() != null) { + Interface interfaze = interfaceContract.getInterface(); + if (interfaze instanceof JavaInterface) { + Class<?> cls = ((JavaInterface)interfaze).getJavaClass(); + if (businessInterface.isAssignableFrom(cls)) { + compatible = true; + } + } + } + + if (!compatible) { + // The interface is not assignable from the interface contract + interfaceContract = javaInterfaceFactory.createJavaInterfaceContract(); + JavaInterface callInterface = javaInterfaceFactory.createJavaInterface(businessInterface); + interfaceContract.setInterface(callInterface); + if (callInterface.getCallbackClass() != null) { + interfaceContract.setCallbackInterface(javaInterfaceFactory.createJavaInterface(callInterface + .getCallbackClass())); + } + } + + return interfaceContract; + } + + /** + * @see org.apache.tuscany.sca.runtime.RuntimeComponentContext#start(org.apache.tuscany.sca.runtime.RuntimeComponentReference) + */ + public void start(RuntimeComponentReference reference) { + compositeActivator.start(compositeContext, component, reference); + } + + /* ******************** Contribution for issue TUSCANY-2281 ******************** */ + + /** + * @see ComponentContext#getServices(Class<B>, String) + */ + public <B> Collection<B> getServices(Class<B> businessInterface, String referenceName) { + ArrayList<B> services = new ArrayList<B>(); + Collection<ServiceReference<B>> serviceRefs = getServiceReferences(businessInterface, referenceName); + for (ServiceReference<B> serviceRef : serviceRefs) { + services.add(serviceRef.getService()); + } + return services; + } + + /** + * @see ComponentContext#getServiceReferences(Class<B>, String) + */ + public <B> Collection<ServiceReference<B>> getServiceReferences(Class<B> businessInterface, String referenceName) { + try { + for (ComponentReference ref : component.getReferences()) { + if (referenceName.equals(ref.getName())) { + ArrayList<ServiceReference<B>> serviceRefs = new ArrayList<ServiceReference<B>>(); + for (EndpointReference endpointReference : ref.getEndpointReferences()) { + RuntimeEndpointReference epr = (RuntimeEndpointReference)endpointReference; + serviceRefs.add(getServiceReference(businessInterface, epr)); + } + return serviceRefs; + } + } + throw new ServiceRuntimeException("Reference not found: " + referenceName); + } catch (ServiceRuntimeException e) { + throw e; + } catch (Exception e) { + throw new ServiceRuntimeException(e.getMessage(), e); + } + } + + /* ******************** Contribution for issue TUSCANY-2281 ******************** */ + + public CompositeContext getCompositeContext() { + return compositeContext; + } + + public ExtensionPointRegistry getExtensionPointRegistry() { + return getCompositeContext().getExtensionPointRegistry(); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/RequestContextImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/RequestContextImpl.java new file mode 100644 index 0000000000..5d0527682e --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/RequestContextImpl.java @@ -0,0 +1,123 @@ +/* + * 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.core.context.impl; + +import java.util.List; + +import javax.security.auth.Subject; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.context.ThreadMessageContext; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.oasisopen.sca.RequestContext; +import org.oasisopen.sca.ServiceReference; + +/** + * @version $Rev$ $Date$ + */ +public class RequestContextImpl implements RequestContext { + + public RequestContextImpl(RuntimeComponent component) { + } + + public Subject getSecuritySubject() { + + Message msgContext = ThreadMessageContext.getMessageContext(); + + if (msgContext == null){ + // message in thread context could be null if the user has + // spun up a new thread inside their component implementation + return null; + } + + Subject subject = null; + for (Object header : msgContext.getHeaders().values()){ + if (header instanceof Subject){ + subject = (Subject)header; + break; + } + } + return subject; + } + + public String getServiceName() { + Message msgContext = ThreadMessageContext.getMessageContext(); + + if (msgContext != null){ + return msgContext.getTo().getService().getName(); + } else { + // message in thread context could be null if the user has + // spun up a new thread inside their component implementation + return null; + } + } + + public <B> ServiceReference<B> getServiceReference() { + Message msgContext = ThreadMessageContext.getMessageContext(); + if (msgContext == null){ + // message in thread context could be null if the user has + // spun up a new thread inside their component implementation + return null; + } + // FIXME: [rfeng] Is this the service reference matching the caller side? + RuntimeEndpoint to = (RuntimeEndpoint) msgContext.getTo(); + RuntimeComponent component = (RuntimeComponent) to.getComponent(); + + ServiceReference<B> callableReference = component.getComponentContext().getServiceReference(null, to); + + return callableReference; + } + + public <CB> CB getCallback() { + ServiceReference<CB> cb = getCallbackReference(); + if (cb == null) { + return null; + } + return cb.getService(); + } + + @SuppressWarnings("unchecked") + public <CB> ServiceReference<CB> getCallbackReference() { + Message msgContext = ThreadMessageContext.getMessageContext(); + if (msgContext == null){ + // message in thread context could be null if the user has + // spun up a new thread inside their component implementation + return null; + } + + Endpoint to = msgContext.getTo(); + RuntimeComponentService service = (RuntimeComponentService) to.getService(); + RuntimeComponentReference callbackReference = (RuntimeComponentReference)service.getCallbackReference(); + if (callbackReference == null) { + return null; + } + JavaInterface javaInterface = (JavaInterface) callbackReference.getInterfaceContract().getInterface(); + Class<CB> javaClass = (Class<CB>)javaInterface.getJavaClass(); + List<EndpointReference> wires = callbackReference.getEndpointReferences(); + ServiceReferenceImpl ref = new CallbackServiceReferenceImpl(javaClass, wires); + + return ref; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ServiceReferenceImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ServiceReferenceImpl.java new file mode 100644 index 0000000000..0cda879011 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/context/impl/ServiceReferenceImpl.java @@ -0,0 +1,424 @@ +/* + * 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.core.context.impl; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.StringWriter; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.CompositeService; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.assembly.builder.BindingBuilder; +import org.apache.tuscany.sca.assembly.builder.BuilderContext; +import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint; +import org.apache.tuscany.sca.context.CompositeContext; +import org.apache.tuscany.sca.contribution.processor.ContributionWriteException; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.assembly.RuntimeAssemblyFactory; +import org.apache.tuscany.sca.core.context.ServiceReferenceExt; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.runtime.Invocable; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * Default implementation of a ServiceReference. + * + * @version $Rev$ $Date$ + * @param <B> the type of the business interface + */ +public class ServiceReferenceImpl<B> implements ServiceReferenceExt<B> { + private static final long serialVersionUID = 6763709434194361540L; + + protected transient ProxyFactory proxyFactory; + protected transient Class<B> businessInterface; + protected transient B proxy; + + protected Object callbackID; // The callbackID should be serializable + + protected transient RuntimeEndpointReference endpointReference; + +// protected String scdl; +// +// private transient XMLStreamReader xmlReader; + + protected transient CompositeContext compositeContext; + protected ExtensionPointRegistry registry; + protected FactoryExtensionPoint modelFactories; + protected RuntimeAssemblyFactory assemblyFactory; + protected StAXArtifactProcessorExtensionPoint staxProcessors; + protected StAXArtifactProcessor<EndpointReference> staxProcessor; + protected XMLInputFactory xmlInputFactory; + protected XMLOutputFactory xmlOutputFactory; + protected BuilderExtensionPoint builders; + + /* + * Public constructor for Externalizable serialization/deserialization + */ + public ServiceReferenceImpl() { + super(); + } + + public ServiceReferenceImpl(Class<B> businessInterface, + Invocable endpointReference, + CompositeContext compositeContext) { + this.businessInterface = businessInterface; + this.endpointReference = (RuntimeEndpointReference) endpointReference; + if (compositeContext == null) { + compositeContext = endpointReference.getCompositeContext(); + } + bind(compositeContext); + } + + public ServiceReferenceImpl(Class<B> businessInterface, + Invocable endpointReference) { + this(businessInterface, endpointReference, null); + } + + protected void bind(CompositeContext context) { + this.compositeContext = context; + this.registry = compositeContext.getExtensionPointRegistry(); + this.modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class); + this.assemblyFactory = (RuntimeAssemblyFactory)modelFactories.getFactory(AssemblyFactory.class); + this.xmlInputFactory = modelFactories.getFactory(XMLInputFactory.class); + this.xmlOutputFactory = modelFactories.getFactory(XMLOutputFactory.class); + this.staxProcessors = registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + this.staxProcessor = staxProcessors.getProcessor(EndpointReference.class); + this.builders = registry.getExtensionPoint(BuilderExtensionPoint.class); + this.proxyFactory = ExtensibleProxyFactory.getInstance(registry); + } + + public RuntimeEndpointReference getEndpointReference() { + return endpointReference; + } + + public B getProxy() throws ObjectCreationException { + try { + if (proxy == null) { + proxy = createProxy(); + } + return proxy; + } catch (Exception e) { + throw new ObjectCreationException(e); + } + } + + public void setProxy(B proxy) { + this.proxy = proxy; + } + + protected B createProxy() throws Exception { + return proxyFactory.createProxy(this); + } + + public B getService() { + try { + resolve(); + return getProxy(); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + public Class<B> getBusinessInterface() { + try { + resolve(); + return businessInterface; + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + } + + /** + * Follow a service promotion chain down to the inner most (non composite) + * component service. + * + * @param topCompositeService + * @return + */ + private ComponentService getPromotedComponentService(CompositeService compositeService) { + ComponentService componentService = compositeService.getPromotedService(); + if (componentService != null) { + Service service = componentService.getService(); + if (componentService.getName() != null && service instanceof CompositeService) { + + // Continue to follow the service promotion chain + return getPromotedComponentService((CompositeService)service); + + } else { + + // Found a non-composite service + return componentService; + } + } else { + + // No promoted service + return null; + } + } + + // ============ WRITE AND READ THE REFERENCE TO EXTERNAL XML ======================== + + /** + * write the reference to a stream + * + * @see java.io.Externalizable#writeExternal(java.io.ObjectOutput) + */ + public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(endpointReference); + /* + try { + String xml = null; + if (scdl == null) { + xml = toXMLString(); + } else { + xml = scdl; + } + + if (xml == null) { + out.writeBoolean(false); + } else { + out.writeBoolean(true); + out.writeUTF(xml); + } + } catch (Exception e) { + // e.printStackTrace(); + throw new IOException(e.toString()); + } + */ + } + + /** + * write the endpoint reference into an xml string + */ + public String toXMLString() throws IOException, XMLStreamException, ContributionWriteException { + StringWriter writer = new StringWriter(); + XMLStreamWriter streamWriter = xmlOutputFactory.createXMLStreamWriter(writer); + staxProcessor.write(endpointReference, streamWriter, new ProcessorContext(registry)); + return writer.toString(); + } + + /** + * Read the reference from a stream + * + * @see java.io.Externalizable#readExternal(java.io.ObjectInput) + */ + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + this.endpointReference = (RuntimeEndpointReference) in.readObject(); + // Force resolve + endpointReference.getComponent(); + bind(endpointReference.getCompositeContext()); + + RuntimeComponentReference reference = (RuntimeComponentReference)endpointReference.getReference(); + reference.setComponent((RuntimeComponent)endpointReference.getComponent()); + + Interface i = reference.getInterfaceContract().getInterface(); + if (i instanceof JavaInterface) { + JavaInterface javaInterface = (JavaInterface)i; + if (javaInterface.isUnresolved()) { + // Allow privileged access to get ClassLoader. Requires RuntimePermission in + // security policy. + ClassLoader classLoader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { + public ClassLoader run() { + return Thread.currentThread().getContextClassLoader(); + } + }); + + javaInterface.setJavaClass(classLoader.loadClass(javaInterface.getName())); + JavaInterfaceFactory javaInterfaceFactory = getJavaInterfaceFactory(compositeContext); + + try { + javaInterfaceFactory.createJavaInterface(javaInterface, javaInterface.getJavaClass()); + } catch (InvalidInterfaceException e) { + throw new ServiceRuntimeException(e); + } + //FIXME: If the interface needs XSDs to be loaded (e.g., for static SDO), + // this needs to be done here. We usually search for XSDs in the current + // contribution at resolve time. Is it possible to locate the current + // contribution at runtime? + } + this.businessInterface = (Class<B>)javaInterface.getJavaClass(); + } + + Binding binding = endpointReference.getBinding(); + if (binding != null) { + BindingBuilder bindingBuilder = builders.getBindingBuilder(binding.getType()); + if (bindingBuilder != null) { + org.apache.tuscany.sca.assembly.builder.BuilderContext context = new BuilderContext(registry); + bindingBuilder.build(endpointReference.getComponent(), reference, endpointReference.getBinding(), context, false); + } + } + + this.proxyFactory = getProxyFactory(this.compositeContext); + + /* + endpointReference.bind(CompositeContext.getCurrentCompositeContext()); + endpointReference.rebuild(); + */ + /* + final boolean hasSCDL = in.readBoolean(); + if (hasSCDL) { + this.scdl = in.readUTF(); + } else { + this.scdl = null; + } + */ + } + + /** + * Read xml string into the endpoint reference + */ + /* + public void fromXMLString() throws IOException, XMLStreamException, ContributionReadException { + + XMLStreamReader streamReader = xmlReader; + + if (scdl != null) { + Reader reader = new StringReader(scdl); + + if (xmlInputFactory == null) { + // this is a reference being read from a external stream + // so set up enough of the reference in order to resolved the + // xml being read + bind(CompositeContext.getCurrentCompositeContext()); + } + + streamReader = xmlInputFactory.createXMLStreamReader(reader); + } + + endpointReference = (RuntimeEndpointReference) staxProcessor.read(streamReader, new ProcessorContext(registry)); + + // ok to GC + xmlReader = null; + scdl = null; + } + */ + + /** + * @throws IOException + */ + private synchronized void resolve() throws Exception { + /* + if ((scdl != null || xmlReader != null) && endpointReference == null) { + fromXMLString(); + + compositeContext.bindComponent((RuntimeComponent) endpointReference.getComponent()); + + RuntimeComponentReference reference = (RuntimeComponentReference)endpointReference.getReference(); + reference.setComponent((RuntimeComponent)endpointReference.getComponent()); + + ReferenceParameters parameters = null; + for (Object ext : reference.getExtensions()) { + if (ext instanceof ReferenceParameters) { + parameters = (ReferenceParameters)ext; + break; + } + } + + if (parameters != null) { + this.callbackID = parameters.getCallbackID(); + } + + Interface i = reference.getInterfaceContract().getInterface(); + if (i instanceof JavaInterface) { + JavaInterface javaInterface = (JavaInterface)i; + if (javaInterface.isUnresolved()) { + // Allow privileged access to get ClassLoader. Requires RuntimePermission in + // security policy. + ClassLoader classLoader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { + public ClassLoader run() { + return Thread.currentThread().getContextClassLoader(); + } + }); + + javaInterface.setJavaClass(classLoader.loadClass(javaInterface.getName())); + JavaInterfaceFactory javaInterfaceFactory = getJavaInterfaceFactory(compositeContext); + + javaInterfaceFactory.createJavaInterface(javaInterface, javaInterface.getJavaClass()); + //FIXME: If the interface needs XSDs to be loaded (e.g., for static SDO), + // this needs to be done here. We usually search for XSDs in the current + // contribution at resolve time. Is it possible to locate the current + // contribution at runtime? + } + this.businessInterface = (Class<B>)javaInterface.getJavaClass(); + } + + Binding binding = endpointReference.getBinding(); + if (binding != null) { + BindingBuilder bindingBuilder = builders.getBindingBuilder(binding.getType()); + if (bindingBuilder != null) { + BuilderContext context = new BuilderContext(registry); + bindingBuilder.build(endpointReference.getComponent(), reference, endpointReference.getBinding(), context); + } + } + + this.proxyFactory = getProxyFactory(this.compositeContext); + } else if (compositeContext == null) { + this.compositeContext = CompositeContext.getCurrentCompositeContext(); + if (this.compositeContext != null) { + this.proxyFactory = getProxyFactory(this.compositeContext); + } + } + */ + } + + private JavaInterfaceFactory getJavaInterfaceFactory(CompositeContext compositeContext) { + ExtensionPointRegistry extensionPointRegistry = compositeContext.getExtensionPointRegistry(); + FactoryExtensionPoint factories = extensionPointRegistry.getExtensionPoint(FactoryExtensionPoint.class); + JavaInterfaceFactory javaInterfaceFactory = factories.getFactory(JavaInterfaceFactory.class); + return javaInterfaceFactory; + } + + private ProxyFactory getProxyFactory(CompositeContext compositeContext) { + ExtensionPointRegistry extensionPointRegistry = compositeContext.getExtensionPointRegistry(); + return ExtensibleProxyFactory.getInstance(extensionPointRegistry); + } + + // ================================================================================== + + /* + public XMLStreamReader getXMLReader() { + return xmlReader; + } + */ +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/InstanceWrapper.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/InstanceWrapper.java new file mode 100644 index 0000000000..4b563b0079 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/InstanceWrapper.java @@ -0,0 +1,49 @@ +/* + * 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.core.factory; + +import org.apache.tuscany.sca.core.scope.TargetDestructionException; +import org.apache.tuscany.sca.core.scope.TargetInitializationException; + + +/** + * Provides lifecycle management for an implementation instance associated with + * a component for use by the component's associated {@link org.apache.tuscany.sca.core.scope.ScopeContainer} + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface InstanceWrapper<T> { + + /** + * @return + */ + T getInstance(); + + /** + * @throws TargetInitializationException + */ + void start() throws TargetInitializationException; + + /** + * @throws TargetDestructionException + */ + void stop() throws TargetDestructionException; + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectCreationException.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectCreationException.java new file mode 100644 index 0000000000..820faf6259 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectCreationException.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.core.factory; + + +/** + * Denotes an error creating a new object instance + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public class ObjectCreationException extends RuntimeException { + private static final long serialVersionUID = -6423113430265944499L; + + public ObjectCreationException() { + super(); + } + + public ObjectCreationException(String message, Throwable cause) { + super(message, cause); + } + + public ObjectCreationException(String message) { + super(message); + } + + public ObjectCreationException(Throwable cause) { + super(cause); + } + +} + diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectFactory.java new file mode 100644 index 0000000000..db10b6cff2 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/factory/ObjectFactory.java @@ -0,0 +1,36 @@ +/* + * 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.core.factory; + +/** + * Implementations create new instances of a particular type + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface ObjectFactory<T> { + + /** + * Return a instance of the type that this factory creates. + * + * @return a instance from this factory + */ + T getInstance() throws ObjectCreationException; + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncFaultWrapper.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncFaultWrapper.java new file mode 100644 index 0000000000..3d98de9e21 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncFaultWrapper.java @@ -0,0 +1,102 @@ +/* + * 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.core.invocation; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +/** + * A class which is used to wrap an Exception of any type thrown by an asynchronous service operation and + * which is returned through a separate one-way message sent asynchronously from the server to the client. + * + */ +public class AsyncFaultWrapper { + + private String faultClassName = null; + private String faultMessage = null; + private AsyncFaultWrapper containedFault = null; + + + public AsyncFaultWrapper() { + super(); + } + + /** + * Constructor which creates an AsyncFaultWrapper which wraps the supplied Throwable + * @param e - a Throwable which is wrapped by this AsyncFaultWrapper + */ + public AsyncFaultWrapper( Throwable e ) { + super(); + storeFault( e ); + } + + /** + * Stores a given Throwable in this AsyncFaultWrapper + * If the supplied Throwable itself contains an embedded Throwable ("cause"), this is recursively + * wrapped by a nested AsyncFaultWrapper + * @param e - the Throwable + */ + public void storeFault( Throwable e ) { + setFaultClassName( e.getClass().getCanonicalName() ); + setFaultMessage( e.getMessage() ); + Throwable cause = e.getCause(); + if( cause != null ) setContainedFault( new AsyncFaultWrapper( cause ) ); + } + + /** + * Retrieves the Throwable wrapped by this AsyncFaultWrapper + * + * Note: When this method is invoked, the method attempts to instantiate an instance of the wrapped Throwable. + * It does this using the Thread Context Class Loader (TCCL) - the caller *MUST* ensure that the TCCL has access + * to the class of the wrapped Throwable and also to the classes of any nested Throwables. If this is not done, + * a ClassNotFound exception is thrown + * + * @return - the Throwable wrapped by this AsyncFaultWrapper - the Throwable will contain any nested Throwable(s) + * in its cause property + * @throws ClassNotFound exception, if the class of the wrapped Throwable is not accessible from the TCCL + */ + public Throwable retrieveFault( ) { + try { + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + Class<?> faultClass = tccl.loadClass(faultClassName); + Class<Throwable> xclass = (Class<Throwable>) faultClass; + if( containedFault != null ) { + // If there is a nested fault, retrieve this recursively + Constructor cons = xclass.getConstructor(String.class, Throwable.class); + return (Throwable) cons.newInstance(faultMessage, getContainedFault().retrieveFault()); + } else { + Constructor cons = xclass.getConstructor(String.class); + return (Throwable) cons.newInstance(faultMessage); + } // end if + } catch (Exception e) { + return e; + } // end try + } // end method retrieveFault + + public void setFaultClassName( String name ) { this.faultClassName = name; } + public String getFaultClassName() { return this.faultClassName; } + + public String getFaultMessage() { return faultMessage; } + public void setFaultMessage(String faultMessage) { this.faultMessage = faultMessage; } + + public AsyncFaultWrapper getContainedFault() { return containedFault; } + public void setContainedFault(AsyncFaultWrapper containedFault) { this.containedFault = containedFault; } + +} // end class AsyncFaultWrapper diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseException.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseException.java new file mode 100644 index 0000000000..df90c3286d --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseException.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.core.invocation; + +/** + * An exception which is used to signal that a service has been invoked asynchronously + * and that the result will be sent separately + * + */ +public class AsyncResponseException extends RuntimeException { + + private static final long serialVersionUID = 457954562860541631L; + + public AsyncResponseException() { + super(); + } + + public AsyncResponseException(String arg0, Throwable arg1) { + super(arg0, arg1); + } + + public AsyncResponseException(String arg0) { + super(arg0); + } + + public AsyncResponseException(Throwable arg0) { + super(arg0); + } + +} // end class AsyncResponseException diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseHandler.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseHandler.java new file mode 100644 index 0000000000..d8eac8a166 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/AsyncResponseHandler.java @@ -0,0 +1,49 @@ +/* + * 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.core.invocation; + +import org.oasisopen.sca.annotation.OneWay; +import org.oasisopen.sca.annotation.Remotable; + +/** + * An interface which describes a general response pattern for the asynchronous invocation of a service + * + * @param <V> - the type of the non-fault response + */ +@Remotable() +public interface AsyncResponseHandler<V> { + + /** + * Async process completed with a Fault. Must only be invoked once + * @param e - the wrapper containing the Fault to send + * @throws IllegalStateException if either the setResponse method or the setFault method have been called previously + */ + @OneWay + public void setFault(AsyncFaultWrapper e); + + /** + * Async process completed with a response message. Must only be invoked once + * @throws IllegalStateException if either the setResponse method or the setFault method have been called previously + * @param res - the response message, which is of type V + */ + @OneWay + public void setResponse(V res); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallableReferenceObjectFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallableReferenceObjectFactory.java new file mode 100644 index 0000000000..400bb333fd --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallableReferenceObjectFactory.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.invocation; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; +import org.oasisopen.sca.ServiceReference; + +/** + * Uses a wire to return a CallableReference + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public class CallableReferenceObjectFactory implements ObjectFactory<ServiceReference<?>> { + private Class<?> businessInterface; + private RuntimeEndpointReference endpointReference; + + /** + * Constructor. + * + * To support the @Reference protected CallableReference<MyService> ref; + * + * @param businessInterface the interface to inject + * @param component the component defining the reference to be injected + * @param reference the reference to be injected + * @param binding the binding for the reference + */ + public CallableReferenceObjectFactory(Class<?> businessInterface, + RuntimeEndpointReference endpointReference) { + this.businessInterface = businessInterface; + this.endpointReference = endpointReference; + } + + public ServiceReference<?> getInstance() throws ObjectCreationException { + RuntimeComponent component = (RuntimeComponent) endpointReference.getComponent(); + return component.getComponentContext().getServiceReference(businessInterface, endpointReference); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackInterfaceInterceptor.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackInterfaceInterceptor.java new file mode 100644 index 0000000000..588eaa2d15 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackInterfaceInterceptor.java @@ -0,0 +1,60 @@ +/* + * 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.core.invocation; + +import org.apache.tuscany.sca.invocation.Interceptor; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; + +/** + * An interceptor applied to the forward direction of a wire that ensures the callback target implements the required + * service contract. This is required as callback targets may be set dynamically by service implementations. + * + * @version $Rev$ $Date$ + */ +public class CallbackInterfaceInterceptor implements Interceptor { + private Invoker next; + + public CallbackInterfaceInterceptor() { + } + + public Message invoke(Message msg) { + + /* TODO - EPR - not required for OASIS + ReferenceParameters parameters = msg.getFrom().getReferenceParameters(); + if (parameters.getCallbackObjectID() != null || parameters.getCallbackReference() != msg.getFrom() + .getCallbackEndpoint()) { + */ + return next.invoke(msg); + /* + } else { + throw new NoRegisteredCallbackException("Callback target does not implement the callback interface"); + } + */ + } + + public void setNext(Invoker next) { + this.next = next; + } + + public Invoker getNext() { + return next; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceObjectFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceObjectFactory.java new file mode 100644 index 0000000000..a56983a5d3 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackReferenceObjectFactory.java @@ -0,0 +1,50 @@ +/* + * 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.core.invocation; + +import java.util.List; + +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.core.context.impl.CallbackServiceReferenceImpl; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.oasisopen.sca.ServiceReference; + +/** + * Uses a wire to return a CallableReference + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public class CallbackReferenceObjectFactory implements ObjectFactory<ServiceReference<?>> { + private Class<?> businessInterface; + private ProxyFactory proxyFactory; + private List<EndpointReference> wires; + + public CallbackReferenceObjectFactory(Class<?> interfaze, ProxyFactory proxyFactory, List<EndpointReference> wires) { + this.businessInterface = interfaze; + this.proxyFactory = proxyFactory; + this.wires = wires; + } + + public ServiceReference<?> getInstance() throws ObjectCreationException { + return new CallbackServiceReferenceImpl(businessInterface, wires); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackWireObjectFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackWireObjectFactory.java new file mode 100644 index 0000000000..fff3727d87 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CallbackWireObjectFactory.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.core.invocation; + +import java.util.List; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.runtime.Invocable; + +/** + * Returns proxy instance for a wire callback + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public class CallbackWireObjectFactory<B> implements ObjectFactory<B> { + private Class<B> businessInterface; + private ProxyFactory proxyFactory; + private List<Invocable> wires; + + public CallbackWireObjectFactory(Class<B> interfaze, ProxyFactory proxyFactory, List<Invocable> wires) { + this.businessInterface = interfaze; + this.proxyFactory = proxyFactory; + this.wires = wires; + } + + public B getInstance() throws ObjectCreationException { + return proxyFactory.createCallbackProxy(businessInterface, wires); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java new file mode 100644 index 0000000000..cb2c01f7d6 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java @@ -0,0 +1,152 @@ +/* + * 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.core.invocation; + +import java.lang.reflect.Method; +import java.util.List; + +import net.sf.cglib.proxy.Callback; +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.Factory; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +import org.apache.tuscany.sca.core.context.ServiceReferenceExt; +import org.apache.tuscany.sca.core.context.impl.ServiceReferenceImpl; +import org.apache.tuscany.sca.core.invocation.impl.JDKCallbackInvocationHandler; +import org.apache.tuscany.sca.core.invocation.impl.JDKInvocationHandler; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.runtime.Invocable; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.oasisopen.sca.ServiceReference; + +/** + * The implementation of a wire service that uses cglib dynamic proxies + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public class CglibProxyFactory implements ProxyFactory { + private MessageFactory messageFactory; + + public CglibProxyFactory(MessageFactory messageFactory, InterfaceContractMapper mapper) { + this.messageFactory = messageFactory; + + } + + public <T> T createProxy(final Class<T> interfaze, Invocable invocable) throws ProxyCreationException { + if (invocable instanceof RuntimeEndpoint) { + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(interfaze); + enhancer.setCallback(new CglibMethodInterceptor<T>(interfaze, invocable)); + Object proxy = enhancer.create(); + return interfaze.cast(proxy); + } + ServiceReference<T> serviceReference = new ServiceReferenceImpl(interfaze, invocable, null); + return createProxy(serviceReference); + } + + /** + * create the proxy with cglib. use the same JDKInvocationHandler as + * JDKProxyService. + */ + public <T> T createProxy(ServiceReference<T> callableReference) throws ProxyCreationException { + Enhancer enhancer = new Enhancer(); + Class<T> interfaze = callableReference.getBusinessInterface(); + enhancer.setSuperclass(interfaze); + enhancer.setCallback(new CglibMethodInterceptor<T>(callableReference)); + Object proxy = enhancer.create(); + ((ServiceReferenceImpl)callableReference).setProxy(proxy); + return interfaze.cast(proxy); + } + + /** + * create the callback proxy with cglib. use the same + * JDKCallbackInvocationHandler as JDKProxyService. + */ + public <T> T createCallbackProxy(Class<T> interfaze, final List<? extends Invocable> wires) throws ProxyCreationException { + ServiceReferenceImpl<T> callbackReference = new ServiceReferenceImpl(interfaze, wires.get(0), null); + return callbackReference != null ? createCallbackProxy(callbackReference) : null; + } + + /** + * create the callback proxy with cglib. use the same + * JDKCallbackInvocationHandler as JDKProxyService. + */ + public <T> T createCallbackProxy(ServiceReference<T> callbackReference) throws ProxyCreationException { + Enhancer enhancer = new Enhancer(); + Class<T> interfaze = callbackReference.getBusinessInterface(); + enhancer.setSuperclass(interfaze); + enhancer.setCallback(new CglibMethodInterceptor<T>(callbackReference)); + Object object = enhancer.create(); + T proxy = interfaze.cast(object); + ((ServiceReferenceExt<T>)callbackReference).setProxy(proxy); + return proxy; + } + + @SuppressWarnings("unchecked") + public <B, R extends ServiceReference<B>> R cast(B target) throws IllegalArgumentException { + if (isProxyClass(target.getClass())) { + Factory factory = (Factory)target; + Callback[] callbacks = factory.getCallbacks(); + if (callbacks.length != 1 || !(callbacks[0] instanceof CglibMethodInterceptor)) { + throw new IllegalArgumentException("The object is not a known proxy."); + } + CglibMethodInterceptor interceptor = (CglibMethodInterceptor)callbacks[0]; + return (R)interceptor.invocationHandler.getCallableReference(); + } else { + throw new IllegalArgumentException("The object is not a known proxy."); + } + } + + /** + * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#isProxyClass(java.lang.Class) + */ + public boolean isProxyClass(Class<?> clazz) { + return Factory.class.isAssignableFrom(clazz); + } + + private class CglibMethodInterceptor<T> implements MethodInterceptor { + private JDKInvocationHandler invocationHandler; + + public CglibMethodInterceptor(ServiceReference<T> callableReference) { + invocationHandler = new JDKInvocationHandler(messageFactory, callableReference); + } + + public CglibMethodInterceptor(Class<?> interfaze, Invocable invocable) { + invocationHandler = new JDKInvocationHandler(messageFactory, interfaze, invocable); + } + + public CglibMethodInterceptor(ServiceReferenceImpl<T> callbackReference) { + invocationHandler = new JDKCallbackInvocationHandler(messageFactory, callbackReference); + } + + /** + * @see net.sf.cglib.proxy.MethodInterceptor#intercept(java.lang.Object, java.lang.reflect.Method, java.lang.Object[], net.sf.cglib.proxy.MethodProxy) + */ + public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { + Object result = invocationHandler.invoke(proxy, method, args); + return result; + } + + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/DefaultProxyFactoryExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/DefaultProxyFactoryExtensionPoint.java new file mode 100644 index 0000000000..af6f039775 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/DefaultProxyFactoryExtensionPoint.java @@ -0,0 +1,95 @@ +/* + * 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.core.invocation; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.LifeCycleListener; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.invocation.impl.JDKProxyFactory; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.invocation.MessageFactory; + +/** + * Default implementation of a ProxyFactoryExtensionPoint. + * + * @version $Rev$ $Date$ + */ +public class DefaultProxyFactoryExtensionPoint implements ProxyFactoryExtensionPoint, LifeCycleListener { + private InterfaceContractMapper interfaceContractMapper; + private MessageFactory messageFactory; + + private ProxyFactory interfaceFactory; + private ProxyFactory classFactory; + + public DefaultProxyFactoryExtensionPoint(ExtensionPointRegistry extensionPoints) { + UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class); + this.interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class); + + FactoryExtensionPoint modelFactories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class); + this.messageFactory = modelFactories.getFactory(MessageFactory.class); + + interfaceFactory = new JDKProxyFactory(messageFactory, interfaceContractMapper); + } + + public DefaultProxyFactoryExtensionPoint(MessageFactory messageFactory, InterfaceContractMapper mapper) { + this.interfaceContractMapper = mapper; + this.messageFactory = messageFactory; + interfaceFactory = new JDKProxyFactory(messageFactory, mapper); + } + + public ProxyFactory getClassProxyFactory() { + return classFactory; + } + + public ProxyFactory getInterfaceProxyFactory() { + return interfaceFactory; + } + + public void setClassProxyFactory(ProxyFactory factory) { + this.classFactory = factory; + + } + + public void setInterfaceProxyFactory(ProxyFactory factory) { + this.interfaceFactory = factory; + + } + + public void start() { + if (interfaceFactory instanceof LifeCycleListener) { + ((LifeCycleListener)interfaceFactory).start(); + } + if (classFactory instanceof LifeCycleListener) { + ((LifeCycleListener)classFactory).start(); + } + } + + public void stop() { + if (interfaceFactory instanceof LifeCycleListener) { + ((LifeCycleListener)interfaceFactory).stop(); + } + if (classFactory instanceof LifeCycleListener) { + ((LifeCycleListener)classFactory).stop(); + } + + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleProxyFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleProxyFactory.java new file mode 100644 index 0000000000..049c73f258 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleProxyFactory.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.core.invocation; + +import java.util.List; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.runtime.Invocable; +import org.oasisopen.sca.ServiceReference; + +/** + * An extensible proxy factory. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public class ExtensibleProxyFactory implements ProxyFactory { + + private ProxyFactoryExtensionPoint proxyFactories; + + public ExtensibleProxyFactory(ProxyFactoryExtensionPoint proxyFactories) { + this.proxyFactories = proxyFactories; + } + + public ExtensibleProxyFactory(ExtensionPointRegistry registry) { + this.proxyFactories = registry.getExtensionPoint(ProxyFactoryExtensionPoint.class); + } + + public static ExtensibleProxyFactory getInstance(ExtensionPointRegistry registry) { + UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class); + return utilities.getUtility(ExtensibleProxyFactory.class); + } + + /** + * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#cast(java.lang.Object) + */ + @SuppressWarnings("unchecked") + public <B, R extends ServiceReference<B>> R cast(B target) throws IllegalArgumentException { + ProxyFactory interfaceFactory = proxyFactories.getInterfaceProxyFactory(); + ProxyFactory classFactory = proxyFactories.getClassProxyFactory(); + if (interfaceFactory.isProxyClass(target.getClass())) { + return (R)interfaceFactory.cast(target); + } else if (classFactory != null && classFactory.isProxyClass(target.getClass())) { + return (R)classFactory.cast(target); + } else { + throw new IllegalArgumentException("The target is not a callable proxy"); + } + } + + /** + * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#createCallbackProxy(java.lang.Class, + * java.util.List) + */ + public <T> T createCallbackProxy(Class<T> interfaze, List<? extends Invocable> wires) throws ProxyCreationException { + ProxyFactory interfaceFactory = proxyFactories.getInterfaceProxyFactory(); + ProxyFactory classFactory = proxyFactories.getClassProxyFactory(); + if (interfaze.isInterface()) { + return interfaceFactory.createCallbackProxy(interfaze, wires); + } else { + return classFactory.createCallbackProxy(interfaze, wires); + } + } + + public <T> T createProxy(ServiceReference<T> callableReference) throws ProxyCreationException { + ProxyFactory interfaceFactory = proxyFactories.getInterfaceProxyFactory(); + ProxyFactory classFactory = proxyFactories.getClassProxyFactory(); + if (callableReference.getBusinessInterface().isInterface()) { + return interfaceFactory.createProxy(callableReference); + } else { + return classFactory.createProxy(callableReference); + } + } + + public <T> T createCallbackProxy(ServiceReference<T> callbackReference) throws ProxyCreationException { + ProxyFactory interfaceFactory = proxyFactories.getInterfaceProxyFactory(); + ProxyFactory classFactory = proxyFactories.getClassProxyFactory(); + if (callbackReference.getBusinessInterface().isInterface()) { + return interfaceFactory.createCallbackProxy(callbackReference); + } else { + return classFactory.createCallbackProxy(callbackReference); + } + } + + /** + * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#createProxy(java.lang.Class, + * org.apache.tuscany.sca.runtime.Invocable) + */ + public <T> T createProxy(Class<T> interfaze, Invocable wire) throws ProxyCreationException { + ProxyFactory interfaceFactory = proxyFactories.getInterfaceProxyFactory(); + ProxyFactory classFactory = proxyFactories.getClassProxyFactory(); + if (interfaze.isInterface()) { + return interfaceFactory.createProxy(interfaze, wire); + } else { + return classFactory.createProxy(interfaze, wire); + } + } + + /** + * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#isProxyClass(java.lang.Class) + */ + public boolean isProxyClass(Class<?> clazz) { + ProxyFactory interfaceFactory = proxyFactories.getInterfaceProxyFactory(); + ProxyFactory classFactory = proxyFactories.getClassProxyFactory(); + return interfaceFactory.isProxyClass(clazz) || (classFactory != null && classFactory.isProxyClass(clazz)); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleWireProcessor.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleWireProcessor.java new file mode 100644 index 0000000000..08019ec3e2 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleWireProcessor.java @@ -0,0 +1,51 @@ +/* + * 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.core.invocation; + +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessor; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessorExtensionPoint; + +/** + * The default implementation of an extensible <code>WireProcessor</code> + * + * @version $Rev$ $Date$ + */ +public class ExtensibleWireProcessor implements RuntimeWireProcessor { + + private RuntimeWireProcessorExtensionPoint processors; + + public ExtensibleWireProcessor(RuntimeWireProcessorExtensionPoint processors) { + this.processors = processors; + } + + public void process(RuntimeEndpoint endpoint) { + for (RuntimeWireProcessor processor : processors.getWireProcessors()) { + processor.process(endpoint); + } + } + + public void process(RuntimeEndpointReference endpointReference) { + for (RuntimeWireProcessor processor : processors.getWireProcessors()) { + processor.process(endpointReference); + } + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/NonBlockingInterceptor.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/NonBlockingInterceptor.java new file mode 100644 index 0000000000..a31a126977 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/NonBlockingInterceptor.java @@ -0,0 +1,185 @@ +/* + * 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.core.invocation; + +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.context.ThreadMessageContext; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Interceptor; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.work.WorkScheduler; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * Adds non-blocking behavior to an invocation chain + * + * @version $Rev$ $Date$ + */ +public class NonBlockingInterceptor implements Interceptor { + + private static final Message RESPONSE = new ImmutableMessage(); + + /** + * The JDK logger that will be used to log messages. + */ + private static final Logger LOGGER = Logger.getLogger(NonBlockingInterceptor.class.getName()); + + private WorkScheduler workScheduler; + private Invoker next; + + public NonBlockingInterceptor(WorkScheduler workScheduler) { + this.workScheduler = workScheduler; + } + + public NonBlockingInterceptor(WorkScheduler workScheduler, Interceptor next) { + this.workScheduler = workScheduler; + this.next = next; + } + + /** + * Sets desired workScheduler to NonBlockingInterceptor. This is a useful function for the extension framework + * to set desired workmanager on the InvocationChain, other than default workmanager which is set per Tuscany runtime. + * Using this function, extension framework can set desired workmanager on InvocationChain during post wire processing. + * @param workScheduler workScheduler which contains workmanager + */ + public void setWorkScheduler(WorkScheduler workScheduler){ + this.workScheduler = workScheduler; + } + + public Message invoke(final Message msg) { + // Schedule the invocation of the next interceptor in a new Work instance + try { + workScheduler.scheduleWork(new Runnable() { + public void run() { + Message context = ThreadMessageContext.setMessageContext(msg); + try { + Message response = null; + + Throwable ex = null; + try { + response = next.invoke(msg); + } catch (Throwable t) { + ex = t; + } + + // Tuscany-2225 - Did the @OneWay method complete successfully? + // (i.e. no exceptions) + if (response != null && response.isFault()) { + // The @OneWay method threw an Exception. Lets log it and + // then pass it on to the WorkScheduler so it can notify any + // listeners + ex = (Throwable)response.getBody(); + } + if (ex != null) { + LOGGER.log(Level.SEVERE, "Exception from @OneWay invocation", ex); + throw new ServiceRuntimeException("Exception from @OneWay invocation", ex); + } + } finally { + ThreadMessageContext.setMessageContext(context); + } + } + }); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + return RESPONSE; + } + + public Invoker getNext() { + return next; + } + + public void setNext(Invoker next) { + this.next = next; + } + + /** + * A dummy message passed back on an invocation + */ + private static class ImmutableMessage implements Message { + + public <T> T getBody() { + return null; + } + + public void setBody(Object body) { + if (body != null) { + throw new UnsupportedOperationException(); + } + } + + public Object getMessageID() { + return null; + } + + public void setMessageID(Object messageId) { + throw new UnsupportedOperationException(); + } + + public boolean isFault() { + return false; + } + + public void setFaultBody(Object fault) { + throw new UnsupportedOperationException(); + } + + public EndpointReference getFrom() { + return null; + } + + public Endpoint getTo() { + return null; + } + + public void setFrom(EndpointReference from) { + throw new UnsupportedOperationException(); + } + + public void setTo(Endpoint to) { + throw new UnsupportedOperationException(); + } + + public Operation getOperation() { + return null; + } + + public void setOperation(Operation op) { + throw new UnsupportedOperationException(); + } + + public Map<String, Object> getHeaders() { + return null; + } + public <T> T getBindingContext() { + return null; + } + + public <T> void setBindingContext(T bindingContext) { + } + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyCreationException.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyCreationException.java new file mode 100644 index 0000000000..0b36b178f3 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyCreationException.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.core.invocation; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; + + +/** + * Denotes an error creating a proxy + * + * @version $Rev$ $Date$ + */ +public class ProxyCreationException extends ObjectCreationException { + private static final long serialVersionUID = 8002454344828513781L; + + public ProxyCreationException() { + super(); + } + + public ProxyCreationException(String message, Throwable cause) { + super(message, cause); + } + + public ProxyCreationException(String message) { + super(message); + } + + public ProxyCreationException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java new file mode 100644 index 0000000000..f2d272757d --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.invocation; + +import java.util.List; + +import org.apache.tuscany.sca.runtime.Invocable; +import org.oasisopen.sca.ServiceReference; + +/** + * Creates proxies that implement Java interfaces and invocation handlers for fronting wires + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ + +public interface ProxyFactory { + + /** + * Creates a Java proxy for the given wire + * + * @param interfaze the interface the proxy implements + * @param invocable the wire to proxy + * @return the proxy + * @throws ProxyCreationException + */ + <T> T createProxy(Class<T> interfaze, Invocable invocable) throws ProxyCreationException; + + /** + * Creates a Java proxy for the given CallableReference + * + * @param callableReference The CallableReference + * @return the proxy + * @throws ProxyCreationException + */ + <T> T createProxy(ServiceReference<T> callableReference) throws ProxyCreationException; + + /** + * Creates a Java proxy for the service contract callback + * + * @param interfaze the interface the proxy should implement + * @return the proxy + * @throws ProxyCreationException + */ + <T> T createCallbackProxy(Class<T> interfaze, List<? extends Invocable> invocables) throws ProxyCreationException; + + /** + * Creates a Java proxy for the given callback reference + * + * @param callableReference The CallableReference + * @return the proxy + * @throws ProxyCreationException + */ + <T> T createCallbackProxy(ServiceReference<T> callbackReference) throws ProxyCreationException; + + /** + * Cast a proxy to a CallableReference. + * + * @param target a proxy generated by this implementation + * @return a CallableReference (or subclass) equivalent to this proxy + * @throws IllegalArgumentException if the object supplied is not a proxy + */ + <B, R extends ServiceReference<B>> R cast(B target) throws IllegalArgumentException; + + /** + * Test if a given class is a generated proxy class by this factory + * @param clazz A java class or interface + * @return true if the class is a generated proxy class by this factory + */ + boolean isProxyClass(Class<?> clazz); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactoryExtensionPoint.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactoryExtensionPoint.java new file mode 100644 index 0000000000..3e0bd7cb17 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactoryExtensionPoint.java @@ -0,0 +1,54 @@ +/* + * 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.core.invocation; + + +/** + * The extension point to plug in proxy factories + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface ProxyFactoryExtensionPoint { + + /** + * Get the proxy factory for java interfaces + * @return + */ + ProxyFactory getInterfaceProxyFactory(); + + /** + * Get the proxy factory for java classes + * @return + */ + ProxyFactory getClassProxyFactory(); + + /** + * Set the proxy factory for java interfaces + * @param factory + */ + void setInterfaceProxyFactory(ProxyFactory factory); + + /** + * Set the proxy factory for java classes + * @param factory + */ + void setClassProxyFactory(ProxyFactory factory); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeInvoker.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeInvoker.java new file mode 100644 index 0000000000..0751fd631b --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/RuntimeInvoker.java @@ -0,0 +1,97 @@ +/* + * 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.core.invocation; + +import java.lang.reflect.InvocationTargetException; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.context.ThreadMessageContext; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.runtime.Invocable; + +/** + * Invoker for a endpoint or endpoint reference + * @version $Rev$ $Date$ + */ +public class RuntimeInvoker implements Invoker { + protected MessageFactory messageFactory; + protected Invocable invocable; + + public RuntimeInvoker(MessageFactory messageFactory, Invocable invocable) { + this.messageFactory = messageFactory; + this.invocable = invocable; + } + + public Message invokeBinding(Message msg) { + Message context = ThreadMessageContext.setMessageContext(msg); + try { + return invocable.getBindingInvocationChain().getHeadInvoker().invoke(msg); + } finally { + ThreadMessageContext.setMessageContext(context); + } + } + + public Message invoke(Message msg) { + return invoke(msg.getOperation(), msg); + } + + public Object invoke(Operation operation, Object[] args) throws InvocationTargetException { + Message msg = messageFactory.createMessage(); + msg.setBody(args); + Message resp = invoke(operation, msg); + Object body = resp.getBody(); + if (resp.isFault()) { + throw new InvocationTargetException((Throwable)body); + } + return body; + } + + + public Message invoke(Operation operation, Message msg) { + InvocationChain chain = invocable.getInvocationChain(operation); + return invoke(chain, msg); + } + + public Message invoke(InvocationChain chain, Message msg) { + + if (invocable instanceof Endpoint) { + msg.setTo((Endpoint)invocable); + } else if (invocable instanceof EndpointReference) { + msg.setFrom((EndpointReference)invocable); + } + + Invoker headInvoker = chain.getHeadInvoker(); + Operation operation = chain.getTargetOperation(); + msg.setOperation(operation); + + Message msgContext = ThreadMessageContext.setMessageContext(msg); + try { + return headInvoker.invoke(msg); + } finally { + ThreadMessageContext.setMessageContext(msgContext); + } + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/WireObjectFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/WireObjectFactory.java new file mode 100644 index 0000000000..489d06a3e1 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/WireObjectFactory.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.core.invocation; + +import org.apache.tuscany.sca.core.context.impl.ServiceReferenceImpl; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.core.invocation.impl.NoMethodForOperationException; +import org.apache.tuscany.sca.runtime.Invocable; + +/** + * Uses a wire to return an object instance + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public class WireObjectFactory<T> implements ObjectFactory<T> { + private Class<T> interfaze; + private Invocable wire; + private ProxyFactory proxyService; + + /** + * Constructor. + * + * @param interfaze the interface to inject on the client + * @param wire the backing wire + * @param proxyService the wire service to create the proxy + * @throws NoMethodForOperationException + */ + public WireObjectFactory(Class<T> interfaze, Invocable wire, ProxyFactory proxyService) { + this.interfaze = interfaze; + this.wire = wire; + this.proxyService = proxyService; + } + + public T getInstance() throws ObjectCreationException { + return new ServiceReferenceImpl<T>(interfaze, wire, null).getProxy(); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncInvocationFutureImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncInvocationFutureImpl.java new file mode 100644 index 0000000000..8db469b25e --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncInvocationFutureImpl.java @@ -0,0 +1,239 @@ +/* + * 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.core.invocation.impl; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import javax.xml.ws.Response; + +import org.apache.tuscany.sca.core.invocation.AsyncFaultWrapper; +import org.apache.tuscany.sca.core.invocation.AsyncResponseHandler; + +/** + * A class which provides an Implementation of a Future<V> and Response<V> for use with the JAXWS defined client + * asynchronous APIs. + * + * This implementation class provides the interfaces for use by the client code, but also provides methods for the + * Tuscany system code to set the result of the asynchronous service invocation, both Regular and Fault responses. + * + * This class is constructed to be fully thread-safe + * + * @param <V> - this is the type of the response message from the invoked service. + */ +public class AsyncInvocationFutureImpl<V> implements Future<V>, Response<V>, AsyncResponseHandler<V> { + + // Lock for handling the completion of this Future + private final Lock lock = new ReentrantLock(); + private final Condition isDone = lock.newCondition(); + + // The result + private volatile V response = null; + private volatile Throwable fault = null; + + private String uniqueID = UUID.randomUUID().toString(); + + private ClassLoader classLoader = null; + + protected AsyncInvocationFutureImpl() { + super(); + } // end constructor + + /** + * Public constructor for AsyncInvocationFutureImpl - newInstance is necessary in order to enable the Type variable + * to be set for the class instances + * @param <V> - the type of the response from the asynchronously invoked service + * @param type - the type of the AsyncInvocationFutureImpl expressed as a parameter + * @param classLoader - the classloader used for the business interface to which this Future applies + * @return - an instance of AsyncInvocationFutureImpl<V> + */ + public static <V> AsyncInvocationFutureImpl<V> newInstance( Class<V> type, ClassLoader classLoader ) { + AsyncInvocationFutureImpl<V> future = new AsyncInvocationFutureImpl<V>(); + future.setClassLoader( classLoader ); + return future; + } + + /** + * Cancels the asynchronous process + * - not possible in this version, so always returns false + */ + public boolean cancel(boolean mayInterruptIfRunning) { + return false; + } + + /** + * Gets the response value returned by the asynchronous process + * - waits forever + * @return - the response value of type V + * @throws InterruptedException if the get() method was interrupted while waiting for the async process to finish + * @throws ExecutionException if the async process threw an exception - the exception thrown is nested + */ + public V get() throws InterruptedException, ExecutionException { + try { + V response = get(Long.MAX_VALUE, TimeUnit.SECONDS); + return response; + } catch (TimeoutException t) { + throw new InterruptedException("Timed out waiting for Future to complete"); + } // end try + } // end method get() + + /** + * Gets the response value returned by the asynchronous process + * @return - the response value of type V + * @throws InterruptedException if the get() method was interrupted while waiting for the async process to finish + * @throws ExecutionException if the async process threw an exception - the exception thrown is nested + * @throws TimeoutException if the get() method timed out waiting for the async process to finish + */ + public V get(long timeout, TimeUnit unit) throws InterruptedException, + ExecutionException, TimeoutException { + lock.lock(); + try { + // wait for result to be available + if( notSetYet() ) isDone.await( timeout, unit); + if( response != null ) return response; + if( fault != null ) throw new ExecutionException( fault ); + throw new TimeoutException("get on this Future timed out"); + } finally { + lock.unlock(); + } // end try + + } // end method get(long timeout, TimeUnit unit) + + /** + * Indicates if the asynchronous process has been cancelled + * - not possible in this version so always returns false + */ + public boolean isCancelled() { + return false; + } + + /** + * Indicates if the asynchronous process is completed + * @return - true if the process is completed, false otherwise + */ + public boolean isDone() { + lock.lock(); + try { + return !notSetYet(); + } finally { + lock.unlock(); + } // end try + } // end method isDone + + /** + * Async process completed with a Fault. Must only be invoked once + * @param e - the Fault to send + * @throws IllegalStateException if either the setResponse method or the setFault method have been called previously + */ + public void setFault(AsyncFaultWrapper w) { + + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + Throwable e; + try { + // Set the TCCL to the classloader of the business interface + Thread.currentThread().setContextClassLoader(this.getClassLoader()); + e = w.retrieveFault(); + } finally { + Thread.currentThread().setContextClassLoader(tccl); + } // end try + + if( e == null ) throw new IllegalArgumentException("AsyncFaultWrapper did not return an Exception"); + lock.lock(); + try { + if( notSetYet() ) { + fault = e; + isDone.signalAll(); + } else { + throw new IllegalStateException("setResponse() or setFault() has been called previously"); + } // end if + } finally { + lock.unlock(); + } // end try + + } // end method setFault + + /** + * Async process completed with a response message. Must only be invoked once + * @throws IllegalStateException if either the setResponse method or the setFault method have been called previously + * @param res - the response message, which is of type V + */ + public void setResponse(V res) { + + lock.lock(); + try { + if( notSetYet() ) { + response = res; + isDone.signalAll(); + } else { + throw new IllegalStateException("setResponse() or setFault() has been called previously"); + } + } finally { + lock.unlock(); + } // end try + + } // end method setResponse + + /** + * Gets the unique ID of this future as a String + */ + public String getUniqueID() { return uniqueID; } + + /** + * Indicates that setting a response value is OK - can only set the response value or fault once + * @return - true if it is OK to set the response, false otherwise + */ + private boolean notSetYet() { + return ( response == null && fault == null ); + } + + /** + * Returns the JAXWS context for the response + * @return - a Map containing the context + */ + public Map<String, Object> getContext() { + // Intentionally returns null + return null; + } + + /** + * Gets the classloader associated with the business interface to which this Future relates + * @return the ClassLoader of the business interface + */ + public ClassLoader getClassLoader() { + return classLoader; + } + + /** + * Sets the classloader associated with the business interface to which this Future relates + * @param classLoader - the classloader of the business interface + */ + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + +} // end class AsyncInvocationFutureImpl diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncJDKInvocationHandler.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncJDKInvocationHandler.java new file mode 100644 index 0000000000..e0e219d3f1 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncJDKInvocationHandler.java @@ -0,0 +1,556 @@ +/* + * 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.core.invocation.impl; + +import java.io.StringReader; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.transform.stream.StreamSource; +import javax.xml.ws.AsyncHandler; +import javax.xml.ws.Response; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.builder.BindingBuilder; +import org.apache.tuscany.sca.assembly.builder.BuilderContext; +import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint; +import org.apache.tuscany.sca.assembly.xml.Constants; +import org.apache.tuscany.sca.context.CompositeContext; +import org.apache.tuscany.sca.contribution.processor.ContributionReadException; +import org.apache.tuscany.sca.contribution.processor.ProcessorContext; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; +import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint; +import org.apache.tuscany.sca.contribution.processor.ValidatingXMLInputFactory; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.assembly.RuntimeAssemblyFactory; +import org.apache.tuscany.sca.core.invocation.AsyncFaultWrapper; +import org.apache.tuscany.sca.core.invocation.AsyncResponseHandler; +import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; +import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; +import org.apache.tuscany.sca.interfacedef.util.FaultException; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.provider.PolicyProvider; +import org.apache.tuscany.sca.provider.ServiceBindingProvider; +import org.apache.tuscany.sca.runtime.Invocable; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; +import org.oasisopen.sca.ServiceReference; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * An InvocationHandler which deals with JAXWS-defined asynchronous client Java API method calls + * + * 2 asynchronous mappings exist for any given synchronous service operation, as shown in this example: + * public interface StockQuote { + * float getPrice(String ticker); + * Response<Float> getPriceAsync(String ticker); + * Future<?> getPriceAsync(String ticker, AsyncHandler<Float> handler); + * } + * + * - the second method is called the "polling method", since the returned Response<?> object permits + * the client to poll to see if the async call has completed + * - the third method is called the "async callback method", since in this case the client application can specify + * a callback operation that is automatically called when the async call completes + */ +public class AsyncJDKInvocationHandler extends JDKInvocationHandler { + + private static final long serialVersionUID = 1L; + + private static int invocationCount = 10; // # of threads to use + private static long maxWaitTime = 30; // Max wait time for completion = 30sec + + // Run the async service invocations using a ThreadPoolExecutor + private static ThreadPoolExecutor theExecutor = new ThreadPoolExecutor( invocationCount, invocationCount, + maxWaitTime, TimeUnit.SECONDS, + new ArrayBlockingQueue<Runnable>( invocationCount ) ); + + + public AsyncJDKInvocationHandler(MessageFactory messageFactory, ServiceReference<?> callableReference) { + super(messageFactory, callableReference); + } + + public AsyncJDKInvocationHandler(MessageFactory messageFactory, + Class<?> businessInterface, + Invocable source) { + super(messageFactory, businessInterface, source); + } + + /** + * Perform the invocation of the operation + * - provides support for all 3 forms of client method: synchronous, polling and async callback + */ + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if (isAsyncCallback(method)) { + return doInvokeAsyncCallback(proxy, method, args); + } else if (isAsyncPoll(method)) { + return doInvokeAsyncPoll(proxy, method, args); + } else { + // Regular synchronous method call + return doInvokeSync(proxy, method, args); + } + } + + /** + * Indicates if a supplied method has the form of an async callback method + * @param method - the method + * @return - true if the method has the form of an async callback + */ + protected boolean isAsyncCallback(Method method) { + if (method.getName().endsWith("Async") && (method.getReturnType().isAssignableFrom(Future.class))) { + if (method.getParameterTypes().length > 0) { + return method.getParameterTypes()[method.getParameterTypes().length-1].isAssignableFrom(AsyncHandler.class); + } + } + return false; + } + + /** + * Indicates is a supplied method has the form of an async polling method + * @param method - the method + * @return - true if the method has the form of an async polling method + */ + protected boolean isAsyncPoll(Method method) { + return method.getName().endsWith("Async") && (method.getReturnType().isAssignableFrom(Response.class)); + } + + /** + * Invoke an async polling method + * @param proxy - the reference proxy + * @param asyncMethod - the async method to invoke + * @param args - array of input arguments to the method + * @return - the Response<?> object that is returned to the client application, typed by the + * type of the response + */ + @SuppressWarnings("unchecked") + protected Response doInvokeAsyncPoll(Object proxy, Method asyncMethod, Object[] args) { + Class<?> returnType = getNonAsyncMethod(asyncMethod).getReturnType(); + // Allocate the Future<?> / Response<?> object - note: Response<?> is a subclass of Future<?> + AsyncInvocationFutureImpl future = AsyncInvocationFutureImpl.newInstance( returnType, getInterfaceClassloader() ); + try { + invokeAsync(proxy, getNonAsyncMethod(asyncMethod), args, future); + } catch (Exception e) { + future.setFault( new AsyncFaultWrapper(e) ); + } catch (Throwable t ) { + Exception e = new ServiceRuntimeException("Received Throwable: " + t.getClass().getName() + + " when invoking: " + asyncMethod.getName(), t); + future.setFault( new AsyncFaultWrapper(e) ); + } // end try + return future; + } // end method doInvokeAsyncPoll + + /** + * Provide a synchronous invocation of a service operation that is either synchronous or asynchronous + * @return + */ + protected Object doInvokeSync(Object proxy, Method method, Object[] args) throws Throwable { + if ( isAsyncInvocation( source ) ) { + // Target service is asynchronous + Class<?> returnType = method.getReturnType(); + AsyncInvocationFutureImpl future = AsyncInvocationFutureImpl.newInstance( returnType, getInterfaceClassloader() ); + invokeAsync(proxy, method, args, future); + // Wait for some maximum time for the result - 1000 seconds here + // Really, if the service is async, the client should use async client methods to invoke the service + // - and be prepared to wait a *really* long time + return future.get(1000, TimeUnit.SECONDS); + } else { + // Target service is not asynchronous, so perform sync invocation + return super.invoke(proxy, method, args); + } // end if + } // end method doInvokeSync + + /** + * Invoke an async callback method - note that this form of the async client API has as its final parameter + * an AsyncHandler method, used for callbacks to the client code + * @param proxy - the reference proxy + * @param asyncMethod - the async method to invoke + * @param args - array of input arguments to the method + * @return - the Future<?> object that is returned to the client application, typed by the type of + * the response + */ + @SuppressWarnings("unchecked") + private Object doInvokeAsyncCallback(Object proxy, Method asyncMethod, Object[] args) { + AsyncHandler handler = (AsyncHandler)args[args.length-1]; + Response response = doInvokeAsyncPoll(proxy,asyncMethod,Arrays.copyOf(args, args.length-1)); + // Invoke the callback handler, if present + if( handler != null ) { + handler.handleResponse(response); + } // end if + + return response; + } // end method doInvokeAsyncCallback + + /** + * Invoke the target (synchronous) method asynchronously + * @param proxy - the reference proxy object + * @param method - the method to invoke + * @param args - arguments for the call + * @param future - Future for handling the response + * @return - returns the response from the invocation + * @throws Throwable - if an exception is thrown during the invocation + */ + @SuppressWarnings("unchecked") + private void invokeAsync(Object proxy, Method method, Object[] args, AsyncInvocationFutureImpl future) throws Throwable { + if (source == null) { + throw new ServiceRuntimeException("No runtime source is available"); + } + + if (source instanceof RuntimeEndpointReference) { + RuntimeEndpointReference epr = (RuntimeEndpointReference)source; + if (epr.isOutOfDate()) { + epr.rebuild(); + chains.clear(); + } + } // end if + + InvocationChain chain = getInvocationChain(method, source); + + if (chain == null) { + throw new IllegalArgumentException("No matching operation is found: " + method); + } + + // Organize for an async service + RuntimeEndpoint theEndpoint = getAsyncCallback( source ); + boolean isAsyncService = false; + if( theEndpoint != null ) { + // ... the service is asynchronous ... + attachFuture( theEndpoint, future ); + isAsyncService = true; + } else { + // ... the service is synchronous ... + } // end if + + // Perform the invocations on separate thread... + theExecutor.execute( new separateThreadInvoker( chain, args, source, future, isAsyncService ) ); + + return; + } // end method invokeAsync + + /** + * An inner class which acts as a runnable task for invoking services asynchronously on threads that are separate from + * those used to execute operations of components + * + * This supports both synchronous services and asynchronous services + */ + private class separateThreadInvoker implements Runnable { + + private AsyncInvocationFutureImpl future; + private InvocationChain chain; + private Object[] args; + private Invocable invocable; + private boolean isAsyncService; + + public separateThreadInvoker( InvocationChain chain, Object[] args, Invocable invocable, + AsyncInvocationFutureImpl future, boolean isAsyncService ) { + super(); + this.chain = chain; + this.args = args; + this.invocable = invocable; + this.future = future; + this.isAsyncService = isAsyncService; + } // end constructor + + public void run() { + Object result; + + try { + if( isAsyncService ) { + invoke(chain, args, invocable, future.getUniqueID()); + // The result is returned asynchronously via the future... + } else { + // ... the service is synchronous ... + result = invoke(chain, args, invocable); + future.setResponse(result); + } // end if + } catch ( ServiceRuntimeException s ) { + Throwable e = s.getCause(); + if( e != null && e instanceof FaultException ) { + if( "AsyncResponse".equals(e.getMessage()) ) { + // Do nothing... + } else { + future.setFault( new AsyncFaultWrapper( s ) ); + } // end if + } // end if + } catch ( Throwable t ) { + System.out.println("Async invoke got exception: " + t.toString()); + future.setFault( new AsyncFaultWrapper( t ) ); + } // end try + + } // end method run + + } // end class separateThreadInvoker + + /** + * Attaches a future to the callback endpoint - so that the Future is triggered when a response is + * received from the asynchronous service invocation associated with the Future + * @param endpoint - the async callback endpoint + * @param future - the async invocation future to attach + */ + private void attachFuture( RuntimeEndpoint endpoint, AsyncInvocationFutureImpl<?> future ) { + Implementation impl = endpoint.getComponent().getImplementation(); + AsyncResponseHandlerImpl<?> asyncHandler = (AsyncResponseHandlerImpl<?>) impl; + asyncHandler.addFuture(future); + } // end method attachFuture + + /** + * Get the async callback endpoint - if not already created, create and start it + * @param source - the RuntimeEndpointReference which needs an async callback endpoint + * @param future + * @return - the RuntimeEndpoint of the async callback + */ + private RuntimeEndpoint getAsyncCallback( Invocable source ) { + if( !(source instanceof RuntimeEndpointReference) ) return null; + RuntimeEndpointReference epr = (RuntimeEndpointReference) source; + if( !isAsyncInvocation( epr ) ) return null; + RuntimeEndpoint endpoint; + synchronized( epr ) { + endpoint = (RuntimeEndpoint)epr.getCallbackEndpoint(); + // If the async callback endpoint is already created, return it... + if( endpoint != null ) return endpoint; + // Create the endpoint for the async callback + endpoint = createAsyncCallbackEndpoint( epr ); + epr.setCallbackEndpoint(endpoint); + } // end synchronized + + // Activate the new callback endpoint + startEndpoint( epr.getCompositeContext(), endpoint ); + endpoint.getInvocationChains(); + + return endpoint; + } // end method setupAsyncCallback + + /** + * Start the callback endpoint + * @param compositeContext - the composite context + * @param ep - the endpoint to start + */ + private void startEndpoint(CompositeContext compositeContext, RuntimeEndpoint ep ) { + for (PolicyProvider policyProvider : ep.getPolicyProviders()) { + policyProvider.start(); + } // end for + + final ServiceBindingProvider bindingProvider = ep.getBindingProvider(); + if (bindingProvider != null) { + // Allow bindings to add shutdown hooks. Requires RuntimePermission shutdownHooks in policy. + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + bindingProvider.start(); + return null; + } + }); + compositeContext.getEndpointRegistry().addEndpoint(ep); + } + } // end method startEndpoint + + /** + * Create the async callback endpoint for a reference that is going to invoke an asyncInvocation service + * @param epr - the RuntimeEndpointReference for which the callback is created + * @return - a RuntimeEndpoint representing the callback endpoint + */ + private RuntimeEndpoint createAsyncCallbackEndpoint( RuntimeEndpointReference epr ) { + CompositeContext compositeContext = epr.getCompositeContext(); + RuntimeAssemblyFactory assemblyFactory = getAssemblyFactory( compositeContext ); + RuntimeEndpoint endpoint = (RuntimeEndpoint)assemblyFactory.createEndpoint(); + endpoint.bind( compositeContext ); + + // Create a pseudo-component and pseudo-service + // - need to end with a chain with an invoker into the AsyncCallbackHandler class + RuntimeComponent fakeComponent = null; + try { + fakeComponent = (RuntimeComponent)epr.getComponent().clone(); + applyImplementation( fakeComponent ); + } catch (CloneNotSupportedException e2) { + // will not happen + } // end try + endpoint.setComponent(fakeComponent); + + // Create pseudo-service + ComponentService service = assemblyFactory.createComponentService(); + ExtensionPointRegistry registry = compositeContext.getExtensionPointRegistry(); + FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class); + JavaInterfaceFactory javaInterfaceFactory = (JavaInterfaceFactory)modelFactories.getFactory(JavaInterfaceFactory.class); + JavaInterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract(); + try { + interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(AsyncResponseHandler.class)); + } catch (InvalidInterfaceException e1) { + // Nothing to do here - will not happen + } // end try + service.setInterfaceContract(interfaceContract); + String serviceName = epr.getReference().getName() + "_asyncCallback"; + service.setName(serviceName); + endpoint.setService(service); + // Set pseudo-service onto the pseudo-component + List<ComponentService> services = fakeComponent.getServices(); + services.clear(); + services.add(service); + + // Create a binding + Binding binding = createMatchingBinding( epr.getBinding(), fakeComponent, service, registry ); + endpoint.setBinding(binding); + + // Need to establish policies here (binding has some...) + endpoint.getRequiredIntents().addAll( epr.getRequiredIntents() ); + endpoint.getPolicySets().addAll( epr.getPolicySets() ); + String epURI = epr.getComponent().getName() + "#service-binding(" + serviceName + "/" + serviceName + ")"; + endpoint.setURI(epURI); + endpoint.setUnresolved(false); + return endpoint; + } + + /** + * Create a matching binding to a supplied binding + * - the matching binding has the same binding type, but is for the supplied component and service + * @param matchBinding - the binding to match + * @param component - the component + * @param service - the service + * @param registry - registry for extensions + * @return - the matching binding, or null if it could not be created + */ + @SuppressWarnings("unchecked") + private Binding createMatchingBinding( Binding matchBinding, RuntimeComponent component, + ComponentService service, ExtensionPointRegistry registry ) { + // Since there is no simple way to obtain a Factory for a binding where the type is not known ahead of + // time, the process followed here is to generate the <binding.xxx/> XML element from the binding type QName + // and then read the XML using the processor for that XML... + QName bindingName = matchBinding.getType(); + String bindingXML = "<ns1:" + bindingName.getLocalPart() + " xmlns:ns1='" + bindingName.getNamespaceURI() + "'/>"; + + StAXArtifactProcessorExtensionPoint processors = registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class); + StAXArtifactProcessor<?> processor = (StAXArtifactProcessor<?>)processors.getProcessor(bindingName); + + FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class); + ValidatingXMLInputFactory inputFactory = modelFactories.getFactory(ValidatingXMLInputFactory.class); + StreamSource source = new StreamSource( new StringReader(bindingXML) ); + + ProcessorContext context = new ProcessorContext(); + try { + XMLStreamReader reader = inputFactory.createXMLStreamReader(source); + reader.next(); + Binding newBinding = (Binding) processor.read(reader, context ); + + // Create a URI address for the callback based on the Component_Name/Reference_Name pattern + String callbackURI = "/" + component.getName() + "/" + service.getName(); + newBinding.setURI(callbackURI); + + BuilderExtensionPoint builders = registry.getExtensionPoint(BuilderExtensionPoint.class); + BindingBuilder builder = builders.getBindingBuilder(newBinding.getType()); + if (builder != null) { + org.apache.tuscany.sca.assembly.builder.BuilderContext builderContext = new BuilderContext(registry); + builder.build(component, service, newBinding, builderContext, true); + } // end if + + return newBinding; + } catch (ContributionReadException e) { + e.printStackTrace(); + } catch (XMLStreamException e) { + e.printStackTrace(); + } + + return null; + } // end method createMatchingBinding + + /** + * Gets a RuntimeAssemblyFactory from the CompositeContext + * @param compositeContext + * @return the RuntimeAssemblyFactory + */ + private RuntimeAssemblyFactory getAssemblyFactory( CompositeContext compositeContext ) { + ExtensionPointRegistry registry = compositeContext.getExtensionPointRegistry(); + FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class); + return (RuntimeAssemblyFactory)modelFactories.getFactory(AssemblyFactory.class); + } // end method RuntimeAssemblyFactory + + /** + * Applies an AsyncResponseHandlerImpl as the implementation of a RuntimeComponent + * - the AsyncResponseHandlerImpl acts as both the implementation class and the implementation provider... + * @param component - the component + */ + private void applyImplementation( RuntimeComponent component ) { + AsyncResponseHandlerImpl<?> asyncHandler = new AsyncResponseHandlerImpl<Object>(); + component.setImplementation( asyncHandler ); + component.setImplementationProvider( asyncHandler ); + return; + } // end method getImplementationProvider + + private static QName ASYNC_INVOKE = new QName( Constants.SCA11_NS, "asyncInvocation" ); + /** + * Determines if the service invocation is asynchronous + * @param source - the EPR involved in the invocation + * @return - true if the invocation is async + */ + private boolean isAsyncInvocation( Invocable source ) { + if( !(source instanceof RuntimeEndpointReference) ) return false; + RuntimeEndpointReference epr = (RuntimeEndpointReference) source; + // First check is to see if the EPR itself has the asyncInvocation intent marked + for( Intent intent : epr.getRequiredIntents() ) { + if ( intent.getName().equals(ASYNC_INVOKE) ) return true; + } // end for + + // Second check is to see if the target service has the asyncInvocation intent marked + Endpoint ep = epr.getTargetEndpoint(); + for( Intent intent : ep.getRequiredIntents() ) { + if ( intent.getName().equals(ASYNC_INVOKE) ) return true; + } // end for + return false; + } // end isAsyncInvocation + + /** + * Return the synchronous method that is the equivalent of an async method + * @param asyncMethod - the async method + * @return - the equivalent synchronous method + */ + protected Method getNonAsyncMethod(Method asyncMethod) { + String methodName = asyncMethod.getName().substring(0, asyncMethod.getName().length()-5); + for (Method m : businessInterface.getMethods()) { + if (methodName.equals(m.getName())) { + return m; + } + } + throw new IllegalStateException("No synchronous method matching async method " + asyncMethod.getName()); + } // end method getNonAsyncMethod + + /** + * Gets the classloader of the business interface + * @return + */ + private ClassLoader getInterfaceClassloader( ) { + return businessInterface.getClassLoader(); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponse.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponse.java new file mode 100644 index 0000000000..7b459f3e7d --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponse.java @@ -0,0 +1,68 @@ +/* + * 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.core.invocation.impl; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import javax.xml.ws.Response; + +public class AsyncResponse implements Response { + + private Object response; + private boolean isException; + + public AsyncResponse(Object response, boolean isException) { + this.response = response; + this.isException = isException; + } + + public Map getContext() { + return new HashMap(); + } + + public boolean cancel(boolean mayInterruptIfRunning) { + return false; + } + + public Object get() throws InterruptedException, ExecutionException { + if (isException) { + throw new ExecutionException((Throwable)response); + } else { + return response; + } + } + + public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + return get(); + } + + public boolean isCancelled() { + return false; + } + + public boolean isDone() { + return true; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponseHandlerImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponseHandlerImpl.java new file mode 100644 index 0000000000..8d56088c44 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponseHandlerImpl.java @@ -0,0 +1,193 @@ +/* + * 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.core.invocation.impl; + +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.Implementation; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.assembly.Service; +import org.apache.tuscany.sca.core.invocation.AsyncFaultWrapper; +import org.apache.tuscany.sca.core.invocation.AsyncResponseHandler; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.policy.ExtensionType; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; + +/** + * A class intended to form the final link in the chain calling into a Future which represents + * the response to an asynchronous service invocation + * + * Most methods are dummies, required to fulfil the contracts for ImplementationProvider, Implementation + * and Invoker, since this class collapses together the functions of these separate interfaces, due to its + * specialized nature, where most of the function will never be used. + * + * The class acts as the implementation object that terminates the chain - and also as the provider of the implementation. + * The class accepts Future objects which represent individual invocations of forward operations on the async service + * and expects that the responses it handles as invocations will carry the unique ID of one of the Future objects in the + * message header. On receipt of each message, the class seeks out the Future with that unique ID and completes the future + * either with a response message or with a Fault. + * + * @param <V> + */ +public class AsyncResponseHandlerImpl<V> implements AsyncResponseHandler<V>, + ImplementationProvider, Implementation, Invoker { + + private ConcurrentHashMap< String, AsyncInvocationFutureImpl<?> > table = + new ConcurrentHashMap< String, AsyncInvocationFutureImpl<?> >(); + + /** + * This class is its own invoker... + */ + public Invoker createInvoker(RuntimeComponentService service, + Operation operation) { + return this; + } + + /** + * Add a future to this response handler + * @param future - the future + */ + public void addFuture( AsyncInvocationFutureImpl<?> future ) { + // The Future is stored in the table indexed by its unique ID + table.put(future.getUniqueID(), future); + } // end method addFuture + + public boolean supportsOneWayInvocation() { + return true; + } + + public void start() {} + + public void stop() {} + + public List<Operation> getOperations() { + return null; + } + + public QName getType() { + return null; + } + + public List<Property> getProperties() { + return null; + } + + public Property getProperty(String name) { + return null; + } + + public Reference getReference(String name) { + return null; + } + + public List<Reference> getReferences() { + return null; + } + + public Service getService(String name) { + return null; + } + + public List<Service> getServices() { + return null; + } + + public String getURI() { + return null; + } + + public void setURI(String uri) {} + + public boolean isUnresolved() { + return false; + } + + public void setUnresolved(boolean unresolved) {} + + public ExtensionType getExtensionType() { + return null; + } + + public List<PolicySet> getPolicySets() { + return null; + } + + public List<Intent> getRequiredIntents() { + return null; + } + + public void setExtensionType(ExtensionType type) {} + + public void setFault(AsyncFaultWrapper e) {} + + public void setResponse(V res) { } + + /** + * Method which is the termination for the invocation chain from the callback endpoint + * @param msg - the Tuscany message containing the response from the async service invocation + * which is either the Response message or an exception of some kind + */ + private static final String WS_MESSAGE_ID = "WS_MESSAGE_ID"; + public Message invoke(Message msg) { + // Get the unique ID from the message header + String idValue = (String)msg.getHeaders().get(WS_MESSAGE_ID); + if( idValue == null ) { + System.out.println( "Async message ID not found "); + } else { + // Fetch the Future with that Unique ID + AsyncInvocationFutureImpl future = table.get(idValue); + if( future == null ) { + System.out.println("Future not found for id: " + idValue); + } else { + // Complete the Future with a Response message + Object payload = msg.getBody(); + Object response; + if( payload == null ) { + System.out.println("Returned response message was null"); + } else { + if (payload.getClass().isArray()) { + response = ((Object[])payload)[0]; + } else { + response = payload; + } // end if + if( response.getClass().equals(AsyncFaultWrapper.class)) { + future.setFault((AsyncFaultWrapper) response ); + } else { + future.setResponse(response); + } // end if + } // end if + } // end if + } // end if + + // Prepare an empty response message + msg.setBody(null); + return msg; + } // end method invoke + +} // end class diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImpl.java new file mode 100644 index 0000000000..8569af0de8 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImpl.java @@ -0,0 +1,208 @@ +/* + * 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.core.invocation.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.DataExchangeSemantics; +import org.apache.tuscany.sca.invocation.Interceptor; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Phase; +import org.apache.tuscany.sca.invocation.PhasedInterceptor; + +/** + * Default implementation of an invocation chain + * + * @version $Rev$ $Date$ + */ +public class InvocationChainImpl implements InvocationChain { + private Operation sourceOperation; + private Operation targetOperation; + private List<Node> nodes = new ArrayList<Node>(); + + private final PhaseManager phaseManager; + private boolean forReference; + private boolean allowsPassByReference; + + public InvocationChainImpl(Operation sourceOperation, Operation targetOperation, boolean forReference, PhaseManager phaseManager) { + this.targetOperation = targetOperation; + this.sourceOperation = sourceOperation; + this.forReference = forReference; + this.phaseManager = phaseManager; + } + + public Operation getTargetOperation() { + return targetOperation; + } + + public void setTargetOperation(Operation operation) { + this.targetOperation = operation; + } + + public void addInterceptor(Interceptor interceptor) { + if (interceptor instanceof PhasedInterceptor) { + PhasedInterceptor pi = (PhasedInterceptor)interceptor; + if (pi.getPhase() != null) { + addInvoker(pi.getPhase(), pi); + return; + } + } + String phase = forReference ? Phase.REFERENCE : Phase.SERVICE; + addInterceptor(phase, interceptor); + } + + public void addInvoker(Invoker invoker) { + if (invoker instanceof PhasedInterceptor) { + PhasedInterceptor pi = (PhasedInterceptor)invoker; + if (pi.getPhase() != null) { + addInvoker(pi.getPhase(), pi); + return; + } + } + String phase = forReference ? Phase.REFERENCE_BINDING : Phase.IMPLEMENTATION; + addInvoker(phase, invoker); + } + + public Invoker getHeadInvoker() { + return nodes.isEmpty() ? null : nodes.get(0).getInvoker(); + } + + public Invoker getHeadInvoker(String phase) { + int index = phaseManager.getAllPhases().indexOf(phase); + if (index == -1) { + throw new IllegalArgumentException("Invalid phase name: " + phase); + } + for (Node node : nodes) { + if (index <= node.getPhaseIndex()) { + return node.getInvoker(); + } + } + return null; + } + + /** + * @return the sourceOperation + */ + public Operation getSourceOperation() { + return sourceOperation; + } + + /** + * @param sourceOperation the sourceOperation to set + */ + public void setSourceOperation(Operation sourceOperation) { + this.sourceOperation = sourceOperation; + } + + public void addInterceptor(String phase, Interceptor interceptor) { + addInvoker(phase, interceptor); + } + + private void addInvoker(String phase, Invoker invoker) { + int index = phaseManager.getAllPhases().indexOf(phase); + if (index == -1) { + throw new IllegalArgumentException("Invalid phase name: " + phase); + } + Node node = new Node(index, invoker); + ListIterator<Node> li = nodes.listIterator(); + Node before = null, after = null; + boolean found = false; + while (li.hasNext()) { + before = after; + after = li.next(); + if (after.getPhaseIndex() > index) { + // Move back + li.previous(); + li.add(node); + found = true; + break; + } + } + if (!found) { + // Add to the end + nodes.add(node); + before = after; + after = null; + } + + // Relink the interceptors + if (before != null) { + if (before.getInvoker() instanceof Interceptor) { + ((Interceptor)before.getInvoker()).setNext(invoker); + } + } + if (after != null) { + if (invoker instanceof Interceptor) { + ((Interceptor)invoker).setNext(after.getInvoker()); + } + } + + } + + public boolean allowsPassByReference() { + if (allowsPassByReference) { + // No need to check the invokers + return true; + } + // Check if any of the invokers allows pass-by-reference + boolean allowsPBR = false; + for (Node i : nodes) { + if (i.getInvoker() instanceof DataExchangeSemantics) { + if (((DataExchangeSemantics)i.getInvoker()).allowsPassByReference()) { + allowsPBR = true; + break; + } + } + } + return allowsPBR; + } + + public void setAllowsPassByReference(boolean allowsPBR) { + this.allowsPassByReference = allowsPBR; + } + + private static class Node { + private int phaseIndex; + private Invoker invoker; + + public Node(int phaseIndex, Invoker invoker) { + super(); + this.phaseIndex = phaseIndex; + this.invoker = invoker; + } + + public int getPhaseIndex() { + return phaseIndex; + } + + public Invoker getInvoker() { + return invoker; + } + + @Override + public String toString() { + return "(" + phaseIndex + ")" + invoker; + } + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKCallbackInvocationHandler.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKCallbackInvocationHandler.java new file mode 100644 index 0000000000..168af952db --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKCallbackInvocationHandler.java @@ -0,0 +1,77 @@ +/* + * 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.core.invocation.impl; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.core.context.impl.CallbackServiceReferenceImpl; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; +import org.oasisopen.sca.ServiceReference; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * Responsible for dispatching to a callback through a wire. <p/> TODO cache + * target invoker + * + * @version $Rev$ $Date$ + */ +public class JDKCallbackInvocationHandler extends JDKInvocationHandler { + private static final long serialVersionUID = -3350283555825935609L; + + public JDKCallbackInvocationHandler(MessageFactory messageFactory, ServiceReference<?> ref) { + super(messageFactory, ref); + this.fixedWire = false; + } + + @Override + @SuppressWarnings( {"unchecked"}) + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + + if (Object.class == method.getDeclaringClass()) { + return invokeObjectMethod(method, args); + } + + // obtain a dedicated wire to be used for this callback invocation + RuntimeEndpointReference wire = ((CallbackServiceReferenceImpl)callableReference).getCallbackEPR(); + if (wire == null) { + //FIXME: need better exception + throw new ServiceRuntimeException("No callback wire found"); + } + + setEndpoint(((CallbackServiceReferenceImpl)callableReference).getResolvedEndpoint()); + + InvocationChain chain = getInvocationChain(method, wire); + if (chain == null) { + throw new IllegalArgumentException("No matching operation is found: " + method); + } + + try { + return invoke(chain, args, wire); + } catch (InvocationTargetException e) { + Throwable t = e.getCause(); + throw t; + } finally { + // allow the cloned wire to be reused by subsequent callbacks + } + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKInvocationHandler.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKInvocationHandler.java new file mode 100644 index 0000000000..d0095f45ee --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKInvocationHandler.java @@ -0,0 +1,311 @@ +/* + * 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.core.invocation.impl; + +import java.io.Serializable; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.context.ThreadMessageContext; +import org.apache.tuscany.sca.core.context.ServiceReferenceExt; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaOperation; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.runtime.Invocable; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; +import org.oasisopen.sca.ServiceReference; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * @version $Rev$ $Date$ + */ +public class JDKInvocationHandler implements InvocationHandler, Serializable { + private static final long serialVersionUID = -3366410500152201371L; + + protected MessageFactory messageFactory; + protected Endpoint target; + protected Invocable source; + protected ServiceReferenceExt<?> callableReference; + protected Class<?> businessInterface; + + protected boolean fixedWire = true; + + protected transient Map<Method, InvocationChain> chains = new IdentityHashMap<Method, InvocationChain>(); + + public JDKInvocationHandler(MessageFactory messageFactory, Class<?> businessInterface, Invocable source) { + this.messageFactory = messageFactory; + this.source = source; + this.businessInterface = businessInterface; + } + + public JDKInvocationHandler(MessageFactory messageFactory, ServiceReference<?> callableReference) { + this.messageFactory = messageFactory; + this.callableReference = (ServiceReferenceExt<?>)callableReference; + if (callableReference != null) { + this.businessInterface = callableReference.getBusinessInterface(); + this.source = (RuntimeEndpointReference) this.callableReference.getEndpointReference(); + } + } + + + public Class<?> getBusinessInterface() { + return businessInterface; + } + + protected Object getCallbackID() { + return null; + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if (Object.class == method.getDeclaringClass()) { + return invokeObjectMethod(method, args); + } + if (source == null) { + throw new ServiceRuntimeException("No runtime source is available"); + } + + if (source instanceof RuntimeEndpointReference) { + RuntimeEndpointReference epr = (RuntimeEndpointReference)source; + if (epr.isOutOfDate()) { + epr.rebuild(); + chains.clear(); + } + } + + InvocationChain chain = getInvocationChain(method, source); + + if (chain == null) { + throw new IllegalArgumentException("No matching operation is found: " + method); + } + + // send the invocation down the source + Object result = invoke(chain, args, source); + + return result; + } + + /** + * Handle the methods on the Object.class + * @param method + * @param args + */ + protected Object invokeObjectMethod(Method method, Object[] args) throws Throwable { + String name = method.getName(); + if ("toString".equals(name)) { + return "[Proxy - " + toString() + "]"; + } else if ("equals".equals(name)) { + Object obj = args[0]; + if (obj == null) { + return false; + } + if (!Proxy.isProxyClass(obj.getClass())) { + return false; + } + return equals(Proxy.getInvocationHandler(obj)); + } else if ("hashCode".equals(name)) { + return hashCode(); + } else { + return method.invoke(this); + } + } + + /** + * Determines if the given operation matches the given method + * + * @return true if the operation matches, false if does not + */ + // FIXME: Should it be in the InterfaceContractMapper? + @SuppressWarnings("unchecked") + private static boolean match(Operation operation, Method method) { + if (operation instanceof JavaOperation) { + JavaOperation javaOp = (JavaOperation)operation; + Method m = javaOp.getJavaMethod(); + if (!method.getName().equals(m.getName())) { + return false; + } + if (method.equals(m)) { + return true; + } + } else { + if (!method.getName().equals(operation.getName())) { + return false; + } + } + + // For remotable interface, operation is not overloaded. + if (operation.getInterface().isRemotable()) { + return true; + } + + Class<?>[] params = method.getParameterTypes(); + + DataType<List<DataType>> inputType = null; + if (operation.isWrapperStyle()) { + inputType = operation.getWrapper().getUnwrappedInputType(); + } else { + inputType = operation.getInputType(); + } + List<DataType> types = inputType.getLogical(); + boolean matched = true; + if (types.size() == params.length && method.getName().equals(operation.getName())) { + for (int i = 0; i < params.length; i++) { + Class<?> clazz = params[i]; + Class<?> type = types.get(i).getPhysical(); + // Object.class.isAssignableFrom(int.class) returns false + if (type != Object.class && (!type.isAssignableFrom(clazz))) { + matched = false; + } + } + } else { + matched = false; + } + return matched; + + } + + protected synchronized InvocationChain getInvocationChain(Method method, Invocable source) { + if (source instanceof RuntimeEndpoint) { + InvocationChain invocationChain = source.getBindingInvocationChain(); + for (InvocationChain chain : source.getInvocationChains()) { + Operation operation = chain.getTargetOperation(); + if (method.getName().equals(operation.getName())) { + invocationChain.setTargetOperation(operation); + } + } + return source.getBindingInvocationChain(); + } + if (fixedWire && chains.containsKey(method)) { + return chains.get(method); + } + InvocationChain found = null; + for (InvocationChain chain : source.getInvocationChains()) { + Operation operation = chain.getSourceOperation(); + if (operation.isDynamic()) { + operation.setName(method.getName()); + found = chain; + break; + } else if (match(operation, method)) { + found = chain; + break; + } + } + if (fixedWire) { + chains.put(method, found); + } + return found; + } + + protected void setEndpoint(Endpoint endpoint) { + this.target = endpoint; + } + + protected Object invoke(InvocationChain chain, Object[] args, Invocable source) + throws Throwable { + return invoke( chain, args, source, null ); + } + + /** + * Invoke the chain + * @param chain - the chain + * @param args - arguments to the invocation as an array of Objects + * @param source - the Endpoint or EndpointReference to which the chain relates + * @param msgID - an ID for the message being sent, may be null + * @return - the Response message from the invocation + * @throws Throwable - if any exception occurs during the invocation + */ + protected Object invoke(InvocationChain chain, Object[] args, Invocable source, String msgID) + throws Throwable { + Message msg = messageFactory.createMessage(); + if (source instanceof RuntimeEndpointReference) { + msg.setFrom((RuntimeEndpointReference)source); + } + if (target != null) { + msg.setTo(target); + } else { + if (source instanceof RuntimeEndpointReference) { + msg.setTo(((RuntimeEndpointReference)source).getTargetEndpoint()); + } + } + Invoker headInvoker = chain.getHeadInvoker(); + Operation operation = chain.getTargetOperation(); + msg.setOperation(operation); + msg.setBody(args); + + Message msgContext = ThreadMessageContext.getMessageContext(); + + // Deal with header information that needs to be copied from the message context to the new message... + transferMessageHeaders( msg, msgContext); + + ThreadMessageContext.setMessageContext(msg); + + // If there is a supplied message ID, place its value into the Message Header under "MESSAGE_ID" + if( msgID != null ){ + msg.getHeaders().put("MESSAGE_ID", msgID); + } // end if + + try { + // dispatch the source down the chain and get the response + Message resp = headInvoker.invoke(msg); + Object body = resp.getBody(); + if (resp.isFault()) { + throw (Throwable)body; + } + return body; + } finally { + ThreadMessageContext.setMessageContext(msgContext); + } + } + + /** + * Transfer relevant header information from the old message (incoming) to the new message (outgoing) + * @param newMsg + * @param oldMsg + */ + private void transferMessageHeaders( Message newMsg, Message oldMsg ) { + if( oldMsg == null ) return; + // For the present, simply copy all the headers + if( !oldMsg.getHeaders().isEmpty() ) newMsg.getHeaders().putAll( oldMsg.getHeaders() ); + } // end transferMessageHeaders + + /** + * @return the callableReference + */ + public ServiceReference<?> getCallableReference() { + return callableReference; + } + + /** + * @param callableReference the callableReference to set + */ + public void setCallableReference(ServiceReference<?> callableReference) { + this.callableReference = (ServiceReferenceExt<?>)callableReference; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java new file mode 100644 index 0000000000..a162110835 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java @@ -0,0 +1,202 @@ +/* + * 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.core.invocation.impl; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.List; +import java.util.concurrent.Future; + +import javax.xml.ws.AsyncHandler; +import javax.xml.ws.Response; + +import org.apache.tuscany.sca.common.java.collection.LRUCache; +import org.apache.tuscany.sca.core.LifeCycleListener; +import org.apache.tuscany.sca.core.context.ServiceReferenceExt; +import org.apache.tuscany.sca.core.context.impl.CallbackServiceReferenceImpl; +import org.apache.tuscany.sca.core.context.impl.ServiceReferenceImpl; +import org.apache.tuscany.sca.core.invocation.ProxyCreationException; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.runtime.Invocable; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.oasisopen.sca.ServiceReference; +import org.oasisopen.sca.ServiceRuntimeException; + + +/** + * the default implementation of a wire service that uses JDK dynamic proxies + * + * @version $Rev$ $Date$ + */ +public class JDKProxyFactory implements ProxyFactory, LifeCycleListener { + protected InterfaceContractMapper contractMapper; + private MessageFactory messageFactory; + + public JDKProxyFactory(MessageFactory messageFactory, InterfaceContractMapper mapper) { + this.contractMapper = mapper; + this.messageFactory = messageFactory; + } + + /** + * The original createProxy method assumes that the proxy doesn't want to + * share conversation state so sets the conversation object to null + */ + public <T> T createProxy(final Class<T> interfaze, Invocable invocable) throws ProxyCreationException { + if (invocable instanceof RuntimeEndpoint) { + InvocationHandler handler; + if (isAsync(interfaze)) { + handler = new AsyncJDKInvocationHandler(messageFactory, interfaze, invocable); + } else { + handler = new JDKInvocationHandler(messageFactory, interfaze, invocable); + } + // Allow privileged access to class loader. Requires RuntimePermission in security policy. + ClassLoader cl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { + public ClassLoader run() { + return interfaze.getClassLoader(); + } + }); + T proxy = interfaze.cast(newProxyInstance(cl, new Class[] {interfaze}, handler)); + return proxy; + } + ServiceReference<T> serviceReference = new ServiceReferenceImpl<T>(interfaze, invocable, null); + return createProxy(serviceReference); + } + + public <T> T createProxy(ServiceReference<T> callableReference) throws ProxyCreationException { + assert callableReference != null; + final Class<T> interfaze = callableReference.getBusinessInterface(); + InvocationHandler handler; + if (isAsync(interfaze)) { + handler = new AsyncJDKInvocationHandler(messageFactory, callableReference); + } else { + handler = new JDKInvocationHandler(messageFactory, callableReference); + } + // Allow privileged access to class loader. Requires RuntimePermission in security policy. + ClassLoader cl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { + public ClassLoader run() { + return interfaze.getClassLoader(); + } + }); + T proxy = interfaze.cast(newProxyInstance(cl, new Class[] {interfaze}, handler)); + ((ServiceReferenceExt<T>)callableReference).setProxy(proxy); + return proxy; + } + + private boolean isAsync(Class<?> interfaze) { + for (Method method : interfaze.getMethods()) { + if (method.getName().endsWith("Async")) { + if (method.getReturnType().isAssignableFrom(Future.class)) { + if (method.getParameterTypes().length > 0) { + if (method.getParameterTypes()[method.getParameterTypes().length-1].isAssignableFrom(AsyncHandler.class)) { + return true; + } + } + } + if (method.getReturnType().isAssignableFrom(Response.class)) { + return true; + } + } + } + return false; + } + + public <T> T createCallbackProxy(Class<T> interfaze, List<? extends Invocable> wires) throws ProxyCreationException { + ServiceReferenceImpl<T> callbackReference = null; + try { + callbackReference = new CallbackServiceReferenceImpl(interfaze, wires); + } catch (ServiceRuntimeException e) { + // [rfeng] In case that the call is not from a bidirectional interface, the field should be injected with null + callbackReference = null; + } + return callbackReference != null ? createCallbackProxy(callbackReference) : null; + } + + public <T> T createCallbackProxy(ServiceReference<T> callbackReference) throws ProxyCreationException { + assert callbackReference != null; + Class<T> interfaze = callbackReference.getBusinessInterface(); + InvocationHandler handler = new JDKCallbackInvocationHandler(messageFactory, callbackReference); + ClassLoader cl = interfaze.getClassLoader(); + T proxy = interfaze.cast(newProxyInstance(cl, new Class[] {interfaze}, handler)); + ((ServiceReferenceExt<T>) callbackReference).setProxy(proxy); + return proxy; + } + + public <B, R extends ServiceReference<B>> R cast(B target) throws IllegalArgumentException { + InvocationHandler handler = Proxy.getInvocationHandler(target); + if (handler instanceof JDKInvocationHandler) { + return (R)((JDKInvocationHandler)handler).getCallableReference(); + } else { + throw new IllegalArgumentException("The object is not a known proxy."); + } + } + + /** + * @see org.apache.tuscany.sca.core.invocation.ProxyFactory#isProxyClass(java.lang.Class) + */ + public boolean isProxyClass(Class<?> clazz) { + return Proxy.isProxyClass(clazz); + } + + // This is a cache containing the proxy class constructor for each business interface. + // This improves performance compared to calling Proxy.newProxyInstance() + // every time that a proxy is needed. + private final LRUCache<Class<?>, Constructor<?>> cache = new LRUCache<Class<?>, Constructor<?>>(512); + + public Object newProxyInstance(ClassLoader classloader, + Class<?> interfaces[], + InvocationHandler invocationhandler) throws IllegalArgumentException { + if (interfaces.length > 1) { + // We only cache the proxy constructors with one single interface which the case in SCA where + // one reference can have one interface + return Proxy.newProxyInstance(classloader, interfaces, invocationhandler); + } + try { + if (invocationhandler == null) + throw new NullPointerException("InvocationHandler is null"); + // Lookup cached constructor. aclass[0] is the reference's business interface. + Constructor<?> proxyCTOR; + synchronized (cache) { + proxyCTOR = cache.get(interfaces[0]); + } + if (proxyCTOR == null) { + Class<?> proxyClass = Proxy.getProxyClass(classloader, interfaces); + proxyCTOR = proxyClass.getConstructor(InvocationHandler.class); + synchronized (cache) { + cache.put(interfaces[0], proxyCTOR); + } + } + return proxyCTOR.newInstance(invocationhandler); + } catch (Throwable e) { + throw new IllegalArgumentException(e); + } + } + + public void start() { + } + + public void stop() { + cache.clear(); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageFactoryImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageFactoryImpl.java new file mode 100644 index 0000000000..6ce2ffca21 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageFactoryImpl.java @@ -0,0 +1,36 @@ +/* + * 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.core.invocation.impl; + +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.invocation.MessageFactory; + +/** + * Implementation of MessageFactory. + * + * @version $Rev$ $Date$ + */ +public class MessageFactoryImpl implements MessageFactory { + + public Message createMessage() { + return new MessageImpl(); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageImpl.java new file mode 100644 index 0000000000..cc8cb48cc5 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/MessageImpl.java @@ -0,0 +1,114 @@ +/* + * 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.core.invocation.impl; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.Message; + +/** + * The default implementation of a message flowed through a wire during an invocation + * + * @version $Rev $Date$ + */ +public class MessageImpl implements Message { + private Map<String, Object> headers = new HashMap<String, Object>(); + private Object body; + private Object messageID; + private boolean isFault; + private Operation operation; + + private EndpointReference from; + private Endpoint to; + + private Object bindingContext; + + public MessageImpl() { + this.from = null; + this.to = null; + } + + @SuppressWarnings("unchecked") + public <T> T getBody() { + return (T)body; + } + + public <T> void setBody(T body) { + this.isFault = false; + this.body = body; + } + + public Object getMessageID() { + return messageID; + } + + public void setMessageID(Object messageId) { + this.messageID = messageId; + } + + public boolean isFault() { + return isFault; + } + + public void setFaultBody(Object fault) { + this.isFault = true; + this.body = fault; + } + + public EndpointReference getFrom() { + return from; + } + + public void setFrom(EndpointReference from) { + this.from = from; + } + + public Endpoint getTo() { + return to; + } + + public void setTo(Endpoint to) { + this.to = to; + } + + public Operation getOperation() { + return operation; + } + + public void setOperation(Operation op) { + this.operation = op; + } + + public Map<String, Object> getHeaders() { + return headers; + } + + @SuppressWarnings("unchecked") + public <T> T getBindingContext() { + return (T)bindingContext; + } + + public <T> void setBindingContext(T bindingContext) { + this.bindingContext = bindingContext; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/NoMethodForOperationException.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/NoMethodForOperationException.java new file mode 100644 index 0000000000..45f4bf52bf --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/NoMethodForOperationException.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.invocation.impl; + +import org.apache.tuscany.sca.core.invocation.ProxyCreationException; + + +/** + * Thrown when an {@link org.apache.tuscany.sca.core.factory.model.Operation} cannot be mapped to a method on an interface + * @version $Rev$ $Date$ + */ +public class NoMethodForOperationException extends ProxyCreationException { + private static final long serialVersionUID = 5116536602309483679L; + + public NoMethodForOperationException() { + } + + public NoMethodForOperationException(String message) { + super(message); + } + + public NoMethodForOperationException(String message, Throwable cause) { + super(message, cause); + } + + public NoMethodForOperationException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManager.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManager.java new file mode 100644 index 0000000000..85ef79b5d7 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManager.java @@ -0,0 +1,313 @@ +/* + * 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.core.invocation.impl; + +import static org.apache.tuscany.sca.invocation.Phase.IMPLEMENTATION; +import static org.apache.tuscany.sca.invocation.Phase.IMPLEMENTATION_POLICY; +import static org.apache.tuscany.sca.invocation.Phase.REFERENCE; +import static org.apache.tuscany.sca.invocation.Phase.REFERENCE_BINDING; +import static org.apache.tuscany.sca.invocation.Phase.REFERENCE_BINDING_POLICY; +import static org.apache.tuscany.sca.invocation.Phase.REFERENCE_BINDING_TRANSPORT; +import static org.apache.tuscany.sca.invocation.Phase.REFERENCE_BINDING_WIREFORMAT; +import static org.apache.tuscany.sca.invocation.Phase.REFERENCE_INTERFACE; +import static org.apache.tuscany.sca.invocation.Phase.REFERENCE_POLICY; +import static org.apache.tuscany.sca.invocation.Phase.SERVICE; +import static org.apache.tuscany.sca.invocation.Phase.SERVICE_BINDING; +import static org.apache.tuscany.sca.invocation.Phase.SERVICE_BINDING_OPERATION_SELECTOR; +import static org.apache.tuscany.sca.invocation.Phase.SERVICE_BINDING_POLICY; +import static org.apache.tuscany.sca.invocation.Phase.SERVICE_BINDING_TRANSPORT; +import static org.apache.tuscany.sca.invocation.Phase.SERVICE_BINDING_WIREFORMAT; +import static org.apache.tuscany.sca.invocation.Phase.SERVICE_INTERFACE; +import static org.apache.tuscany.sca.invocation.Phase.SERVICE_POLICY; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.extensibility.ServiceDeclaration; +import org.apache.tuscany.sca.invocation.Phase; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * @version $Rev$ $Date$ + */ +public class PhaseManager { + private static final Logger log = Logger.getLogger(PhaseManager.class.getName()); + + public static final String STAGE_REFERENCE = "reference"; + public static final String STAGE_REFERENCE_BINDING = "reference.binding"; + public static final String STAGE_SERVICE_BINDING = "service.binding"; + public static final String STAGE_SERVICE = "service"; + public static final String STAGE_IMPLEMENTATION = "implementation"; + + private static final String[] SYSTEM_REFERENCE_PHASES = + {REFERENCE, REFERENCE_POLICY, REFERENCE_INTERFACE, REFERENCE_BINDING}; + + private static final String[] SYSTEM_REFERENCE_BINDING_PHASES = + {REFERENCE_BINDING_WIREFORMAT, REFERENCE_BINDING_POLICY, REFERENCE_BINDING_TRANSPORT}; + + private static final String[] SYSTEM_SERVICE_BINDING_PHASES = + {SERVICE_BINDING_TRANSPORT, SERVICE_BINDING_OPERATION_SELECTOR, SERVICE_BINDING_WIREFORMAT, SERVICE_BINDING_POLICY}; + + private static final String[] SYSTEM_SERVICE_PHASES = + {SERVICE_BINDING, SERVICE_INTERFACE, SERVICE_POLICY, SERVICE}; + + private static final String[] SYSTEM_IMPLEMENTATION_PHASES = {IMPLEMENTATION_POLICY, IMPLEMENTATION}; + + private ExtensionPointRegistry registry; + private String pattern = Phase.class.getName(); + private Map<String, Stage> stages; + private List<String> phases; + + public class Stage { + private String name; + private PhaseSorter<String> sorter = new PhaseSorter<String>(); + private Set<String> firstSet = new HashSet<String>(); + private Set<String> lastSet = new HashSet<String>(); + private List<String> phases = new ArrayList<String>(); + + public Stage(String name) { + super(); + this.name = name; + } + + public String getName() { + return name; + } + + public PhaseSorter<String> getSorter() { + return sorter; + } + + public Set<String> getFirstSet() { + return firstSet; + } + + public Set<String> getLastSet() { + return lastSet; + } + + public List<String> getPhases() { + return phases; + } + + @Override + public String toString() { + return name + phases; + } + } + + /** + * @param registry + */ + public PhaseManager(ExtensionPointRegistry registry) { + super(); + this.registry = registry; + } + + public static PhaseManager getInstance(ExtensionPointRegistry registry) { + UtilityExtensionPoint utilityExtensionPoint = registry.getExtensionPoint(UtilityExtensionPoint.class); + return utilityExtensionPoint.getUtility(PhaseManager.class); + } + + // For unit test purpose + PhaseManager(String pattern) { + super(); + this.pattern = pattern; + this.registry = new DefaultExtensionPointRegistry(); + } + + private List<String> getPhases(String stage) { + Stage s = getStages().get(stage); + return s == null ? null : s.getPhases(); + } + + public List<String> getReferencePhases() { + return getPhases(STAGE_REFERENCE); + } + + public List<String> getServicePhases() { + return getPhases(STAGE_SERVICE); + } + + public List<String> getReferenceBindingPhases() { + return getPhases(STAGE_REFERENCE_BINDING); + } + + public List<String> getServiceBindingPhases() { + return getPhases(STAGE_SERVICE_BINDING); + } + + public List<String> getImplementationPhases() { + return getPhases(STAGE_IMPLEMENTATION); + } + + public synchronized List<String> getAllPhases() { + if (phases == null) { + phases = new ArrayList<String>(); + phases.addAll(getReferencePhases()); + phases.addAll(getReferenceBindingPhases()); + phases.addAll(getServiceBindingPhases()); + phases.addAll(getServicePhases()); + phases.addAll(getImplementationPhases()); + } + return phases; + } + + public synchronized Map<String, Stage> getStages() { + if (stages != null) { + return stages; + } + init(); + + Collection<ServiceDeclaration> services; + try { + services = registry.getServiceDiscovery().getServiceDeclarations(pattern); + } catch (IOException e) { + throw new ServiceRuntimeException(e); + } + + for (ServiceDeclaration d : services) { + if (log.isLoggable(Level.FINE)) { + log.fine(d.getLocation() + ": " + d.getAttributes()); + } + String name = d.getAttributes().get("name"); + if (name == null) { + throw new ServiceRuntimeException("Required attribute 'name' is missing."); + } + String stageName = d.getAttributes().get("stage"); + if (stageName == null) { + throw new ServiceRuntimeException("Required attribute 'stage' is missing."); + } + Stage stage = stages.get(stageName); + if (stage == null) { + throw new ServiceRuntimeException("Invalid stage: " + stageName); + } + PhaseSorter<String> graph = stage.getSorter(); + Set<String> firstSet = stage.getFirstSet(), lastSet = stage.getLastSet(); + + String before = d.getAttributes().get("before"); + String after = d.getAttributes().get("after"); + if (before != null) { + StringTokenizer tokenizer = new StringTokenizer(before); + while (tokenizer.hasMoreTokens()) { + String p = tokenizer.nextToken(); + if (!"*".equals(p)) { + graph.addEdge(name, p); + } else { + firstSet.add(name); + } + } + } + if (after != null) { + StringTokenizer tokenizer = new StringTokenizer(after); + while (tokenizer.hasMoreTokens()) { + String p = tokenizer.nextToken(); + if (!"*".equals(p)) { + graph.addEdge(p, name); + } else { + lastSet.add(name); + } + } + } + graph.addVertext(name); + if(firstSet.size()>1) { + log.warning("More than one phases are declared to be first: "+firstSet); + } + for (String s : firstSet) { + for (String v : new HashSet<String>(graph.getVertices().keySet())) { + if (!firstSet.contains(v)) { + graph.addEdge(s, v); + } + } + } + if(lastSet.size()>1) { + log.warning("More than one phases are declared to be the last: "+lastSet); + } + for (String s : lastSet) { + for (String v : new HashSet<String>(graph.getVertices().keySet())) { + if (!lastSet.contains(v)) { + graph.addEdge(v, s); + } + } + } + + } + + for (Stage s : stages.values()) { + List<String> phases = s.getSorter().topologicalSort(false); + s.getPhases().clear(); + s.getPhases().addAll(phases); + } + if (log.isLoggable(Level.FINE)) { + log.fine("Stages: " + stages); + } + return stages; + } + + private void init() { + stages = new HashMap<String, Stage>(); + + Stage referenceStage = new Stage(STAGE_REFERENCE); + for (int i = 1; i < SYSTEM_REFERENCE_PHASES.length; i++) { + referenceStage.getSorter().addEdge(SYSTEM_REFERENCE_PHASES[i - 1], SYSTEM_REFERENCE_PHASES[i]); + } + referenceStage.getLastSet().add(REFERENCE_BINDING); + stages.put(referenceStage.getName(), referenceStage); + + Stage referenceBindingStage = new Stage(STAGE_REFERENCE_BINDING); + for (int i = 1; i < SYSTEM_REFERENCE_BINDING_PHASES.length; i++) { + referenceBindingStage.getSorter().addEdge(SYSTEM_REFERENCE_BINDING_PHASES[i - 1], SYSTEM_REFERENCE_BINDING_PHASES[i]); + } + stages.put(referenceBindingStage.getName(), referenceBindingStage); + + Stage serviceBindingStage = new Stage(STAGE_SERVICE_BINDING); + for (int i = 1; i < SYSTEM_SERVICE_BINDING_PHASES.length; i++) { + serviceBindingStage.getSorter().addEdge(SYSTEM_SERVICE_BINDING_PHASES[i - 1], SYSTEM_SERVICE_BINDING_PHASES[i]); + } + stages.put(serviceBindingStage.getName(), serviceBindingStage); + + + Stage serviceStage = new Stage(STAGE_SERVICE); + for (int i = 1; i < SYSTEM_SERVICE_PHASES.length; i++) { + serviceStage.getSorter().addEdge(SYSTEM_SERVICE_PHASES[i - 1], SYSTEM_SERVICE_PHASES[i]); + } + stages.put(serviceStage.getName(), serviceStage); + + Stage implementationStage = new Stage(STAGE_IMPLEMENTATION); + for (int i = 1; i < SYSTEM_IMPLEMENTATION_PHASES.length; i++) { + implementationStage.getSorter().addEdge(SYSTEM_IMPLEMENTATION_PHASES[i - 1], + SYSTEM_IMPLEMENTATION_PHASES[i]); + } + implementationStage.getLastSet().add(IMPLEMENTATION); + stages.put(implementationStage.getName(), implementationStage); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorter.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorter.java new file mode 100644 index 0000000000..175f3463ad --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorter.java @@ -0,0 +1,236 @@ +/* + * 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.core.invocation.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Directed, weighted graph + * + * @param <V> The type of vertex object + * @param <E> The type of edge object + * + * @version $Rev$ $Date$ + */ +public class PhaseSorter<V> implements Cloneable { + private final Map<V, Vertex> vertices = new HashMap<V, Vertex>(); + + /** + * Vertex of a graph + */ + public final class Vertex { + private V value; + + // TODO: Do we want to support multiple edges for a vertex pair? If so, + // we should use a List instead of Map + private Map<Vertex, Edge> outEdges = new HashMap<Vertex, Edge>(); + private Map<Vertex, Edge> inEdges = new HashMap<Vertex, Edge>(); + + private Vertex(V value) { + this.value = value; + } + + @Override + public String toString() { + return "(" + value + ")"; + } + + public V getValue() { + return value; + } + + public Map<Vertex, Edge> getOutEdges() { + return outEdges; + } + + public Map<Vertex, Edge> getInEdges() { + return inEdges; + } + + } + + /** + * An Edge connects two vertices in one direction + */ + public final class Edge { + private Vertex sourceVertex; + + private Vertex targetVertex; + + public Edge(Vertex source, Vertex target) { + this.sourceVertex = source; + this.targetVertex = target; + } + + @Override + public String toString() { + return sourceVertex + "->" + targetVertex; + } + + public Vertex getTargetVertex() { + return targetVertex; + } + + public void setTargetVertex(Vertex vertex) { + this.targetVertex = vertex; + } + + public Vertex getSourceVertex() { + return sourceVertex; + } + + public void setSourceVertex(Vertex sourceVertex) { + this.sourceVertex = sourceVertex; + } + } + + public void addEdge(V source, V target) { + Vertex s = getVertex(source); + if (s == null) { + s = new Vertex(source); + vertices.put(source, s); + } + Vertex t = getVertex(target); + if (t == null) { + t = new Vertex(target); + vertices.put(target, t); + } + Edge edge = new Edge(s, t); + s.outEdges.put(t, edge); + t.inEdges.put(s, edge); + } + + public void addVertext(V source) { + Vertex s = getVertex(source); + if (s == null) { + s = new Vertex(source); + vertices.put(source, s); + } + } + + public Vertex getVertex(V source) { + Vertex s = vertices.get(source); + return s; + } + + public boolean removeEdge(V source, V target) { + Vertex s = getVertex(source); + if (s == null) { + return false; + } + + Vertex t = getVertex(target); + if (t == null) { + return false; + } + + return s.outEdges.remove(t) != null && t.inEdges.remove(s) != null; + + } + + public void removeEdge(Edge edge) { + edge.sourceVertex.outEdges.remove(edge.targetVertex); + edge.targetVertex.inEdges.remove(edge.sourceVertex); + } + + public void removeVertex(Vertex vertex) { + vertices.remove(vertex.getValue()); + for (Edge e : new ArrayList<Edge>(vertex.outEdges.values())) { + removeEdge(e); + } + for (Edge e : new ArrayList<Edge>(vertex.inEdges.values())) { + removeEdge(e); + } + } + + public Edge getEdge(Vertex source, Vertex target) { + return source.outEdges.get(target); + } + + public Edge getEdge(V source, V target) { + Vertex sv = getVertex(source); + if (sv == null) { + return null; + } + Vertex tv = getVertex(target); + if (tv == null) { + return null; + } + return getEdge(getVertex(source), getVertex(target)); + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + for (Vertex v : vertices.values()) { + sb.append(v.outEdges.values()).append("\n"); + } + return sb.toString(); + } + + public Map<V, Vertex> getVertices() { + return vertices; + } + + public void addGraph(PhaseSorter<V> otherGraph) { + for (Vertex v : otherGraph.vertices.values()) { + for (Edge e : v.outEdges.values()) { + addEdge(e.sourceVertex.value, e.targetVertex.value); + } + } + } + + private Vertex getFirst() { + for (Vertex v : vertices.values()) { + if (v.inEdges.isEmpty()) { + return v; + } + } + if (!vertices.isEmpty()) { + throw new IllegalArgumentException("Circular ordering has been detected: " + toString()); + } else { + return null; + } + } + + public List<V> topologicalSort(boolean readOnly) { + PhaseSorter<V> graph = (!readOnly) ? this : (PhaseSorter<V>)clone(); + List<V> list = new ArrayList<V>(); + while (true) { + Vertex v = graph.getFirst(); + if (v == null) { + break; + } + list.add(v.getValue()); + graph.removeVertex(v); + } + + return list; + } + + @Override + public Object clone() { + PhaseSorter<V> copy = new PhaseSorter<V>(); + copy.addGraph(this); + return copy; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/EndpointReferenceBinderImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/EndpointReferenceBinderImpl.java new file mode 100644 index 0000000000..b58635d6d1 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/EndpointReferenceBinderImpl.java @@ -0,0 +1,806 @@ +/* + * 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.core.runtime.impl; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.logging.Logger; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.Binding; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.assembly.SCABinding; +import org.apache.tuscany.sca.assembly.builder.BindingBuilder; +import org.apache.tuscany.sca.assembly.builder.BuilderContext; +import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint; +import org.apache.tuscany.sca.assembly.builder.PolicyBuilder; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.assembly.impl.RuntimeEndpointReferenceImpl; +import org.apache.tuscany.sca.definitions.Definitions; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.interfacedef.util.Audit; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.MonitorFactory; +import org.apache.tuscany.sca.policy.BindingType; +import org.apache.tuscany.sca.policy.Intent; +import org.apache.tuscany.sca.policy.IntentMap; +import org.apache.tuscany.sca.policy.PolicySet; +import org.apache.tuscany.sca.policy.Qualifier; +import org.apache.tuscany.sca.runtime.CompositeActivator; +import org.apache.tuscany.sca.runtime.EndpointReferenceBinder; +import org.apache.tuscany.sca.runtime.EndpointRegistry; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * A builder that takes endpoint references and resolves them. It either finds local + * service endpoints if they are available or asks the domain. The main function here + * is to perform binding and policy matching. + * + * This is a separate from the builders so that the mechanism for reference/service matching + * can be used at runtime as well as build time and can also be replaced independently + * + * @version $Rev$ $Date$ + */ +public class EndpointReferenceBinderImpl implements EndpointReferenceBinder { + private static final Logger logger = Logger.getLogger(EndpointReferenceBinderImpl.class.getName()); + + protected ExtensionPointRegistry extensionPoints; + protected AssemblyFactory assemblyFactory; + protected InterfaceContractMapper interfaceContractMapper; + protected BuilderExtensionPoint builders; + protected CompositeActivator compositeActivator; + protected Monitor monitor; + + + public EndpointReferenceBinderImpl(ExtensionPointRegistry extensionPoints) { + this.extensionPoints = extensionPoints; + + FactoryExtensionPoint factories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class); + this.assemblyFactory = factories.getFactory(AssemblyFactory.class); + + UtilityExtensionPoint utils = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class); + this.interfaceContractMapper = utils.getUtility(InterfaceContractMapper.class); + + MonitorFactory monitorFactory = utils.getUtility(MonitorFactory.class); + monitor = monitorFactory.createMonitor(); + + this.builders = extensionPoints.getExtensionPoint(BuilderExtensionPoint.class); + this.compositeActivator = extensionPoints.getExtensionPoint(CompositeActivator.class); + } + + /** + * Bind a single endpoint reference at build time. Here we only expect the + * registry to have a record of local endpoints + * + * @param endpointRegistry + * @param endpointReference + */ + public void bindBuildTime(EndpointRegistry endpointRegistry, + EndpointReference endpointReference) { + bind(endpointRegistry, endpointReference, false); + } + + /** + * Bind a single endpoint reference at build time. Here we expect the + * registry to be populated with endpoints from across the domain + * + * @param endpointRegistry + * @param endpointReference + */ + public void bindRunTime(EndpointRegistry endpointRegistry, + EndpointReference endpointReference) { + bind(endpointRegistry, endpointReference, true); + } + + /** + * Bind a reference to a service endpoint + * + * @param endpointRegistry + * @param endpointReference + * @param runtime set true if called from the runtime + */ + public void bind(EndpointRegistry endpointRegistry, + EndpointReference endpointReference, + boolean runtime){ + + logger.fine("Binding " + endpointReference.toString()); + + Audit matchAudit = new Audit(); + + // This logic does post build autowire matching but isn't actually used at the moment + // as problems with dependencies mean we still do this during build + if (endpointReference.getStatus() == EndpointReference.Status.AUTOWIRE_PLACEHOLDER){ + + // do autowire matching + // will only be called at build time at the moment + Multiplicity multiplicity = endpointReference.getReference().getMultiplicity(); + for (Endpoint endpoint : endpointRegistry.getEndpoints()){ +// if (endpoint is in the same composite as endpoint reference){ + if ((multiplicity == Multiplicity.ZERO_ONE || + multiplicity == Multiplicity.ONE_ONE) && + (endpointReference.getReference().getEndpointReferences().size() > 1)) { + break; + } + + // Prevent autowire connecting to self + if (endpointReference.getComponent() == + endpoint.getComponent()) { + continue; + } + + if (haveMatchingPolicy(endpointReference, endpoint, matchAudit) && + haveMatchingInterfaceContracts(endpointReference, endpoint, matchAudit)){ + // matching service so find if this reference already has + // an endpoint reference for this endpoint + Endpoint autowireEndpoint = null; + + for (EndpointReference epr : endpointReference.getReference().getEndpointReferences()){ + if (epr.getTargetEndpoint() == endpoint){ + autowireEndpoint = endpoint; + break; + } + } + + if (autowireEndpoint == null){ + // create new EPR for autowire + EndpointReference autowireEndpointRefrence = null; + try { + autowireEndpointRefrence = (EndpointReference)endpointReference.clone(); + } catch (Exception ex){ + // won't happen as clone is supported + } + + autowireEndpointRefrence.setTargetEndpoint(endpoint); + autowireEndpointRefrence.setBinding(endpoint.getBinding()); + autowireEndpointRefrence.setStatus(EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED); + endpointReference.getReference().getEndpointReferences().add(autowireEndpointRefrence); + } + } +// } + } + + if (multiplicity == Multiplicity.ONE_N || multiplicity == Multiplicity.ONE_ONE) { + if (endpointReference.getReference().getEndpointReferences().size() == 1) { + Monitor.error(monitor, + this, + "endpoint-validation-messages", + "NoComponentReferenceTarget", + endpointReference.getReference().getName()); + throw new ServiceRuntimeException("Unable to bind " + + monitor.getLastProblem().toString()); + } + } + + setSingleAutoWireTarget(endpointReference.getReference()); + + } else if ( endpointReference.getStatus() == EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED|| + endpointReference.getStatus() == EndpointReference.Status.RESOLVED_BINDING ) { + // The endpoint reference is already resolved to either + // a service endpoint local to this composite or it has + // a remote binding + + // still need to check that the callback endpoint is set correctly + if (hasCallback(endpointReference) && + (endpointReference.getCallbackEndpoint() == null + || endpointReference.getCallbackEndpoint().isUnresolved())) { + selectCallbackEndpoint(endpointReference, + endpointReference.getReference().getCallbackService(), + matchAudit); + } + } else if (endpointReference.getStatus() == EndpointReference.Status.WIRED_TARGET_FOUND_READY_FOR_MATCHING ){ + // The endpoint reference is already resolved to either + // a service endpoint but no binding was specified in the + // target URL and/or the policies have yet to be matched. + // TODO - is this really required now + + selectForwardEndpoint(endpointReference, + endpointReference.getTargetEndpoint().getService().getEndpoints(), + matchAudit); + + if (hasCallback(endpointReference)){ + selectCallbackEndpoint(endpointReference, + endpointReference.getReference().getCallbackService(), + matchAudit); + } + } else if (endpointReference.getStatus() == EndpointReference.Status.WIRED_TARGET_IN_BINDING_URI || + endpointReference.getStatus() == EndpointReference.Status.WIRED_TARGET_NOT_FOUND || + endpointReference.getStatus() == EndpointReference.Status.NOT_CONFIGURED){ + // The reference is not yet matched to a service + + // find the service in the endpoint registry + List<Endpoint> endpoints = endpointRegistry.findEndpoint(endpointReference); + + if ((endpoints.size() == 0) && + (runtime == true) ) { + + // tweak to test if this could be a resolve binding. This is the back end of the test + // in the builder that pulls the URI out of the binding if there are no targets + // on the reference. have to wait until here to see if the binding uri matches any + // available services. If not we assume here that it's a resolved binding + if (endpointReference.getStatus() == EndpointReference.Status.WIRED_TARGET_IN_BINDING_URI){ + endpointReference.getTargetEndpoint().setBinding(endpointReference.getBinding()); + endpointReference.setStatus(EndpointReference.Status.RESOLVED_BINDING); + } else { + Monitor.error(monitor, + this, + "endpoint-validation-messages", + "NoEndpointsFound", + endpointReference.toString()); + throw new ServiceRuntimeException("Unable to bind " + + monitor.getLastProblem().toString()); + } + } + + selectForwardEndpoint(endpointReference, + endpoints, + matchAudit); + + if (hasCallback(endpointReference)){ + selectCallbackEndpoint(endpointReference, + endpointReference.getReference().getCallbackService(), + matchAudit); + } + } + + logger.fine(matchAudit.toString()); + + if (endpointReference.getStatus() != EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED && + endpointReference.getStatus() != EndpointReference.Status.RESOLVED_BINDING){ + + if (runtime){ + Monitor.error(monitor, + this, + "endpoint-validation-messages", + "EndpointReferenceCantBeMatched", + endpointReference.toString(), + matchAudit); + } else { + Monitor.warning(monitor, + this, + "endpoint-validation-messages", + "ComponentReferenceTargetNotFound", + endpointReference.toString()); + } + + throw new ServiceRuntimeException("Unable to bind " + + monitor.getLastProblem().toString()); + } + + // Now the endpoint reference is resolved check that the binding interfaces contract + // and the reference contract are compatible + ((RuntimeEndpointReference)endpointReference).validateReferenceInterfaceCompatibility(); + + // System.out.println("MATCH AUDIT:" + matchAudit.toString()); + } + + /** + * Returns true if the reference has a callback + */ + private boolean hasCallback(EndpointReference endpointReference){ + if (endpointReference.getReference().getInterfaceContract() == null || + endpointReference.getReference().getInterfaceContract().getCallbackInterface() == null || + endpointReference.getReference().getName().startsWith("$self$.")){ + return false; + } else { + return true; + } + } + + /** + * Selects a forward endpoint from a list of possible candidates + * + * @param endpointReference + * @param endpoints + */ + private void selectForwardEndpoint(EndpointReference endpointReference, List<Endpoint> endpoints, Audit matchAudit) { + + Endpoint matchedEndpoint = null; + + if (endpointReference.getReference().getName().startsWith("$self$.")){ + // just select the first one and don't do any policy matching + matchedEndpoint = endpoints.get(0); + } else { + // find the first endpoint that matches this endpoint reference + for (Endpoint endpoint : endpoints){ + if (haveMatchingPolicy(endpointReference, endpoint, matchAudit) && + haveMatchingInterfaceContracts(endpointReference, endpoint, matchAudit)){ + matchedEndpoint = endpoint; + break; + } + } + } + + if (matchedEndpoint == null){ + return; + } else { + endpointReference.setTargetEndpoint(matchedEndpoint); + Binding binding = endpointReference.getTargetEndpoint().getBinding(); + endpointReference.setBinding(binding); + build(endpointReference); + endpointReference.setStatus(EndpointReference.Status.WIRED_TARGET_FOUND_AND_MATCHED); + endpointReference.setUnresolved(false); + } + } + + private void build(EndpointReference endpointReference) { + BindingBuilder builder = builders.getBindingBuilder(endpointReference.getBinding().getType()); + if (builder != null) { + builder.build(endpointReference.getComponent(), + endpointReference.getReference(), + endpointReference.getBinding(), + new BuilderContext(extensionPoints), + false); + } + } + + /** + * Selects a callback endpoint from a list of possible candidates + * + * @param endpointReference + * @param endpoints + */ + private void selectCallbackEndpoint(EndpointReference endpointReference, ComponentService callbackService, Audit matchAudit) { + + // find the first callback endpoint that matches a callback endpoint reference + // at the service + RuntimeEndpoint callbackEndpoint = null; + match: + for ( EndpointReference callbackEndpointReference : endpointReference.getTargetEndpoint().getCallbackEndpointReferences()){ + for (Endpoint endpoint : callbackService.getEndpoints()){ + if (haveMatchingPolicy(callbackEndpointReference, endpoint, matchAudit) && + haveMatchingInterfaceContracts(callbackEndpointReference, endpoint, matchAudit)){ + callbackEndpoint = (RuntimeEndpoint)endpoint; + break match; + } + } + } + + // if no callback endpoint was found or if the binding is the SCA binding and it doesn't match + // the forward binding then create a new callback endpoint + // TODO - there is a hole here in that the user may explicitly specify an SCA binding for the + // callback that is different from the forward binding. Waiting for feedback form OASIS + // before doing more drastic surgery to fix this corner case as there are other things + // wrong with the default case, such as what to do about policy + if (callbackEndpoint == null || + (callbackEndpoint.getBinding().getType().equals(SCABinding.TYPE) && + !endpointReference.getBinding().getType().equals(SCABinding.TYPE))){ + // no endpoint in place so we need to create one + callbackEndpoint = (RuntimeEndpoint)assemblyFactory.createEndpoint(); + callbackEndpoint.setComponent(endpointReference.getComponent()); + callbackEndpoint.setService(callbackService); + + Binding forwardBinding = endpointReference.getBinding(); + Binding callbackBinding = null; + for (EndpointReference callbackEPR : endpointReference.getTargetEndpoint().getCallbackEndpointReferences()){ + if (callbackEPR.getBinding().getType().equals(forwardBinding.getType())){ + try { + callbackBinding = (Binding)callbackEPR.getBinding().clone(); + } catch (CloneNotSupportedException ex){ + + } + break; + } + } + + // get the callback binding URI by looking at the SCA binding + // that will have been added at build time + callbackBinding.setURI(null); + for (Endpoint endpoint : callbackService.getEndpoints()){ + if (endpoint.getBinding().getType().equals(SCABinding.TYPE)){ + callbackBinding.setURI(endpoint.getBinding().getURI()); + } + } + + callbackEndpoint.setBinding(callbackBinding); + callbackService.getBindings().add(callbackBinding); + + callbackEndpoint.setUnresolved(false); + callbackService.getEndpoints().add(callbackEndpoint); + + // build it + build(callbackEndpoint); + + // activate it + compositeActivator.activate(((RuntimeEndpointReferenceImpl)endpointReference).getCompositeContext(), + callbackEndpoint); + + // start it + compositeActivator.start(((RuntimeEndpointReferenceImpl)endpointReference).getCompositeContext(), + callbackEndpoint); + } + + endpointReference.setCallbackEndpoint(callbackEndpoint); + } + + private void build(Endpoint endpoint) { + + BindingBuilder builder = builders.getBindingBuilder(endpoint.getBinding().getType()); + if (builder != null) { + builder.build(endpoint.getComponent(), + endpoint.getService(), + endpoint.getBinding(), + new BuilderContext(extensionPoints), + true); + } + } + + /** + * Determine if endpoint reference and endpoint policies match. We know by this stage + * that + * - a given policy set will only contain expressions from a single language + * - a given endpoint or endpoint reference's policy sets will only contain + * expressions from a single language + * + * Matching algorithm (read from the top down): + * - FAIL if there are intents that are mutually exclusive between reference and service + * - PASS if there are no intents or policies present at reference and service + * - FAIL if there are unresolved intents (intents with no policy set) at the reference (service should have been checked previously) + * - PASS if there are no policies at reference and service (now we know all intents are resolved) + * - FAIL if there are some policies on one side but not on the other + * - PASS if the QName of the policy sets on each side match + * - FAIL if the policy languages on both sides are different + * - Perform policy specific match + * + */ + private boolean haveMatchingPolicy(EndpointReference endpointReference, Endpoint endpoint, Audit matchAudit){ + matchAudit.append("Match policy of " + endpointReference.toString() + " to " + endpoint.toString() + " "); + + List<PolicySet> referencePolicySets = new ArrayList<PolicySet>(); + Binding binding = null; + + if (endpointReference.getBinding() == null){ + binding = endpoint.getBinding(); + } else { + binding = endpointReference.getBinding(); + } + + // if there are any intents that are mutually exclusive between + // service and reference then they don't match + for (Intent eprIntent : endpointReference.getRequiredIntents()){ + for (Intent epIntent : endpoint.getRequiredIntents()){ + if (eprIntent.getExcludedIntents().contains(epIntent) || + epIntent.getExcludedIntents().contains(eprIntent) || + checkQualifiedMutualExclusion(eprIntent.getExcludedIntents(), epIntent) || + checkQualifiedMutualExclusion(epIntent.getExcludedIntents(), eprIntent)){ + matchAudit.append("No match because the following intents are mutually exclusive " + + eprIntent.toString() + + " " + + epIntent.toString() + + " "); + return false; + } + } + } + + // Find the set of policy sets from this reference. This includes + // the policy sets that are specific to the service binding and + // any policy sets that are not binding specific + for (PolicySet policySet : endpointReference.getPolicySets()){ + PolicyBuilder policyBuilder = null; + + if (policySet.getPolicies().size() > 0){ + QName policyType = policySet.getPolicies().get(0).getName(); + policyBuilder = builders.getPolicyBuilder(policyType); + } + + if ((policyBuilder == null) || + (policyBuilder != null && policyBuilder.getSupportedBindings() == null) || + (policyBuilder != null && policyBuilder.getSupportedBindings().contains(binding.getType()))){ + referencePolicySets.add(policySet); + } + } + + // the "appliesTo" algorithm to remove any policy sets that + // don't apply to the service binding will already have been + // run during the build phase + + // Determine if there are any reference policies + boolean noEndpointReferencePolicies = true; + + for (PolicySet policySet : referencePolicySets){ + if (policySet.getPolicies().size() > 0){ + noEndpointReferencePolicies = false; + break; + } + } + + // Determine of there are any service policies + boolean noEndpointPolicies = true; + + for (PolicySet policySet : endpoint.getPolicySets()){ + if (policySet.getPolicies().size() > 0){ + noEndpointPolicies = false; + break; + } + } + + // if no policy sets or intents are present then they match + if ((endpointReference.getRequiredIntents().size() == 0) && + (endpoint.getRequiredIntents().size() == 0) && + (noEndpointReferencePolicies) && + (noEndpointPolicies)) { + matchAudit.append("Match because there are no intents or policies "); + return true; + } + + // check that the intents on the reference side are resolved + // can't do this until this point as the service binding + // may come into play. Intents may be satisfied by the default + // or optional intents that the binding type provides. Failing + // this they must be satisfied by reference policy sets + // Failing this the intent is unresolved and the reference and + // service don't match + List<Intent> eprIntents = new ArrayList<Intent>(); + eprIntents.addAll(endpointReference.getRequiredIntents()); + + // TODO - seems that we should do this loop on a binding by binding basis + // rather than each time we do matching + BindingType bindingType = null; + Definitions systemDefinitions = ((RuntimeEndpoint)endpoint).getCompositeContext().getSystemDefinitions(); + for (BindingType loopBindingType : systemDefinitions.getBindingTypes()){ + if (loopBindingType.getType().equals(binding.getType())){ + bindingType = loopBindingType; + break; + } + } + + // first check the binding type + for (Intent intent : endpointReference.getRequiredIntents()){ + if (bindingType != null && + bindingType.getAlwaysProvidedIntents().contains(intent)){ + eprIntents.remove(intent); + } else if (bindingType != null && + bindingType.getMayProvidedIntents().contains(intent)){ + eprIntents.remove(intent); + } else { + // TODO - this code also appears in the ComponentPolicyBuilder + // so should rationalize + loop: for (PolicySet policySet : referencePolicySets){ + if (policySet.getProvidedIntents().contains(intent)){ + eprIntents.remove(intent); + break; + } + + for (Intent psProvidedIntent : policySet.getProvidedIntents()){ + if (isQualifiedBy(psProvidedIntent, intent)){ + eprIntents.remove(intent); + break loop; + } + } + + for (IntentMap map : policySet.getIntentMaps()) { + for (Qualifier q : map.getQualifiers()) { + if (intent.equals(q.getIntent())) { + eprIntents.remove(intent); + break loop; + } + } + } + } + } + } + + // if there are unresolved intents the service and reference don't match + if (eprIntents.size() > 0){ + matchAudit.append("No match because there are unresolved intents " + eprIntents.toString() + " "); + return false; + } + + // if there are no policies on epr or ep side then + // they match + if (noEndpointPolicies && noEndpointReferencePolicies){ + matchAudit.append("Match because the intents are resolved and there are no policy sets "); + return true; + } + + // if there are some policies on one side and not the other then + // the don't match + if (noEndpointPolicies && !noEndpointReferencePolicies) { + matchAudit.append("No match because there are policy sets at the endpoint reference but not at the endpoint "); + return false; + } + + if (!noEndpointPolicies && noEndpointReferencePolicies){ + matchAudit.append("No match because there are policy sets at the endpoint but not at the endpoint reference "); + return false; + } + + // If policy set QNames from epr and er match exactly then the reference and + // service policies are compatible + Set<PolicySet> referencePolicySet = new HashSet<PolicySet>(referencePolicySets); + Set<PolicySet> servicePolicySet = new HashSet<PolicySet>(endpoint.getPolicySets()); + if(referencePolicySet.equals(servicePolicySet)){ + matchAudit.append("Match because the policy sets on both sides are eactly the same "); + return true; + } + + // if policy set language at ep and epr are not the same then there is no + // match. We get the policy language by looking at the first expression + // of the first policy set. By this stage we know that all the policy sets + // in an endpoint or endpoint reference will use a single language and we know + // that there is at least one policy set with at least one policy + QName eprLanguage = null; + + for (PolicySet policySet : referencePolicySets){ + if (policySet.getPolicies().size() > 0){ + eprLanguage = policySet.getPolicies().get(0).getName(); + break; + } + } + + QName epLanguage = null; + + for (PolicySet policySet : endpoint.getPolicySets()){ + if (policySet.getPolicies().size() > 0){ + epLanguage = policySet.getPolicies().get(0).getName(); + break; + } + } + + if(!eprLanguage.equals(epLanguage)){ + matchAudit.append("No match because the policy sets on either side have policies in differnt languages " + + eprLanguage + + " and " + + epLanguage + + " "); + return false; + } + + // now do a policy specific language match + PolicyBuilder builder = builders.getPolicyBuilder(eprLanguage); + boolean match = false; + + // switch the derived list of policy sets into the reference + // it will be left there if there is a match + List<PolicySet> originalPolicySets = endpointReference.getPolicySets(); + endpointReference.getPolicySets().clear(); + endpointReference.getPolicySets().addAll(referencePolicySets); + + if (builder != null) { + // TODO - where to get builder context from? + BuilderContext builderContext = new BuilderContext(monitor); + + match = builder.build(endpointReference, endpoint, builderContext); + } + + if (!match){ + matchAudit.append("No match because the language specific matching failed "); + endpointReference.getPolicySets().clear(); + endpointReference.getPolicySets().addAll(originalPolicySets); + } else { + matchAudit.append("Match because the language specific matching succeeded "); + } + + return match; + } + + protected boolean isQualifiedBy(Intent qualifiableIntent, Intent qualifiedIntent){ + if (qualifiedIntent.getQualifiableIntent() == qualifiableIntent){ + return true; + } else { + return false; + } + } + + protected boolean checkQualifiedMutualExclusion(List<Intent> excludedIntentList, Intent intent){ + for (Intent excludedIntent : excludedIntentList){ + if (intent.getQualifiableIntent() != null && + excludedIntent != null && + intent.getQualifiableIntent().equals(excludedIntent)){ + return true; + } + } + return false; + } + + /** + * Determine if endpoint reference and endpoint interface contracts match + */ + private boolean haveMatchingInterfaceContracts(EndpointReference endpointReference, Endpoint endpoint, Audit matchAudit){ + matchAudit.append("Match interface of " + endpointReference.toString() + " to " + endpoint.toString() + " "); + + if (endpointReference.getReference().getInterfaceContract() == null){ + matchAudit.append("Match because there is no interface contract on the reference "); + return true; + } + + // TODO - is there a better test for this. Would have to cast to the + // correct iface type to get to the resolved flag + if (endpoint.getComponentServiceInterfaceContract().getInterface().getOperations().size() == 0){ + // the interface contract is likely remote but unresolved + // we discussed this on the ML and decided that we could + // live with this for the case where there is no central matching of references + // to services. Any errors will be detected when the message flows. + matchAudit.append("Match because the endpoint is remote and we don't have a copy of it's interface contract "); + return true; + } + + boolean match = false; + match = interfaceContractMapper.isCompatibleSubset(endpointReference.getReference().getInterfaceContract(), + endpoint.getComponentServiceInterfaceContract(), matchAudit); + + if (!match){ + matchAudit.append("Match failed because the linterface contract mapper failed "); + } else { + matchAudit.append("Match because the interface contract mapper succeeded "); + } + + return match; + } + + /** + * Checks to see if the registry has been updated since the reference was last matched + * + * @return true is the registry has changed + */ + public boolean isOutOfDate(EndpointRegistry endpointRegistry, EndpointReference endpointReference) { + Endpoint te = endpointReference.getTargetEndpoint(); + if (te != null && !te.isUnresolved() + && te.getURI() != null + && endpointReference.getStatus() != EndpointReference.Status.RESOLVED_BINDING) { + List<Endpoint> endpoints = endpointRegistry.findEndpoint(endpointReference); + return ! endpoints.contains(endpointReference.getTargetEndpoint()); + } + return false; + } + + /** + * ASM_5021: where a <reference/> of a <component/> has @autowire=true + * and where the <reference/> has a <binding/> child element which + * declares a single target service, the reference is wired only to + * the single service identified by the <wire/> element + */ + private void setSingleAutoWireTarget(ComponentReference reference) { + if (reference.getEndpointReferences().size() > 1 && reference.getBindings() != null + && reference.getBindings().size() == 1) { + String uri = reference.getBindings().get(0).getURI(); + if (uri != null) { + if (uri.indexOf('/') > -1) { + // TODO: must be a way to avoid this fiddling + int i = uri.indexOf('/'); + String c = uri.substring(0, i); + String s = uri.substring(i + 1); + uri = c + "#service(" + s + ")"; + } + for (EndpointReference er : reference.getEndpointReferences()) { + if (er.getTargetEndpoint() != null && uri.equals(er.getTargetEndpoint().getURI())) { + reference.getEndpointReferences().clear(); + reference.getEndpointReferences().add(er); + return; + } + } + } + } + } + + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/RuntimePropertiesImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/RuntimePropertiesImpl.java new file mode 100644 index 0000000000..cd8bc936af --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/runtime/impl/RuntimePropertiesImpl.java @@ -0,0 +1,38 @@ +/* + * 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.core.runtime.impl; + +import java.util.Properties; + +import org.apache.tuscany.sca.runtime.RuntimeProperties; + +public class RuntimePropertiesImpl implements RuntimeProperties { + + private Properties properties = new Properties(); + + public Properties getProperties() { + return properties; + } + + public void setProperties(Properties properties) { + this.properties = properties; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainer.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainer.java new file mode 100644 index 0000000000..4674456925 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/AbstractScopeContainer.java @@ -0,0 +1,196 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.scope; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.sca.core.factory.InstanceWrapper; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * Implements functionality common to scope contexts. + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractScopeContainer<KEY> implements ScopeContainer<KEY> { + protected Map<KEY, InstanceWrapper<?>> wrappers = new ConcurrentHashMap<KEY, InstanceWrapper<?>>(); + protected final Scope scope; + + protected RuntimeComponent component; + protected volatile int lifecycleState = UNINITIALIZED; + + + public AbstractScopeContainer(Scope scope, RuntimeComponent component) { + this.scope = scope; + this.component = component; + } + + protected void checkInit() { + if (getLifecycleState() != RUNNING) { + throw new IllegalStateException("Scope container not running [" + getLifecycleState() + "]"); + } + } + + /** + * Creates a new physical instance of a component, wrapped in an + * InstanceWrapper. + * + * @param component the component whose instance should be created + * @return a wrapped instance that has been injected but not yet started + * @throws TargetResolutionException if there was a problem creating the + * instance + */ + protected InstanceWrapper createInstanceWrapper() throws TargetResolutionException { + ImplementationProvider implementationProvider = component.getImplementationProvider(); + if (implementationProvider instanceof ScopedImplementationProvider) { + return ((ScopedImplementationProvider)implementationProvider).createInstanceWrapper(); + } + return null; + } + + public InstanceWrapper getAssociatedWrapper(KEY contextId) throws TargetResolutionException { + return getWrapper(contextId); // TODO: what is this method supposed to do diff than getWrapper? + } + + public Scope getScope() { + return scope; + } + + public InstanceWrapper getWrapper(KEY contextId) throws TargetResolutionException { + return wrappers.get(contextId); + } + + public void addWrapperReference(KEY existingContextId, KEY newContextId) + throws TargetResolutionException { + // do nothing here. the conversational scope container implements this + } + + public void registerWrapper(InstanceWrapper wrapper, KEY contextId) throws TargetResolutionException { + // do nothing here. the conversational scope container implements this + } + + protected boolean isEagerInit() { + ImplementationProvider implementationProvider = ((RuntimeComponent)component).getImplementationProvider(); + if (implementationProvider instanceof ScopedImplementationProvider) { + return ((ScopedImplementationProvider)implementationProvider).isEagerInit(); + } + return false; + } + + public void returnWrapper(InstanceWrapper wrapper, KEY contextId) throws TargetDestructionException { + } + + /** + * Default implementation of remove which does nothing + * + * @param contextId the identifier of the context to remove. + */ + public void remove(KEY contextId) + throws TargetDestructionException { + } + + public synchronized void start() { + int lifecycleState = getLifecycleState(); + if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) { + throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]"); + } + setLifecycleState(RUNNING); + } + + public void startContext(KEY contextId) { + if(isEagerInit()) { + try { + getWrapper(contextId); + } catch (TargetResolutionException e) { + // + } + } + } + + public synchronized void stop() { + int lifecycleState = getLifecycleState(); + if (lifecycleState != RUNNING) { + throw new IllegalStateException("Scope in wrong state [" + lifecycleState + "]"); + } + setLifecycleState(STOPPED); + } + + public void stopContext(KEY contextId) { + wrappers.remove(contextId); + } + + @Override + public String toString() { + String s; + switch (lifecycleState) { + case ScopeContainer.CONFIG_ERROR: + s = "CONFIG_ERROR"; + break; + case ScopeContainer.ERROR: + s = "ERROR"; + break; + case ScopeContainer.INITIALIZING: + s = "INITIALIZING"; + break; + case ScopeContainer.INITIALIZED: + s = "INITIALIZED"; + break; + case ScopeContainer.RUNNING: + s = "RUNNING"; + break; + case ScopeContainer.STOPPING: + s = "STOPPING"; + break; + case ScopeContainer.STOPPED: + s = "STOPPED"; + break; + case ScopeContainer.UNINITIALIZED: + s = "UNINITIALIZED"; + break; + default: + s = "UNKNOWN"; + break; + } + return "In state [" + s + ']'; + } + + public RuntimeComponent getComponent() { + return component; + } + + public void setComponent(RuntimeComponent component) { + this.component = component; + } + + public int getLifecycleState() { + return lifecycleState; + } + + /** + * Set the current state of the Lifecycle. + * + * @param lifecycleState the new state + */ + protected void setLifecycleState(int lifecycleState) { + this.lifecycleState = lifecycleState; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/DefaultScopeRegistry.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/DefaultScopeRegistry.java new file mode 100644 index 0000000000..2ea724ccf6 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/DefaultScopeRegistry.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.scope; + +import org.apache.tuscany.sca.core.scope.impl.CompositeScopeContainerFactory; +import org.apache.tuscany.sca.core.scope.impl.ScopeRegistryImpl; +import org.apache.tuscany.sca.core.scope.impl.StatelessScopeContainerFactory; + +/** + * A default scope registry implementation. + * + * @version $Rev$ $Date$ + */ +public class DefaultScopeRegistry extends ScopeRegistryImpl implements ScopeRegistry { + + public DefaultScopeRegistry() { + ScopeContainerFactory[] factories = + new ScopeContainerFactory[] {new CompositeScopeContainerFactory(), new StatelessScopeContainerFactory()}; + for (ScopeContainerFactory f : factories) { + register(f); + } + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/Scope.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/Scope.java new file mode 100644 index 0000000000..35da433af0 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/Scope.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.core.scope; + +/** + * The default implementation scopes supported by assemblies. + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public class Scope { + public static final Scope STATELESS = new Scope("STATELESS"); + public static final Scope COMPOSITE = new Scope("COMPOSITE"); + public static final Scope INVALID = new Scope("INVALID"); + + private String scope; + + public Scope(String scope) { + this.scope = scope.toUpperCase().intern(); + } + + public String getScope() { + return scope; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final Scope scope1 = (Scope) o; + return !(scope != null ? scope != scope1.scope.intern() : scope1.scope != null); + } + + @Override + public int hashCode() { + return scope != null ? scope.hashCode() : 0; + } + + @Override + public String toString() { + return scope; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainer.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainer.java new file mode 100644 index 0000000000..7d34a0144b --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainer.java @@ -0,0 +1,160 @@ +/* + * 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.core.scope; + +import org.apache.tuscany.sca.core.factory.InstanceWrapper; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + + +/** + * Manages the lifecycle and visibility of instances associated with a an {@link RuntimeComponent}. + * + * @version $Rev$ $Date$ + * @param <KEY> the type of IDs that this container uses to identify its contexts. + * For example, for COMPOSITE scope this could be the URI of the composite component, + * or for HTTP Session scope it might be the HTTP session ID. + * + * @tuscany.spi.extension.asclient + */ +public interface ScopeContainer<KEY> { + + /** + * Returns the Scope that this container supports. + * + * @return the Scope that this container supports + */ + Scope getScope(); + + /** + * Start a new context with the supplied ID. + * + * @param contextId an ID that uniquely identifies the context. + */ + void startContext(KEY contextId); + + /** + * Stop the context with the supplied ID. + * + * @param contextId an ID that uniquely identifies the context. + */ + void stopContext(KEY contextId); + + /** + * Returns an instance wrapper associated with the current scope context, creating one if necessary + * @param contextId the id for the scope context + * + * @return the wrapper for the target instance + * @throws TargetResolutionException if there was a problem instantiating the target instance + */ + InstanceWrapper getWrapper(KEY contextId) throws TargetResolutionException; + + /** + * Allows a component to be registered against more than one context id. This is required in the + * case of stateful callbacks where we want to identify the originating client component instance + * as the callback target but we don't want to reuse the clients original conversation id + * + * @param existingContextId an id that identifies an existing component instance + * @param newContextId a new id against which this component will also be registered + * @throws TargetResolutionException + */ + void addWrapperReference(KEY existingContextId, KEY newContextId) + throws TargetResolutionException; + + /** + * Register an existing instance against a context id. This is needed + * for a stateful callback where the service reference for the forward call + * contains a callback object that is not a service reference. + * + * @param wrapper the instance wrapper for the instance to be registered + * @param contextId the id for the scope context + * @throws TargetResolutionException + */ + void registerWrapper(InstanceWrapper wrapper, KEY contextId) + throws TargetResolutionException; + + /** + * Returns an implementation instance associated with the current scope context. + * If no instance is found, a {@link TargetNotFoundException} is thrown. + * @param contextId the id for the scope context + * + * @return the wrapper for the target instance + * @throws TargetResolutionException if there was a problem instantiating the target instance + */ + InstanceWrapper getAssociatedWrapper(KEY contextId) + throws TargetResolutionException; + + /** + * Return a wrapper after use (for example, after invoking the instance). + * @param wrapper the wrapper for the target instance being returned + * @param contextId the id for the scope context + * + * @throws TargetDestructionException if there was a problem returning the target instance + */ + void returnWrapper(InstanceWrapper wrapper, KEY contextId) + throws TargetDestructionException; + + /** + * Removes an identified component implementation instance associated with the current + * context from persistent storage + * + * @param contextId the identifier of the context to remove. + */ + void remove(KEY contextId) + throws TargetDestructionException; + + /* A configuration error state */ + int CONFIG_ERROR = -1; + /* Has not been initialized */ + int UNINITIALIZED = 0; + /* In the process of being configured and initialized */ + int INITIALIZING = 1; + /* Instantiated and configured */ + int INITIALIZED = 2; + /* Configured and initialized */ + int RUNNING = 4; + /* In the process of being shutdown */ + int STOPPING = 5; + /* Has been shutdown and removed from the composite */ + int STOPPED = 6; + /* In an error state */ + int ERROR = 7; + + /** + * Returns the lifecycle state + * + * @see #UNINITIALIZED + * @see #INITIALIZING + * @see #INITIALIZED + * @see #RUNNING + * @see #STOPPING + * @see #STOPPED + */ + int getLifecycleState(); + + /** + * Starts the Lifecycle. + */ + void start(); + + /** + * Stops the Lifecycle. + */ + void stop(); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainerFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainerFactory.java new file mode 100644 index 0000000000..b19c14b3e0 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeContainerFactory.java @@ -0,0 +1,32 @@ +/* + * 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.core.scope; + +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * Factory to create ScopeContainer for components + * + * @version $Rev$ $Date$ + */ +public interface ScopeContainerFactory { + ScopeContainer createScopeContainer(RuntimeComponent component); + Scope getScope(); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistry.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistry.java new file mode 100644 index 0000000000..842ed4c547 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopeRegistry.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.scope; + +import org.apache.tuscany.sca.runtime.RuntimeComponent; + + +/** + * Manages {@link ScopeContainer}s in the runtime + * + * @version $Rev$ $Date$ + */ +public interface ScopeRegistry { + + /** + * Returns the scope container for the given scope or null if one not found + * + * @param scope the scope + * @return the scope container for the given scope or null if one not found + */ + ScopeContainer getScopeContainer(RuntimeComponent component); + + /** + * @param factory + */ + void register(ScopeContainerFactory factory); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedImplementationProvider.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedImplementationProvider.java new file mode 100644 index 0000000000..ee55917f2f --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedImplementationProvider.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.core.scope; + +import org.apache.tuscany.sca.core.factory.InstanceWrapper; +import org.apache.tuscany.sca.provider.ImplementationProvider; + +/** + * A component implementation can implement this interface to provide scope + * management for the components + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public interface ScopedImplementationProvider extends ImplementationProvider { + /** + * Get the scope for the component implementation + * + * @return The scope for the component implementation, if null is returned, + * STATELESS will be used + */ + Scope getScope(); + + /** + * Indicate if the component needs to be eagerly initialized + * + * @return true if the component is marked to be eagerly initialized, false + * otherwise + */ + boolean isEagerInit(); + + /** + * Create a wrapper for the component instance for the scope management + * + * @return A wrapper for the component instance + */ + InstanceWrapper createInstanceWrapper(); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedRuntimeComponent.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedRuntimeComponent.java new file mode 100644 index 0000000000..98c5f84c71 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/ScopedRuntimeComponent.java @@ -0,0 +1,41 @@ +/* + * 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.core.scope; + +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * Scoped runtime component + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public interface ScopedRuntimeComponent extends RuntimeComponent { + /** + * Set the associated scope container + * @param scopeContainer + */ + void setScopeContainer(ScopeContainer scopeContainer); + /** + * Get the assoicated scope container + * @return + */ + ScopeContainer getScopeContainer(); +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetDestructionException.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetDestructionException.java new file mode 100644 index 0000000000..5c85fead2c --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetDestructionException.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.scope; + +/** + * Denotes an error destroying a target + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public class TargetDestructionException extends TargetResolutionException { + private static final long serialVersionUID = -6126684147851674709L; + + public TargetDestructionException() { + super(); + } + + public TargetDestructionException(String message, Throwable cause) { + super(message, cause); + } + + public TargetDestructionException(String message) { + super(message); + } + + public TargetDestructionException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetInitializationException.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetInitializationException.java new file mode 100644 index 0000000000..89ddd7e538 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetInitializationException.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.scope; + +/** + * Denotes an error initializing a target + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public class TargetInitializationException extends TargetResolutionException { + private static final long serialVersionUID = -6228778208649752698L; + + public TargetInitializationException() { + super(); + } + + public TargetInitializationException(String message, Throwable cause) { + super(message, cause); + } + + public TargetInitializationException(String message) { + super(message); + } + + public TargetInitializationException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetNotFoundException.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetNotFoundException.java new file mode 100644 index 0000000000..bb46a2499b --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetNotFoundException.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.core.scope; + +/** + * Thrown when a target of an operation cannot be found + * + * @version $Rev$ $Date$ + */ +public class TargetNotFoundException extends TargetResolutionException { + private static final long serialVersionUID = 5541830480658471186L; + + public TargetNotFoundException() { + super(); + } + + public TargetNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public TargetNotFoundException(String message) { + super(message); + } + + public TargetNotFoundException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetResolutionException.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetResolutionException.java new file mode 100644 index 0000000000..17afd36219 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/TargetResolutionException.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.scope; + +/** + * Denotes an error retrieving a target instance + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.asclient + */ +public class TargetResolutionException extends Exception { + private static final long serialVersionUID = 2912513650522019405L; + + public TargetResolutionException() { + super(); + } + + public TargetResolutionException(String message, Throwable cause) { + super(message, cause); + } + + public TargetResolutionException(String message) { + super(message); + } + + public TargetResolutionException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainer.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainer.java new file mode 100644 index 0000000000..730f92e0f9 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainer.java @@ -0,0 +1,87 @@ +/* + * 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.core.scope.impl; + +import org.apache.tuscany.sca.core.factory.InstanceWrapper; +import org.apache.tuscany.sca.core.scope.AbstractScopeContainer; +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.core.scope.TargetDestructionException; +import org.apache.tuscany.sca.core.scope.TargetNotFoundException; +import org.apache.tuscany.sca.core.scope.TargetResolutionException; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.oasisopen.sca.ServiceUnavailableException; + +/** + * A scope context which manages atomic component instances keyed by composite + * + * @version $Rev$ $Date$ + */ +public class CompositeScopeContainer<KEY> extends AbstractScopeContainer<KEY> { + private InstanceWrapper<?> wrapper; + + public CompositeScopeContainer(RuntimeComponent component) { + super(Scope.COMPOSITE, component); + } + + @Override + public synchronized void stop() { + super.stop(); + if (wrapper != null) { + try { + wrapper.stop(); + } catch (TargetDestructionException e) { + throw new IllegalStateException(e); + } + } + wrapper = null; + } + + @Override + public synchronized InstanceWrapper getWrapper(KEY contextId) throws TargetResolutionException { + if (wrapper == null) { + try { + wrapper = createInstanceWrapper(); + wrapper.start(); + } catch (Exception e) { + throw new ServiceUnavailableException(e); + } + } + return wrapper; + } + + @Override + public InstanceWrapper getAssociatedWrapper(KEY contextId) throws TargetResolutionException { + if (wrapper == null) { + throw new TargetNotFoundException(component.getURI()); + } + return wrapper; + } + + @Override + public synchronized void start() { + super.start(); + if (isEagerInit()) { + try { + getWrapper(null); + } catch (TargetResolutionException e) { + throw new IllegalStateException(e); + } + } + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainerFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainerFactory.java new file mode 100644 index 0000000000..f61e70a598 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/CompositeScopeContainerFactory.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.scope.impl; + +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.ScopeContainerFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * @version $Rev$ $Date$ + */ +public class CompositeScopeContainerFactory implements ScopeContainerFactory { + + public ScopeContainer createScopeContainer(RuntimeComponent component) { + return new CompositeScopeContainer(component); + } + + public Scope getScope() { + return Scope.COMPOSITE; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ScopeRegistryImpl.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ScopeRegistryImpl.java new file mode 100644 index 0000000000..9884c5f053 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/ScopeRegistryImpl.java @@ -0,0 +1,70 @@ +/* + * 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.core.scope.impl; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.ScopeContainerFactory; +import org.apache.tuscany.sca.core.scope.ScopeRegistry; +import org.apache.tuscany.sca.core.scope.ScopedImplementationProvider; +import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * The default implementation of a scope registry + * + * @version $Rev$ $Date$ + */ +public class ScopeRegistryImpl implements ScopeRegistry { + private final Map<Scope, ScopeContainerFactory> scopeCache = new ConcurrentHashMap<Scope, ScopeContainerFactory>(); + + public void register(ScopeContainerFactory factory) { + scopeCache.put(factory.getScope(), factory); + } + + public ScopeContainer getScopeContainer(RuntimeComponent runtimeComponent) { + if (!(runtimeComponent instanceof ScopedRuntimeComponent)) { + return null; + } + ScopedRuntimeComponent component = (ScopedRuntimeComponent)runtimeComponent; + if (component.getScopeContainer() != null) { + return component.getScopeContainer(); + } + ImplementationProvider implementationProvider = component.getImplementationProvider(); + if (implementationProvider instanceof ScopedImplementationProvider) { + ScopedImplementationProvider provider = (ScopedImplementationProvider)implementationProvider; + Scope scope = provider.getScope(); + if (scope == null) { + scope = Scope.STATELESS; + } else if (scope.equals(Scope.INVALID)) { + return null; + } + ScopeContainerFactory factory = scopeCache.get(scope); + ScopeContainer container = factory.createScopeContainer(component); + component.setScopeContainer(container); + return container; + } + return null; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainer.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainer.java new file mode 100644 index 0000000000..1235fd2a67 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainer.java @@ -0,0 +1,61 @@ +/* + * 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.core.scope.impl; + +import org.apache.tuscany.sca.core.factory.InstanceWrapper; +import org.apache.tuscany.sca.core.scope.AbstractScopeContainer; +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.core.scope.TargetDestructionException; +import org.apache.tuscany.sca.core.scope.TargetResolutionException; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * A scope context which manages stateless atomic component instances in a non-pooled fashion. + * + * @version $Rev$ $Date$ + */ +public class StatelessScopeContainer<KEY> extends AbstractScopeContainer<KEY> { + + public StatelessScopeContainer(RuntimeComponent component) { + super(Scope.STATELESS, component); + } + + @Override + public InstanceWrapper getWrapper(KEY contextId) throws TargetResolutionException { + if (lifecycleState != RUNNING) { + throw new TargetResolutionException("scope container not running, lifecycleState=" + lifecycleState); + } + InstanceWrapper ctx = createInstanceWrapper(); + ctx.start(); + return ctx; + } + + @Override + public InstanceWrapper getAssociatedWrapper(KEY contextId) + throws TargetResolutionException { + return getWrapper(contextId); + } + + @Override + public void returnWrapper(InstanceWrapper wrapper, KEY contextId) + throws TargetDestructionException { + wrapper.stop(); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainerFactory.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainerFactory.java new file mode 100644 index 0000000000..5bf20a6a5f --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/scope/impl/StatelessScopeContainerFactory.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.sca.core.scope.impl; + +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.ScopeContainerFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * @version $Rev$ $Date$ + */ +public class StatelessScopeContainerFactory implements ScopeContainerFactory { + + public ScopeContainer createScopeContainer(RuntimeComponent component) { + return new StatelessScopeContainer(component); + } + + public Scope getScope() { + return Scope.STATELESS; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/DefaultWorkScheduler.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/DefaultWorkScheduler.java new file mode 100644 index 0000000000..380ca818c5 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/DefaultWorkScheduler.java @@ -0,0 +1,204 @@ +/* + * 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.core.work.impl; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Map; + +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.LifeCycleListener; +import org.apache.tuscany.sca.work.NotificationListener; +import org.apache.tuscany.sca.work.WorkScheduler; +import org.apache.tuscany.sca.work.WorkSchedulerException; + +/** + * A work scheduler implementation based on a JSR 237 work manager. + * <p/> + * <p/> + * This needs a JSR 237 work manager implementation available for scheduling work. Instances can be configured with a + * work manager implementation that is injected in. It is the responsibility of the runtime environment to make a work + * manager implementation available. For example, if the managed environment supports work manager the runtime can use + * the appropriate lookup mechanism to inject the work manager implementation. </p> + * + * @version $Rev$ $Date$ + */ +public class DefaultWorkScheduler implements WorkScheduler, LifeCycleListener { + + /** + * Underlying JSR-237 work manager + */ + private ThreadPoolWorkManager jsr237WorkManager; + private int maxThreads = 0; + + /** + * Initializes the JSR 237 work manager. + * + * @param jsr237WorkManager JSR 237 work manager. + */ + public DefaultWorkScheduler(ExtensionPointRegistry registry, Map<String, String> attributes) { + if (attributes != null) { + String value = attributes.get("maxThreads"); + if (value != null) { + maxThreads = Integer.parseInt(value.trim()); + } + } + } + + private synchronized ThreadPoolWorkManager getWorkManager() { + if (jsr237WorkManager != null) { + return jsr237WorkManager; + } +// try { +// InitialContext ctx = new InitialContext(); +// jsr237WorkManager = (ThreadPoolWorkManager)ctx.lookup("java:comp/env/wm/TuscanyWorkManager"); +// } catch (Throwable e) { +// // ignore +// } + if (jsr237WorkManager == null) { + jsr237WorkManager = new ThreadPoolWorkManager(maxThreads); + } + return jsr237WorkManager; + } + + /** + * Schedules a unit of work for future execution. The notification listener is used to register interest in + * callbacks regarding the status of the work. + * + * @param work The unit of work that needs to be asynchronously executed. + */ + public <T extends Runnable> void scheduleWork(T work) { + scheduleWork(work, null); + } + + /** + * Schedules a unit of work for future execution. The notification listener is used to register interest in + * callbacks regarding the status of the work. + * + * @param work The unit of work that needs to be asynchronously executed. + * @param listener Notification listener for callbacks. + */ + public <T extends Runnable> void scheduleWork(T work, NotificationListener<T> listener) { + + if (work == null) { + throw new IllegalArgumentException("Work cannot be null"); + } + + Work<T> jsr237Work = new Work<T>(work); + try { + if (listener == null) { + getWorkManager().schedule(jsr237Work); + } else { + Jsr237WorkListener<T> jsr237WorkListener = new Jsr237WorkListener<T>(listener, work); + getWorkManager().schedule(jsr237Work, jsr237WorkListener); + } + } catch (IllegalArgumentException ex) { + if (listener != null) { + listener.workRejected(work); + } else { + throw new WorkSchedulerException(ex); + } + } catch (Exception ex) { + throw new WorkSchedulerException(ex); + } + + } + + public void start() { + } + + public void stop() { + if (jsr237WorkManager instanceof ThreadPoolWorkManager) { + // Allow privileged access to modify threads. Requires RuntimePermission in security + // policy. + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + ((ThreadPoolWorkManager)jsr237WorkManager).destroy(); + return null; + } + }); + } + } + + /* + * WorkListener for keeping track of work status callbacks. + * + */ + private class Jsr237WorkListener<T extends Runnable> implements WorkListener { + + // Notification listener + private NotificationListener<T> listener; + + // Work + private T work; + + /* + * Initializes the notification listener. + */ + public Jsr237WorkListener(NotificationListener<T> listener, T work) { + this.listener = listener; + this.work = work; + } + + /* + * Callback when the work is accepted. + */ + public void workAccepted(WorkEvent workEvent) { + T work = getWork(); + listener.workAccepted(work); + } + + /* + * Callback when the work is rejected. + */ + public void workRejected(WorkEvent workEvent) { + T work = getWork(); + listener.workRejected(work); + } + + /* + * Callback when the work is started. + */ + public void workStarted(WorkEvent workEvent) { + T work = getWork(); + listener.workStarted(work); + } + + /* + * Callback when the work is completed. + */ + public void workCompleted(WorkEvent workEvent) { + T work = getWork(); + Exception exception = workEvent.getException(); + if (exception != null) { + listener.workFailed(work, exception); + } else { + listener.workCompleted(work); + } + } + + /* + * Gets the underlying work from the work event. + */ + private T getWork() { + return work; + } + + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManager.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManager.java new file mode 100644 index 0000000000..1cd70c75de --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManager.java @@ -0,0 +1,228 @@ +/* + * 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.core.work.impl; + +import java.util.Collection; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ThreadFactory; + +import org.apache.tuscany.sca.work.WorkSchedulerException; + +/** + * A thread-pool based implementation for the JSR-237 work manager. + * <p/> + * <p/> + * This implementation supports only local work. + * <p/> + * TODO Elaborate the implementation. </p> + * + * @version $Rev$ $Date$ + */ +public class ThreadPoolWorkManager { + + // Map of work items currently handled by the work manager + private Map<WorkItem, WorkListener> workItems = new ConcurrentHashMap<WorkItem, WorkListener>(); + + // Thread-pool + private ExecutorService executor; + + /** + * Initializes the thread-pool. + * + * @param threadPoolSize Thread-pool size. If the size <1, then a cached pool is created + */ + public ThreadPoolWorkManager(int threadPoolSize) { + ThreadFactory factory = new ThreadFactory() { + public Thread newThread(Runnable r) { + Thread thread = new Thread(r); + thread.setDaemon(true); + return thread; + } + }; + if (threadPoolSize <= 0) { + + // Creates a new Executor, use a custom ThreadFactory that + // creates daemon threads. + executor = Executors.newCachedThreadPool(factory); + } else { + executor = Executors.newFixedThreadPool(threadPoolSize, factory); + } + } + + /** + * Schedules a unit of work asynchronously. + * + * @param work Work that needs to be scheduled. + * @return Work Work item representing the asynchronous work + */ + public WorkItem schedule(Work work) throws IllegalArgumentException { + return schedule(work, null); + } + + /** + * Schedules a unit of work asynchronously. + * + * @param work Work that needs to be scheduled. + * @param workListener Work listener for callbacks. + * @return Work Work item representing the asynchronous work + */ + public WorkItem schedule(Work work, WorkListener workListener) throws IllegalArgumentException { + + WorkItem workItem = new WorkItem(UUID.randomUUID().toString(), work); + if (workListener != null) { + workItems.put(workItem, workListener); + } + workAccepted(workItem, work); + if (scheduleWork(work, workItem)) { + return workItem; + } else { + workItem.setStatus(WorkEvent.WORK_REJECTED); + if (workListener != null) { + workListener.workRejected(new WorkEvent(workItem)); + } + throw new IllegalArgumentException("Unable to schedule work"); + } + } + + /** + * Wait for all the specified units of work to finish. + * + * @param works Units of the work that need to finish. + * @param timeout Timeout for waiting for the units of work to finish. + */ + public boolean waitForAll(Collection works, long timeout) { + throw new UnsupportedOperationException("waitForAll not supported"); + } + + /** + * Wait for any of the specified units of work to finish. + * + * @param works Units of the work that need to finish. + * @param timeout Timeout for waiting for the units of work to finish. + */ + public Collection waitForAny(Collection works, long timeout) { + throw new UnsupportedOperationException("waitForAny not supported"); + } + + /** + * Method provided for subclasses to indicate a work acceptance. + * + * @param workItem Work item representing the work that was accepted. + * @param work Work that was accepted. + */ + private void workAccepted(final WorkItem workItem, final Work work) { + WorkListener listener = workItems.get(workItem); + if (listener != null) { + workItem.setStatus(WorkEvent.WORK_ACCEPTED); + WorkEvent event = new WorkEvent(workItem); + listener.workAccepted(event); + } + } + + /* + * Method to indicate a work start. + */ + private void workStarted(final WorkItem workItem, final Work work) { + WorkListener listener = workItems.get(workItem); + if (listener != null) { + workItem.setStatus(WorkEvent.WORK_STARTED); + WorkEvent event = new WorkEvent(workItem); + listener.workStarted(event); + } + } + + /* + * Method to indicate a work completion. + */ + private void workCompleted(final WorkItem workItem, final Work work) { + workCompleted(workItem, work, null); + } + + /* + * Method to indicate a work completion. + */ + private void workCompleted(final WorkItem workItem, final Work work, final WorkSchedulerException exception) { + WorkListener listener = workItems.get(workItem); + if (listener != null) { + workItem.setStatus(WorkEvent.WORK_COMPLETED); + workItem.setResult(work); + workItem.setException(exception); + WorkEvent event = new WorkEvent(workItem); + listener.workCompleted(event); + workItems.remove(workItem); + } + } + + /* + * Schedules the work using the ThreadPool. + */ + private boolean scheduleWork(final Work work, final WorkItem workItem) { + try { + executor.execute(new DecoratingWork(workItem, work)); + return true; + } catch (RejectedExecutionException ex) { + return false; + } + } + + /* + * Class that decorates the original worker so that it can get callbacks when work is done. + */ + private final class DecoratingWork implements Runnable { + + // Work item for this work. + private WorkItem workItem; + + // The original work. + private Work decoratedWork; + + /* + * Initializes the work item and underlying work. + */ + private DecoratingWork(final WorkItem workItem, final Work decoratedWork) { + this.workItem = workItem; + this.decoratedWork = decoratedWork; + } + + /* + * Overrides the run method. + */ + public void run() { + workStarted(workItem, decoratedWork); + try { + decoratedWork.run(); + workCompleted(workItem, decoratedWork); + } catch (Throwable th) { + workCompleted(workItem, decoratedWork, new WorkSchedulerException(th.getMessage(), th)); + } + } + + } + + public void destroy() { + executor.shutdown(); + } + +} + diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/Work.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/Work.java new file mode 100644 index 0000000000..ca06d0e854 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/Work.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.core.work.impl; + +/** + * JCA work wrapper. + * + * @version $Rev$ $Date$ + */ +public class Work<T extends Runnable> { + + // Work that is being executed. + private T work; + + /* + * Initializes the work instance. + */ + public Work(T work) { + this.work = work; + } + + /* + * Returns the completed work. + */ + public T getWork() { + return work; + } + + /* + * Release the work. + */ + public void release() { + } + + /* + * Work attributes are not daemon. + */ + public boolean isDaemon() { + return false; + } + + /* + * Runs the work. + */ + public void run() { + work.run(); + } +}
\ No newline at end of file diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkEvent.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkEvent.java new file mode 100644 index 0000000000..4580011806 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkEvent.java @@ -0,0 +1,80 @@ +/* + * 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.core.work.impl; + +import org.apache.tuscany.sca.work.WorkSchedulerException; + + + +/** + * Default immutable implementation of the <code>WorkEvent</code> class. + * + * @version $Rev$ $Date$ + */ +class WorkEvent { + + public static final int WORK_ACCEPTED = 1; + public static final int WORK_REJECTED = 2; + public static final int WORK_STARTED = 3; + public static final int WORK_COMPLETED = 4; + + // Work item for this event + private WorkItem workItem; + + // Exception if something has gone wrong + private WorkSchedulerException exception; + + /** + * Instantiates the event. + * + * @param workItem Work item for this event. + */ + public WorkEvent(final WorkItem workItem) { + this.workItem = workItem; + this.exception = workItem.getException(); + } + + /** + * Returns the work type based on whether the work was accepted, started, + * rejected or completed. + * + * @return Work type. + */ + public int getType() { + return workItem.getStatus(); + } + + /** + * Returns the work item associated with this work type. + * + * @return Work item. + */ + public WorkItem getWorkItem() { + return workItem; + } + + /** + * Returns the exception if the work completed with an exception. + * + * @return Work exception. + */ + public WorkSchedulerException getException() { + return exception; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkItem.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkItem.java new file mode 100644 index 0000000000..0fc104d0fc --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkItem.java @@ -0,0 +1,167 @@ +/* + * 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.core.work.impl; + +import org.apache.tuscany.sca.work.WorkSchedulerException; + +/** + * An identity based immutable implementation of the <code>WorkItem</code> + * interface. + * + * @version $Rev$ $Date$ + */ +class WorkItem { + + // Id scoped for the VM + private String id; + + // Status + private int status = -1; + + // Result + private Work<?> result; + + // Original work + private Work<?> originalWork; + + // Exception + private WorkSchedulerException exception; + + /** + * Instantiates an id for this item. + * + * @param id of this work event. + */ + protected WorkItem(final String id, final Work<?> orginalWork) { + this.id = id; + this.originalWork = orginalWork; + } + + /** + * Returns the id. + * + * @return Id of this item. + */ + public String getId() { + return id; + } + + /** + * Returns the original work. + * + * @return Original work. + */ + public Work<?> getOriginalWork() { + return originalWork; + } + + /** + * Returns the work result if the work completed. + * + * @return Work. + * @throws WorkException If the work completed with an exception. + */ + public Work<?> getResult() { + return result; + } + + /** + * Sets the result. + * + * @param result Result. + */ + protected void setResult(final Work<?> result) { + this.result = result; + } + + /** + * Returns the exception if work completed with an exception. + * + * @return Work exception. + */ + protected WorkSchedulerException getException() { + return exception; + } + + /** + * Sets the exception. + * + * @param exception Exception. + */ + protected void setException(final WorkSchedulerException exception) { + this.exception = exception; + } + + /** + * Returns the work type based on whether the work was accepted, started, + * rejected or completed. + * + * @return Work status. + */ + public int getStatus() { + return status; + } + + /** + * Sets the status. + * + * @param status Status. + */ + protected void setStatus(final int status) { + this.status = status; + } + + /** + * @see Object#hashCode() + */ + @Override + public int hashCode() { + return id.hashCode(); + } + + /** + * Indicates whether some other object is "equal to" this one. + * + * @param obj Object to be compared. + * @return true if this object is the same as the obj argument; false + * otherwise.. + */ + @Override + public boolean equals(final Object obj) { + return (obj != null) && (obj.getClass() == WorkItem.class) && ((WorkItem) obj).id.equals(id); + } + + /** + * Compares this object with the specified object for order. Returns a + * negative integer, zero, or a positive integer as this object is less + * than, equal to, or greater than the specified object. + * + * @param o Object to be compared. + * @return A negative integer, zero, or a positive integer as this object + * is less than, equal to, or greater than the specified object. + * @throws ClassCastException needs better documentation. + */ + public int compareTo(final Object o) { + if (o.getClass() != WorkItem.class) { + throw new ClassCastException(o.getClass().getName()); + } else { + return ((WorkItem) o).getId().compareTo(getId()); + } + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkListener.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkListener.java new file mode 100644 index 0000000000..38bbaeebe0 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/java/org/apache/tuscany/sca/core/work/impl/WorkListener.java @@ -0,0 +1,32 @@ +/* + * 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.core.work.impl; + +public interface WorkListener { + + long IMMEDIATE = 0; + long INDEFINITE = java.lang.Long.MAX_VALUE; + + void workAccepted(WorkEvent event); + void workCompleted(WorkEvent event); + void workRejected(WorkEvent event); + void workStarted(WorkEvent event); + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.assembly.AssemblyFactory b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.assembly.AssemblyFactory new file mode 100644 index 0000000000..e8ee318b6c --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.assembly.AssemblyFactory @@ -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.
+# Set the ranking to be greater than the DefaultAssemblyFactory
+org.apache.tuscany.sca.core.assembly.RuntimeAssemblyFactory;ranking=100
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.ComponentContextFactory b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.ComponentContextFactory new file mode 100644 index 0000000000..51ed2449fb --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.ComponentContextFactory @@ -0,0 +1,17 @@ +# 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.
+org.apache.tuscany.sca.core.context.DefaultComponentContextFactory
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.RequestContextFactory b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.RequestContextFactory new file mode 100644 index 0000000000..70b17a2f00 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.RequestContextFactory @@ -0,0 +1,17 @@ +# 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.
+org.apache.tuscany.sca.core.context.DefaultRequestContextFactory
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor new file mode 100644 index 0000000000..94c83ceeab --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor @@ -0,0 +1,20 @@ +# 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 artifact processor extension +org.apache.tuscany.sca.core.assembly.impl.ReferenceParameterProcessor;qname=http://tuscany.apache.org/xmlns/sca/1.1#referenceParameters,model=org.apache.tuscany.sca.runtime.ReferenceParameters +
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint new file mode 100644 index 0000000000..c6567aa904 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint @@ -0,0 +1,19 @@ +# 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.
+
+org.apache.tuscany.sca.core.invocation.DefaultProxyFactoryExtensionPoint
+
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.scope.ScopeRegistry b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.scope.ScopeRegistry new file mode 100644 index 0000000000..2aa000efc0 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.core.scope.ScopeRegistry @@ -0,0 +1,19 @@ +# 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.
+
+org.apache.tuscany.sca.core.scope.DefaultScopeRegistry
+
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.invocation.MessageFactory b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.invocation.MessageFactory new file mode 100644 index 0000000000..a21b75b570 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.invocation.MessageFactory @@ -0,0 +1,19 @@ +# 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.
+
+org.apache.tuscany.sca.core.invocation.impl.MessageFactoryImpl
+
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.CompositeActivator b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.CompositeActivator new file mode 100644 index 0000000000..0182f52086 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.CompositeActivator @@ -0,0 +1,19 @@ +# 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.
+
+org.apache.tuscany.sca.core.assembly.impl.CompositeActivatorImpl
+
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.DomainRegistryFactory b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.DomainRegistryFactory new file mode 100644 index 0000000000..f2a6f0b4c3 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.DomainRegistryFactory @@ -0,0 +1,17 @@ +# 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.
+org.apache.tuscany.sca.core.assembly.impl.LocalDomainRegistryFactory
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointReferenceBinder b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointReferenceBinder new file mode 100644 index 0000000000..61edf5111e --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointReferenceBinder @@ -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.
+org.apache.tuscany.sca.core.runtime.impl.EndpointReferenceBinderImpl
+
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointSerializer b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointSerializer new file mode 100644 index 0000000000..fb951e75d5 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.EndpointSerializer @@ -0,0 +1,17 @@ +# 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.
+org.apache.tuscany.sca.core.assembly.impl.EndpointSerializerImpl
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.RuntimeProperties b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.RuntimeProperties new file mode 100644 index 0000000000..66e0277d59 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.RuntimeProperties @@ -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.
+org.apache.tuscany.sca.core.runtime.impl.RuntimePropertiesImpl
+
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.work.WorkScheduler b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.work.WorkScheduler new file mode 100644 index 0000000000..90e887739a --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/META-INF/services/org.apache.tuscany.sca.work.WorkScheduler @@ -0,0 +1,17 @@ +# 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.
+org.apache.tuscany.sca.core.work.impl.DefaultWorkScheduler;maxThreads=0
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/endpoint-validation-messages.properties b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/endpoint-validation-messages.properties new file mode 100644 index 0000000000..6e12d11d68 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/main/resources/endpoint-validation-messages.properties @@ -0,0 +1,23 @@ +# +# +# 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. +# +# +NoEndpointsFound = No endpoints found in the domain that match the reference {0} +EndpointReferenceCantBeMatched = = Unable to match the endpoint reference {0} with the policy of the service to which it refers, matching process was {1} +ComponentReferenceTargetNotFound = Component reference target not found, it might be a remote service running elsewhere in the SCA Domain: {1} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImplTestCase.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImplTestCase.java new file mode 100644 index 0000000000..1302bed681 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/InvocationChainImplTestCase.java @@ -0,0 +1,93 @@ +/* + * 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.core.invocation.impl; + +import static org.junit.Assert.assertEquals; + +import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.OperationImpl; +import org.apache.tuscany.sca.invocation.Interceptor; +import org.apache.tuscany.sca.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.invocation.Phase; +import org.junit.Test; + +/** + * @version $Rev$ $Date$ + */ +public class InvocationChainImplTestCase { + + @Test + public void testInsertAtEnd() throws Exception { + Operation op = newOperation("foo"); + InvocationChain chain = new InvocationChainImpl(op, op, true, new PhaseManager(new DefaultExtensionPointRegistry())); + Interceptor inter2 = new MockInterceptor(); + Interceptor inter1 = new MockInterceptor(); + chain.addInterceptor(inter1); + chain.addInterceptor(inter2); + Interceptor head = (Interceptor)chain.getHeadInvoker(); + assertEquals(inter1, head); + assertEquals(inter2, head.getNext()); + } + + @Test + public void testAddByPhase() throws Exception { + Operation op = newOperation("foo"); + InvocationChain chain = new InvocationChainImpl(op, op, false, new PhaseManager(new DefaultExtensionPointRegistry())); + Interceptor inter1 = new MockInterceptor(); + Interceptor inter2 = new MockInterceptor(); + Interceptor inter3 = new MockInterceptor(); + Interceptor inter4 = new MockInterceptor(); + chain.addInterceptor(inter3); // SERVICE + chain.addInterceptor(Phase.IMPLEMENTATION_POLICY, inter4); + chain.addInterceptor(Phase.SERVICE_POLICY, inter2); + chain.addInterceptor(Phase.SERVICE_BINDING, inter1); + Interceptor head = (Interceptor)chain.getHeadInvoker(); + assertEquals(inter1, head); + assertEquals(inter2, inter1.getNext()); + assertEquals(inter3, inter2.getNext()); + assertEquals(inter4, inter3.getNext()); + } + + private class MockInterceptor implements Interceptor { + + private Invoker next; + + public Message invoke(Message msg) { + return null; + } + + public void setNext(Invoker next) { + this.next = next; + } + + public Invoker getNext() { + return next; + } + + } + + private static Operation newOperation(String name) { + Operation operation = new OperationImpl(); + operation.setName(name); + return operation; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManagerTestCase.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManagerTestCase.java new file mode 100644 index 0000000000..8fcead004d --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseManagerTestCase.java @@ -0,0 +1,50 @@ +/* + * 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.core.invocation.impl; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +/** + * @version $Rev$ $Date$ + */ +public class PhaseManagerTestCase { + + @Test + public void testDiscovery() { + PhaseManager pm = new PhaseManager("org.apache.tuscany.sca.invocation.PhaseTest"); + List<String> phases = pm.getAllPhases(); + System.out.println(phases.size()); + System.out.println(phases); + // Assert.assertEquals(15, phases.size()); + Assert.assertEquals("reference.first", phases.get(0)); + + int rt = phases.indexOf("reference.transaction"); + Assert.assertTrue(rt > phases.indexOf("reference.interface")); + + int st = phases.indexOf("service.transaction"); + Assert.assertTrue(st > phases.indexOf("service.binding")); + + int it = phases.indexOf("implementation.transaction"); + Assert.assertTrue(it < phases.indexOf("implementation.policy")); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorterTestCase.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorterTestCase.java new file mode 100644 index 0000000000..c268e133e4 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/invocation/impl/PhaseSorterTestCase.java @@ -0,0 +1,67 @@ +/* + * 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.core.invocation.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class PhaseSorterTestCase { + private PhaseSorter<String> graph; + + @Before + public void setUp() throws Exception { + graph = new PhaseSorter<String>(); + } + + @Test + public void testSort() { + graph.addEdge("a", "b"); + graph.addEdge("a", "c"); + graph.addEdge("c", "d"); + graph.addEdge("b", "c"); + List<String> order = graph.topologicalSort(true); + assertEquals(Arrays.asList("a", "b", "c", "d"), order); + assertTrue(!graph.getVertices().isEmpty()); + + graph.addEdge("d", "a"); + try { + order = graph.topologicalSort(true); + assertTrue("Should have failed", false); + } catch (IllegalArgumentException e) { + assertTrue(true); + } + + graph.removeEdge("d", "a"); + order = graph.topologicalSort(false); + assertEquals(Arrays.asList("a", "b", "c", "d"), order); + assertTrue(graph.getVertices().isEmpty()); + } + + @After + public void tearDown() throws Exception { + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/FailingWork.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/FailingWork.java new file mode 100644 index 0000000000..16ca5fd00e --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/FailingWork.java @@ -0,0 +1,54 @@ +/* + * 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.core.work.impl; + + + +/** + * Simple Work item that will throw an exception + * + * @version $Rev$ $Date$ + */ +public class FailingWork extends Work { + + public FailingWork() { + super(null); + } + + /** + * {@inheritDoc} + */ + public boolean isDaemon() { + return false; + } + + /** + * {@inheritDoc} + */ + public void release() { + } + + /** + * Throws an IllegalArgumentException + */ + public void run() { + System.out.println("Starting " + this + " and throwing an Exception"); + throw new IllegalArgumentException("Sample exception from " + this); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyFailingRunnable.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyFailingRunnable.java new file mode 100644 index 0000000000..2d791e5012 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyFailingRunnable.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.core.work.impl; + +/** + * Simple Runnable that throws an IllegalArgumentException + * + * @version $Rev$ $Date$ + */ +public class JSR237MyFailingRunnable extends JSR237MyRunnable { + + /** + * Constructor + */ + public JSR237MyFailingRunnable() { + super(-1); + } + + /** + * Sleeps for a period of time defined by sleepTime + */ + @Override + public void run() { + System.out.println("Starting " + this + " and throwing an Exception"); + throw new IllegalArgumentException("Sample exception from " + this); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnable.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnable.java new file mode 100644 index 0000000000..c0183b6f9b --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnable.java @@ -0,0 +1,71 @@ +/* + * 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.core.work.impl; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Simple Runnable that is used for testing Jsr237WorkScheduler + * + * @version $Rev$ $Date$ + */ +public class JSR237MyRunnable implements Runnable { + + /** + * Count of workAccepted() method calls + */ + private AtomicInteger runCompletedCount = new AtomicInteger(); + + /** + * The amount of time to sleep in the Run loop + */ + private final long sleepTime; + + /** + * Constructor + * + * @param sleepTime The amount of time to sleep (in milliseconds) in the run() method + */ + public JSR237MyRunnable(long sleepTime) { + this.sleepTime = sleepTime; + } + + /** + * Sleeps for a period of time defined by sleepTime + */ + public void run() { + System.out.println("Starting " + this); + try { + Thread.sleep(sleepTime); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("Done " + this); + runCompletedCount.incrementAndGet(); + } + + /** + * Returns the number of completed calls to run() + * + * @return The number of completed calls to run() + */ + public int getRunCompletedCount() { + return runCompletedCount.get(); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnerListener.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnerListener.java new file mode 100644 index 0000000000..307f24aca7 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/JSR237MyRunnerListener.java @@ -0,0 +1,154 @@ +/* + * 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.core.work.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.tuscany.sca.work.NotificationListener; + +/** + * Simple NotificationListener that is used for testing Jsr237WorkScheduler + * + * @version $Rev$ $Date$ + */ +public class JSR237MyRunnerListener implements NotificationListener<JSR237MyRunnable> { + + /** + * Count of workAccepted() method calls + */ + private AtomicInteger workAcceptedCallCount = new AtomicInteger(); + + /** + * Count of workStarted() method calls + */ + private AtomicInteger workStartedCallCount = new AtomicInteger(); + + /** + * Count of workCompleted() method calls + */ + private AtomicInteger workCompletedCallCount = new AtomicInteger(); + + /** + * Count of workFailed() method calls + */ + private AtomicInteger workFailedCallCount = new AtomicInteger(); + + /** + * Count of workRejected() method calls + */ + private AtomicInteger workRejectedCallCount = new AtomicInteger(); + + /** + * List of all exceptions thrown by Work items + */ + private List<Throwable> workExceptions = Collections.synchronizedList(new ArrayList<Throwable>()); + + /** + * {@inheritDoc} + */ + public void workAccepted(JSR237MyRunnable work) { + workAcceptedCallCount.incrementAndGet(); + } + + /** + * {@inheritDoc} + */ + public void workCompleted(JSR237MyRunnable work) { + workCompletedCallCount.incrementAndGet(); + } + + /** + * {@inheritDoc} + */ + public void workFailed(JSR237MyRunnable work, Throwable error) { + workExceptions.add(error); + workFailedCallCount.incrementAndGet(); + } + + /** + * {@inheritDoc} + */ + public void workRejected(JSR237MyRunnable work) { + workRejectedCallCount.incrementAndGet(); + } + + /** + * {@inheritDoc} + */ + public void workStarted(JSR237MyRunnable work) { + workStartedCallCount.incrementAndGet(); + } + + /** + * Returns the number of calls to workAccepted() + * + * @return The number of calls to workAccepted() + */ + public int getWorkAcceptedCallCount() { + return workAcceptedCallCount.get(); + } + + /** + * Returns the number of calls to workStarted() + * + * @return The number of calls to workStarted() + */ + public int getWorkStartedCallCount() { + return workStartedCallCount.get(); + } + + /** + * Returns the number of calls to workCompleted() + * + * @return The number of calls to workCompleted() + */ + public int getWorkCompletedCallCount() { + return workCompletedCallCount.get(); + } + + /** + * Returns the number of calls to workFailed() + * + * @return The number of calls to workFailed() + */ + public int getWorkFailedCallCount() { + return workFailedCallCount.get(); + } + + /** + * Returns the number of calls to workRejected() + * + * @return The number of calls to workRejected() + */ + public int getWorkRejectedCallCount() { + return workRejectedCallCount.get(); + } + + /** + * Returns a List of all exceptions that are thrown by the Work items + * + * @return A List of all exceptions that are thrown by the Work items + */ + public List<Throwable> getWorkExceptions() { + return Collections.unmodifiableList(workExceptions); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/Jsr237WorkSchedulerTestCase.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/Jsr237WorkSchedulerTestCase.java new file mode 100644 index 0000000000..4ec0f55867 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/Jsr237WorkSchedulerTestCase.java @@ -0,0 +1,240 @@ +/* + * 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.core.work.impl; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * Test case for Jsr237WorkScheduler + * + * @version $Rev$ $Date$ + */ +public class Jsr237WorkSchedulerTestCase { + + /** + * Wait up to 20 seconds for the Work units to complete + */ + private static final long WAIT_TIMEOUT = 20000; + + /** + * This is the shared instance of the ThreadPoolWorkManager used by the tests + */ + private static DefaultWorkScheduler workSchedular = null; + + /** + * Setup the Jsr237WorkScheduler + */ + @BeforeClass + public static void setup() { + workSchedular = new DefaultWorkScheduler(null, null); + } + + /** + * Make sure that the Jsr237WorkScheduler is stopped after running the tests + */ + @AfterClass + public static void destroy() { + if (workSchedular != null) { + workSchedular.stop(); + } + } + + /** + * Tests running a single fast job on the Jsr237WorkScheduler + */ + @Test + public void testSingleFastJob() { + // Create the work and register it + JSR237MyRunnable fast = new JSR237MyRunnable(10); + JSR237MyRunnerListener listener = new JSR237MyRunnerListener(); + workSchedular.scheduleWork(fast, listener); + + // Wait for the 1 job to complete + waitForWorkToComplete(listener, 1); + + // Test that the job completed successfully. + Assert.assertEquals(1, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(1, listener.getWorkStartedCallCount()); + Assert.assertEquals(1, listener.getWorkCompletedCallCount()); + Assert.assertEquals(0, listener.getWorkExceptions().size()); + } + + /** + * Tests running a single job that fails on the Jsr237WorkScheduler + */ + @Test + public void testSingleFailingJob() { + // Create the work and register it + JSR237MyFailingRunnable fail = new JSR237MyFailingRunnable(); + JSR237MyRunnerListener listener = new JSR237MyRunnerListener(); + workSchedular.scheduleWork(fail, listener); + + // Wait for the 1 job to complete + waitForWorkToComplete(listener, 1); + + // Test that the job completed successfully. + Assert.assertEquals(1, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(1, listener.getWorkStartedCallCount()); + Assert.assertEquals(0, listener.getWorkCompletedCallCount()); + Assert.assertEquals(1, listener.getWorkFailedCallCount()); + Assert.assertEquals(1, listener.getWorkExceptions().size()); + } + + /** + * Tests running a mixture of fast and slow jobs on the Jsr237WorkScheduler + */ + @Test + public void testMultipleJobs() { + // Create the work and register it + JSR237MyRunnable fast1 = new JSR237MyRunnable(5); + JSR237MyRunnable fast2 = new JSR237MyRunnable(10); + JSR237MyRunnable fast3 = new JSR237MyRunnable(20); + JSR237MyRunnable slow1= new JSR237MyRunnable(200); + JSR237MyRunnable slow2 = new JSR237MyRunnable(200); + JSR237MyRunnerListener listener = new JSR237MyRunnerListener(); + workSchedular.scheduleWork(fast1, listener); + workSchedular.scheduleWork(fast2, listener); + workSchedular.scheduleWork(fast3, listener); + workSchedular.scheduleWork(slow1, listener); + workSchedular.scheduleWork(slow2, listener); + + // Wait for the 5 jobs to complete + waitForWorkToComplete(listener, 5); + + // Test that the job completed successfully. + Assert.assertEquals(5, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(5, listener.getWorkStartedCallCount()); + Assert.assertEquals(5, listener.getWorkCompletedCallCount()); + Assert.assertEquals(0, listener.getWorkExceptions().size()); + } + + /** + * Tests running a mixture of fast and slow jobs some of which fail on the + * Jsr237WorkScheduler + */ + @Test + public void testMultipleJobsSomeFail() { + // Create the work and register it + JSR237MyRunnable fast1 = new JSR237MyRunnable(5); + JSR237MyRunnable fast2 = new JSR237MyRunnable(10); + JSR237MyRunnable fast3 = new JSR237MyRunnable(20); + JSR237MyRunnable slow1= new JSR237MyRunnable(200); + JSR237MyRunnable slow2 = new JSR237MyRunnable(200); + JSR237MyFailingRunnable fail1 = new JSR237MyFailingRunnable(); + JSR237MyFailingRunnable fail2 = new JSR237MyFailingRunnable(); + JSR237MyRunnerListener listener = new JSR237MyRunnerListener(); + workSchedular.scheduleWork(fast1, listener); + workSchedular.scheduleWork(fast2, listener); + workSchedular.scheduleWork(fail1, listener); + workSchedular.scheduleWork(fast3, listener); + workSchedular.scheduleWork(slow1, listener); + workSchedular.scheduleWork(fail2, listener); + workSchedular.scheduleWork(slow2, listener); + + // Wait for the 7 jobs to complete + waitForWorkToComplete(listener, 7); + + // Test that the job completed successfully. + Assert.assertEquals(7, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(7, listener.getWorkStartedCallCount()); + Assert.assertEquals(5, listener.getWorkCompletedCallCount()); + Assert.assertEquals(2, listener.getWorkFailedCallCount()); + Assert.assertEquals(2, listener.getWorkExceptions().size()); + } + + /** + * Tests running a single job that has no listener + */ + @Test + public void testSingleFastJobWithNoListener() { + // Create the work and register it + JSR237MyRunnable fast = new JSR237MyRunnable(10); + workSchedular.scheduleWork(fast); + + // Wait for the job to complete + long startTime = System.currentTimeMillis(); + while (true) { + int completedCount = fast.getRunCompletedCount(); + if (completedCount == 1) { + break; + } + + if (System.currentTimeMillis() - startTime > WAIT_TIMEOUT) { + Assert.fail("Only " + completedCount + " work items completed before timeout"); + return; + } + + // Lets wait for the job to complete + try { + Thread.sleep(25); + } catch (InterruptedException ex) { + Assert.fail("Unexpected exception: " + ex); + } + } + } + + /** + * Tests scheduling a null as the work item + */ + @Test + public void testNullWork() { + try { + workSchedular.scheduleWork(null); + Assert.fail("Should have thrown IllegalArgumentException "); + } catch (IllegalArgumentException ex) { + // As expected + Assert.assertTrue(ex.toString().indexOf("null") != -1); + } + } + + /** + * Waits for the specified number of jobs to complete or the timeout to fire. + * + * @param listener The listener to use to track Work unit completion + * @param completedWorkItemsToWaitFor The number of Work items to complete + */ + private void waitForWorkToComplete(JSR237MyRunnerListener listener, int completedWorkItemsToWaitFor) { + long startTime = System.currentTimeMillis(); + while (true) { + int completedCount = listener.getWorkCompletedCallCount() + listener.getWorkFailedCallCount(); + if (completedCount == completedWorkItemsToWaitFor) { + return; + } + + if (System.currentTimeMillis() - startTime > WAIT_TIMEOUT) { + Assert.fail("Only " + completedCount + " work items completed before timeout"); + return; + } + + // Lets wait for more jobs to complete + try { + Thread.sleep(25); + } catch (InterruptedException ex) { + Assert.fail("Unexpected exception: " + ex); + } + } + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TestWorkListener.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TestWorkListener.java new file mode 100644 index 0000000000..a452d6f371 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TestWorkListener.java @@ -0,0 +1,153 @@ +/* + * 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.core.work.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.tuscany.sca.work.WorkSchedulerException; +import org.junit.Assert; + +/** + * A simple WorkListener that tracks invocations to it. + * + * @version $Rev$ $Date$ + */ +public class TestWorkListener implements WorkListener { + + /** + * Count of workAccepted() method calls + */ + private AtomicInteger workAcceptedCallCount = new AtomicInteger(); + + /** + * Count of workStarted() method calls + */ + private AtomicInteger workStartedCallCount = new AtomicInteger(); + + /** + * Count of workCompleted() method calls + */ + private AtomicInteger workCompletedCallCount = new AtomicInteger(); + + /** + * Count of workRejected() method calls + */ + private AtomicInteger workRejectedCallCount = new AtomicInteger(); + + /** + * List of all exceptions thrown by Work items + */ + private List<WorkSchedulerException> workExceptions = Collections.synchronizedList(new ArrayList<WorkSchedulerException>()); + + /** + * {@inheritDoc} + */ + public void workAccepted(WorkEvent work) { + workAcceptedCallCount.incrementAndGet(); + + // Validate the WorkEvent + Assert.assertNotNull(work.getWorkItem()); + Assert.assertEquals(WorkEvent.WORK_ACCEPTED, work.getType()); + } + + /** + * {@inheritDoc} + */ + public void workStarted(WorkEvent work) { + workStartedCallCount.incrementAndGet(); + + // Validate the WorkEvent + Assert.assertNotNull(work.getWorkItem()); + Assert.assertEquals(WorkEvent.WORK_STARTED, work.getType()); + } + + /** + * {@inheritDoc} + */ + public void workCompleted(WorkEvent work) { + if (work.getException() != null) { + workExceptions.add(work.getException()); + } + + // Validate the WorkEvent + Assert.assertNotNull(work.getWorkItem()); + Assert.assertEquals(WorkEvent.WORK_COMPLETED, work.getType()); + + workCompletedCallCount.incrementAndGet(); + } + + /** + * {@inheritDoc} + */ + public void workRejected(WorkEvent work) { + workRejectedCallCount.incrementAndGet(); + + // Validate the WorkEvent + Assert.assertNotNull(work.getWorkItem()); + Assert.assertEquals(WorkEvent.WORK_REJECTED, work.getType()); + } + + /** + * Returns the number of calls to workAccepted() + * + * @return The number of calls to workAccepted() + */ + public int getWorkAcceptedCallCount() { + return workAcceptedCallCount.get(); + } + + /** + * Returns the number of calls to workStarted() + * + * @return The number of calls to workStarted() + */ + public int getWorkStartedCallCount() { + return workStartedCallCount.get(); + } + + /** + * Returns the number of calls to workCompleted() + * + * @return The number of calls to workCompleted() + */ + public int getWorkCompletedCallCount() { + return workCompletedCallCount.get(); + } + + /** + * Returns the number of calls to workRejected() + * + * @return The number of calls to workRejected() + */ + public int getWorkRejectedCallCount() { + return workRejectedCallCount.get(); + } + + /** + * Returns a List of all exceptions that are thrown by the Work items + * + * @return A List of all exceptions that are thrown by the Work items + */ + public List<WorkSchedulerException> getWorkExceptions() { + return Collections.unmodifiableList(workExceptions); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManagerTestCase.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManagerTestCase.java new file mode 100644 index 0000000000..122609d7e6 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/ThreadPoolWorkManagerTestCase.java @@ -0,0 +1,227 @@ +/* + * 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.core.work.impl; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * This test case will test the ThreadPoolWorkManager + * + * @version $Rev$ $Date$ + */ +public class ThreadPoolWorkManagerTestCase { + + /** + * Wait up to 20 seconds for the Work units to complete + */ + private static final long WAIT_TIMEOUT = 20000; + + /** + * This is the shared instance of the ThreadPoolWorkManager used by the tests + */ + private static ThreadPoolWorkManager workManager = null; + + /** + * Setup the ThreadPoolWorkManager + */ + @BeforeClass + public static void setup() { + workManager = new ThreadPoolWorkManager(10); + } + + /** + * Make sure that the ThreadPoolWorkManager is stopped after running the tests + */ + @AfterClass + public static void destroy() { + if (workManager != null) { + workManager.destroy(); + } + } + + /** + * Tests running a single fast job on the ThreadPoolWorkManager + */ + @Test + public void testSingleFastJob() { + // Create the work and register it + TimeDelayWork fast = new TimeDelayWork(10); + TestWorkListener listener = new TestWorkListener(); + workManager.schedule(fast, listener); + + // Wait for the 1 job to complete + waitForWorkToComplete(listener, 1); + + // Test that the job completed successfully. + Assert.assertEquals(1, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(1, listener.getWorkStartedCallCount()); + Assert.assertEquals(1, listener.getWorkCompletedCallCount()); + Assert.assertEquals(0, listener.getWorkExceptions().size()); + } + + /** + * Tests running a single job that fails on the ThreadPoolWorkManager + */ + @Test + public void testSingleFailingJob() { + // Create the work and register it + FailingWork fail = new FailingWork(); + TestWorkListener listener = new TestWorkListener(); + workManager.schedule(fail, listener); + + // Wait for the 1 job to complete + waitForWorkToComplete(listener, 1); + + // Test that the job completed successfully. + Assert.assertEquals(1, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(1, listener.getWorkStartedCallCount()); + Assert.assertEquals(1, listener.getWorkCompletedCallCount()); + Assert.assertEquals(1, listener.getWorkExceptions().size()); + } + + /** + * Tests running a mixture of fast and slow jobs on the ThreadPoolWorkManager + */ + @Test + public void testMultipleJobs() { + // Create the work and register it + TimeDelayWork fast1 = new TimeDelayWork(5); + TimeDelayWork fast2 = new TimeDelayWork(10); + TimeDelayWork fast3 = new TimeDelayWork(20); + TimeDelayWork slow1= new TimeDelayWork(200); + TimeDelayWork slow2 = new TimeDelayWork(200); + TestWorkListener listener = new TestWorkListener(); + workManager.schedule(fast1, listener); + workManager.schedule(fast2, listener); + workManager.schedule(fast3, listener); + workManager.schedule(slow1, listener); + workManager.schedule(slow2, listener); + + // Wait for the 5 jobs to complete + waitForWorkToComplete(listener, 5); + + // Test that the job completed successfully. + Assert.assertEquals(5, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(5, listener.getWorkStartedCallCount()); + Assert.assertEquals(5, listener.getWorkCompletedCallCount()); + Assert.assertEquals(0, listener.getWorkExceptions().size()); + } + + /** + * Tests running a mixture of fast and slow jobs some of which fail on the + * ThreadPoolWorkManager + */ + @Test + public void testMultipleJobsSomeFail() { + // Create the work and register it + TimeDelayWork fast1 = new TimeDelayWork(5); + TimeDelayWork fast2 = new TimeDelayWork(10); + TimeDelayWork fast3 = new TimeDelayWork(20); + TimeDelayWork slow1= new TimeDelayWork(200); + TimeDelayWork slow2 = new TimeDelayWork(200); + FailingWork fail1 = new FailingWork(); + FailingWork fail2 = new FailingWork(); + TestWorkListener listener = new TestWorkListener(); + workManager.schedule(fast1, listener); + workManager.schedule(fast2, listener); + workManager.schedule(fail1, listener); + workManager.schedule(fast3, listener); + workManager.schedule(slow1, listener); + workManager.schedule(fail2, listener); + workManager.schedule(slow2, listener); + + // Wait for the 7 jobs to complete + waitForWorkToComplete(listener, 7); + + // Test that the job completed successfully. + Assert.assertEquals(7, listener.getWorkAcceptedCallCount()); + Assert.assertEquals(0, listener.getWorkRejectedCallCount()); + Assert.assertEquals(7, listener.getWorkStartedCallCount()); + Assert.assertEquals(7, listener.getWorkCompletedCallCount()); + Assert.assertEquals(2, listener.getWorkExceptions().size()); + } + + /** + * Tests running a single job that has no listener + */ + @Test + public void testSingleFastJobWithNoListener() { + // Create the work and register it + TimeDelayWork fast = new TimeDelayWork(10); + workManager.schedule(fast); + + // Wait for the job to complete + long startTime = System.currentTimeMillis(); + while (true) { + int completedCount = fast.getRunCompletedCount(); + if (completedCount == 1) { + break; + } + + if (System.currentTimeMillis() - startTime > WAIT_TIMEOUT) { + Assert.fail("Only " + completedCount + " work items completed before timeout"); + return; + } + + // Lets wait for the job to complete + try { + Thread.sleep(25); + } catch (InterruptedException ex) { + Assert.fail("Unexpected exception: " + ex); + } + } + + // Make sure we have got one completed run + Assert.assertEquals(1, fast.getRunCompletedCount()); + } + + /** + * Waits for the specified number of jobs to complete or the timeout to fire. + * + * @param listener The listener to use to track Work unit completion + * @param completedWorkItemsToWaitFor The number of Work items to complete + */ + private void waitForWorkToComplete(TestWorkListener listener, int completedWorkItemsToWaitFor) { + long startTime = System.currentTimeMillis(); + while (true) { + int completedCount = listener.getWorkCompletedCallCount(); + if (completedCount == completedWorkItemsToWaitFor) { + return; + } + + if (System.currentTimeMillis() - startTime > WAIT_TIMEOUT) { + Assert.fail("Only " + completedCount + " work items completed before timeout"); + return; + } + + // Lets wait for more jobs to complete + try { + Thread.sleep(25); + } catch (InterruptedException ex) { + Assert.fail("Unexpected exception: " + ex); + } + } + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TimeDelayWork.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TimeDelayWork.java new file mode 100644 index 0000000000..f6435659ef --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/core/work/impl/TimeDelayWork.java @@ -0,0 +1,86 @@ +/* + * 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.core.work.impl; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Simple Work item that will sleep in the run() method for the specified + * period of time + * + * @version $Rev$ $Date$ + */ +public class TimeDelayWork extends Work { + + /** + * Count of completed run() method calls + */ + private AtomicInteger runCompletedCount = new AtomicInteger(); + + /** + * The amount of time to sleep in the Run loop + */ + private final long sleepTime; + + /** + * Constructor + * + * @param sleepTime The amount of time to sleep (in milliseconds) in the run() method + */ + public TimeDelayWork(long sleepTime) { + super(null); + this.sleepTime = sleepTime; + } + + /** + * {@inheritDoc} + */ + public boolean isDaemon() { + return false; + } + + /** + * {@inheritDoc} + */ + public void release() { + } + + /** + * Sleeps for a period of time defined by sleepTime + */ + public void run() { + System.out.println("Starting " + this); + try { + Thread.sleep(sleepTime); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("Done " + this); + runCompletedCount.incrementAndGet(); + } + + /** + * Returns the number of completed calls to run() + * + * @return The number of completed calls to run() + */ + public int getRunCompletedCount() { + return runCompletedCount.get(); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/scope/ScopeTestCase.java b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/scope/ScopeTestCase.java new file mode 100644 index 0000000000..ca7bf9b3d7 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/java/org/apache/tuscany/sca/scope/ScopeTestCase.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.scope; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.apache.tuscany.sca.core.scope.Scope; +import org.junit.Test; +/** + * @version $Rev$ $Date$ + */ +public class ScopeTestCase { + + @Test + public void testEquals() throws Exception { + Scope scope = new Scope("COMPOSITE"); + assertTrue(scope.equals(Scope.COMPOSITE)); + } + + @Test + public void testEqualsNew() throws Exception { + Scope foo = new Scope("foo"); + Scope foo2 = new Scope("FOO"); + assertTrue(foo.equals(foo2)); + } + + @Test + public void testNotEquals() throws Exception { + Scope foo = new Scope("BAR"); + Scope foo2 = new Scope("FOO"); + assertFalse(foo.equals(foo2)); + } + + @Test + public void testNotEqualsDifferent() throws Exception { + Scope foo = new Scope("FOO"); + assertFalse(foo.equals(new Bar("FOO"))); + } + + public class Bar { + String scope; + + public Bar(String scope) { + this.scope = scope; + } + } + + +} diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/resources/META-INF/services/org.apache.tuscany.sca.invocation.PhaseTest b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/resources/META-INF/services/org.apache.tuscany.sca.invocation.PhaseTest new file mode 100644 index 0000000000..ad23df3761 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/core/src/test/resources/META-INF/services/org.apache.tuscany.sca.invocation.PhaseTest @@ -0,0 +1,24 @@ +# 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.
+
+name=implementation.last, stage=implementation, after=*
+name=reference.first, stage=reference, before=*
+name=reference.transaction, stage=reference, after=reference.interface
+name=reference.binding.header, stage=reference.binding, after=reference.binding.transport
+name=service.binding.header, stage=service.binding, after=service.binding.transport
+name=service.transaction, stage=service, after=service.binding, before=component.service
+name=implementation.transaction, stage=implementation, before=implementation.policy
|