diff options
Diffstat (limited to 'sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime')
62 files changed, 5652 insertions, 0 deletions
diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/LICENSE b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/LICENSE new file mode 100644 index 0000000000..8aa906c321 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/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-Beta3/modules/implementation-java-runtime/META-INF/MANIFEST.MF b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..4ba430760a --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/META-INF/MANIFEST.MF @@ -0,0 +1,71 @@ +Manifest-Version: 1.0
+Export-Package: org.apache.tuscany.sca.implementation.java.context;version="2.0.0";
+ uses:="org.apache.tuscany.sca.core.context,
+ org.apache.tuscany.sca.core.factory,
+ org.apache.tuscany.sca.implementation.java,
+ org.apache.tuscany.sca.core.scope,
+ org.apache.tuscany.sca.implementation.java.injection",
+ org.apache.tuscany.sca.implementation.java.injection;version="2.0.0";
+ uses:="org.apache.tuscany.sca.databinding,
+ org.apache.tuscany.sca.databinding.xml,
+ org.apache.tuscany.sca.runtime,
+ org.apache.tuscany.sca.interfacedef.util,
+ org.apache.tuscany.sca.assembly,
+ org.apache.tuscany.sca.context,
+ org.apache.tuscany.sca.databinding.impl,
+ org.apache.tuscany.sca.core.context,
+ org.apache.tuscany.sca.implementation.java.introspect,
+ org.apache.tuscany.sca.implementation.java,
+ org.apache.tuscany.sca.interfacedef,
+ org.w3c.dom,
+ javax.xml.namespace,
+ org.apache.tuscany.sca.invocation,
+ org.apache.tuscany.sca.core.factory,
+ org.apache.tuscany.sca.interfacedef.impl,
+ org.oasisopen.sca,
+ org.apache.tuscany.sca.core.invocation",
+ org.apache.tuscany.sca.implementation.java.invocation;version="2.0.0"
+Private-Package: org.apache.tuscany.sca.implementation.java.invocation
+ ;version="2.0.0",org.apache.tuscany.sca.implementation.java.module;vers
+ ion="2.0.0"
+SCA-Version: 1.1
+Bundle-Name: Apache Tuscany SCA Java Implementation Model
+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 Java Implementation Model
+Import-Package: javax.xml.namespace,
+ org.apache.tuscany.sca.assembly;version="2.0.0",
+ org.apache.tuscany.sca.common.xml.dom;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.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.databinding;version="2.0.0",
+ org.apache.tuscany.sca.databinding.impl;version="2.0.0",
+ org.apache.tuscany.sca.databinding.xml;version="2.0.0",
+ org.apache.tuscany.sca.implementation.java;version="2.0.0",
+ org.apache.tuscany.sca.implementation.java.context;version="2.0.0",
+ org.apache.tuscany.sca.implementation.java.injection;version="2.0.0",
+ org.apache.tuscany.sca.implementation.java.introspect;version="2.0.0",
+ org.apache.tuscany.sca.implementation.java.invocation;resolution:=optional,
+ org.apache.tuscany.sca.interfacedef;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef.impl;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef.java;version="2.0.0",
+ org.apache.tuscany.sca.interfacedef.java.impl;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.policy;version="2.0.0",
+ org.apache.tuscany.sca.policy.util;version="2.0.0",
+ org.apache.tuscany.sca.provider;version="2.0.0",
+ org.apache.tuscany.sca.runtime;version="2.0.0",
+ org.oasisopen.sca;version="2.0.0",
+ org.oasisopen.sca.annotation;version="2.0.0",
+ org.w3c.dom
+Bundle-SymbolicName: org.apache.tuscany.sca.implementation.java.runtim
+ e
+Bundle-DocURL: http://www.apache.org/
+Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6 diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/NOTICE b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/NOTICE new file mode 100644 index 0000000000..d69e595698 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/NOTICE @@ -0,0 +1,6 @@ +${pom.name} +Copyright (c) 2005 - 2011 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-Beta3/modules/implementation-java-runtime/pom.xml b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/pom.xml new file mode 100644 index 0000000000..6f5c9cebf0 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/pom.xml @@ -0,0 +1,57 @@ +<?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-Beta3-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>tuscany-implementation-java-runtime</artifactId> + <name>Apache Tuscany SCA Implementation Java Runtime</name> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core-spi</artifactId> + <version>2.0-Beta3-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-implementation-java</artifactId> + <version>2.0-Beta3-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-databinding</artifactId> + <version>2.0-Beta3-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-core</artifactId> + <version>2.0-Beta3-SNAPSHOT</version> + </dependency> + </dependencies> + +</project> diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactory.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactory.java new file mode 100644 index 0000000000..e2d99852d8 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactory.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.implementation.java.context; + +import org.apache.tuscany.sca.core.factory.InstanceWrapper; + +/** + * Interface for a factory that returns an injected component instance. + * This is used by a Component implementation to create new instances of + * application implementation objects as determined by the component scope's + * lifecycle. + * <p/> + * The implementation of this interface may be supplied by the user, + * may be generated during deployment, or may be dynamic. + * + * @version $Rev$ $Date$ + * @param <T> Type of the instance generated by the factory. + */ +public interface InstanceFactory<T> { + /** + * Creates a new instance of the component. + * All injected values must be set but any @Init methods must not have been invoked. + * + * @return A wrapper for the created component instance. + */ + InstanceWrapper<T> newInstance(); +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactoryProvider.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactoryProvider.java new file mode 100644 index 0000000000..df21e013f1 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/InstanceFactoryProvider.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.implementation.java.context; + +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.implementation.java.JavaElementImpl; + +/** + * @version $Rev$ $Date$ + */ +public interface InstanceFactoryProvider<T> { + /** + * Return the implementation class. + * + * @return the implementation class. + */ + Class<T> getImplementationClass(); + + /** + * Sets an object factory for an injection site + * + * @param element the injection site name + * @param objectFactory the object factory + */ + void setObjectFactory(JavaElementImpl element, ObjectFactory<?> objectFactory); + + /** + * Create an instance factory that can be used to create component instances. + * + * @return a new instance factory + */ + InstanceFactory<T> createFactory(); +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceFactory.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceFactory.java new file mode 100644 index 0000000000..f5d9860130 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceFactory.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.context; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import org.apache.tuscany.sca.core.factory.InstanceWrapper; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.Injector; +import org.apache.tuscany.sca.implementation.java.invocation.EventInvoker; + +/** + * @version $Rev$ $Date$ + */ +public class ReflectiveInstanceFactory<T> implements InstanceFactory<T> { + private final Constructor<T> ctr; + private final ObjectFactory<?>[] ctrArgs; + private final Injector<T>[] injectors; + private final EventInvoker<T> initInvoker; + private final EventInvoker<T> destroyInvoker; + private final Injector<T>[] callbackInjectors; + + public ReflectiveInstanceFactory(Constructor<T> ctr, + ObjectFactory<?>[] ctrArgs, + Injector<T>[] injectors, + Injector<T>[] callbackInjectors, + EventInvoker<T> initInvoker, + EventInvoker<T> destroyInvoker) { + this.ctr = ctr; + this.ctrArgs = ctrArgs; + this.injectors = injectors; + this.callbackInjectors = callbackInjectors; + this.initInvoker = initInvoker; + this.destroyInvoker = destroyInvoker; + } + + public InstanceWrapper<T> newInstance() { + T instance; + try { + if (ctrArgs != null) { + Object[] args = new Object[ctrArgs.length]; + for (int i = 0; i < args.length; i++) { + args[i] = ctrArgs[i].getInstance(); + } + instance = ctr.newInstance(args); + } else { + instance = ctr.newInstance(); + } + } catch (InstantiationException e) { + String name = ctr.getDeclaringClass().getName(); + throw new AssertionError("Class is not instantiable [" + name + "]"); + } catch (IllegalAccessException e) { + String name = ctr.getName(); + throw new AssertionError("Constructor is not accessible [" + name + "]"); + } catch ( + InvocationTargetException e) { + String name = ctr.getName(); + throw new ObjectCreationException("Exception thrown by constructor: " + name, e); + } + + if (injectors != null) { + for (Injector<T> injector : injectors) { + //FIXME Injectors should never be null + if (injector != null) + try { + injector.inject(instance); + } catch (Exception e) { + if (destroyInvoker != null) { + destroyInvoker.invokeEvent(instance); + } + throw new ObjectCreationException("Exception invoking injector - " + e.getMessage(), e); + } + } + } + + return new ReflectiveInstanceWrapper<T>(instance, initInvoker, destroyInvoker, callbackInjectors); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapper.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapper.java new file mode 100644 index 0000000000..a3ed16dde5 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapper.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.implementation.java.context; + +import org.apache.tuscany.sca.core.factory.InstanceWrapper; +import org.apache.tuscany.sca.core.scope.TargetDestructionException; +import org.apache.tuscany.sca.core.scope.TargetInitializationException; +import org.apache.tuscany.sca.implementation.java.injection.Injector; +import org.apache.tuscany.sca.implementation.java.invocation.EventInvoker; + +/** + * @version $Rev$ $Date$ + */ +public class ReflectiveInstanceWrapper<T> implements InstanceWrapper<T> { + private final EventInvoker<T> initInvoker; + private final EventInvoker<T> destroyInvoker; + private final T instance; + private final Injector<T>[] callbackInjectors; + + public ReflectiveInstanceWrapper(T instance, EventInvoker<T> initInvoker, EventInvoker<T> destroyInvoker, Injector<T>[] callbackInjectors) { + this.instance = instance; + this.initInvoker = initInvoker; + this.destroyInvoker = destroyInvoker; + this.callbackInjectors = callbackInjectors; + } + + public T getInstance() { + return instance; + } + + public void start() throws TargetInitializationException { + if (initInvoker != null) { + try { + initInvoker.invokeEvent(instance); + } catch (Exception e) { + try { + stop(); + } catch (TargetDestructionException e1) { + throw new TargetInitializationException("TargetDestructionException while handling init exception", e); + } + throw new TargetInitializationException(e); + } + } + } + + public void stop() throws TargetDestructionException { + if (destroyInvoker != null) { + destroyInvoker.invokeEvent(instance); + } + } + + public Injector<T>[] getCallbackInjectors() { + return this.callbackInjectors; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/databinding/PropertyDataTypeProcessor.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/databinding/PropertyDataTypeProcessor.java new file mode 100644 index 0000000000..16de5bbefb --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/databinding/PropertyDataTypeProcessor.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.implementation.java.databinding; + +import org.apache.tuscany.sca.assembly.Property; +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.implementation.java.IntrospectionException; +import org.apache.tuscany.sca.implementation.java.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.introspect.BaseJavaClassVisitor; +import org.apache.tuscany.sca.implementation.java.introspect.JavaIntrospectionHelper; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * + */ +public class PropertyDataTypeProcessor extends BaseJavaClassVisitor { + private Mediator mediator; + + /** + * @param registry + */ + public PropertyDataTypeProcessor(ExtensionPointRegistry registry) { + super(registry); + UtilityExtensionPoint utilityExtensionPoint = registry.getExtensionPoint(UtilityExtensionPoint.class); + this.mediator = utilityExtensionPoint.getUtility(Mediator.class); + } + + /** + * Introspect the property + * @param javaElement + * @return + */ + private void introspect(Property property, JavaElementImpl javaElement) { + // XMLType xmlType = new XMLType(property.getXSDElement(), property.getXSDType()); + // property.getDataType().setLogical(xmlType); + mediator.getDataBindings().introspectType(property.getDataType(), null); + } + + @Override + public <T> void visitEnd(Class<T> clazz, JavaImplementation type) throws IntrospectionException { + for (Property property : type.getProperties()) { + String name = property.getName(); + JavaElementImpl element = type.getPropertyMembers().get(name); + introspect(property, element); + DataType dt = property.getDataType(); + if (dt.getLogical() instanceof XMLType) { + XMLType xmlType = (XMLType)dt.getLogical(); + property.setXSDType(xmlType.getTypeName()); + property.setXSDElement(xmlType.getElementName()); + } else { + Class<?> baseType = JavaIntrospectionHelper.getBaseType(element.getType(), element.getGenericType()); + property.setXSDType(JavaXMLMapper.getXMLType(baseType)); + } + } + super.visitEnd(clazz, type); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ArrayMultiplicityObjectFactory.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ArrayMultiplicityObjectFactory.java new file mode 100644 index 0000000000..2513c63e38 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ArrayMultiplicityObjectFactory.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.implementation.java.injection; + +import java.lang.reflect.Array; +import java.util.List; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; + +/** + * Resolves targets configured in a multiplicity by delegating to object factories and returning an <code>Array</code> + * containing object instances + * + * @version $Rev$ $Date$ + */ +public class ArrayMultiplicityObjectFactory implements ObjectFactory<Object> { + + private ObjectFactory[] factories; + + private Class interfaceType; + + public ArrayMultiplicityObjectFactory(Class interfaceType, List<ObjectFactory<?>> factories) { + assert interfaceType != null : "Interface type was null"; + assert factories != null : "Object factories were null"; + this.interfaceType = interfaceType; + this.factories = factories.toArray(new ObjectFactory[factories.size()]); + } + + public Object getInstance() throws ObjectCreationException { + Object array = Array.newInstance(interfaceType, factories.length); + for (int i = 0; i < factories.length; i++) { + Array.set(array, i, factories[i].getInstance()); + } + return array; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ContextInjector.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ContextInjector.java new file mode 100644 index 0000000000..d8eef18c74 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ContextInjector.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.implementation.java.injection; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; + +/** + * Implementations inject a pre-configured context type (interface) on an instance. + * + * @version $Rev$ $Date$ + */ +public interface ContextInjector<S, T> extends Injector<T> { + + void setContext(S context) throws ObjectCreationException; + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/FieldInjector.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/FieldInjector.java new file mode 100644 index 0000000000..4d97e72bd0 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/FieldInjector.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.implementation.java.injection; + +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; + +/** + * Injects a value created by an {@link org.apache.tuscany.sca.core.factory.ObjectFactory} on a given field + * + * @version $Rev$ $Date$ + */ +public class FieldInjector<T> implements Injector<T> { + + private final Field field; + + private final ObjectFactory<?> objectFactory; + + /** + * Create an injector and have it use the given <code>ObjectFactory</code> to inject a value on the instance using + * the reflected <code>Field</code> + */ + public FieldInjector(Field pField, ObjectFactory<?> objectFactory) { + field = pField; + // Allow privileged access to set accessibility. Requires ReflectPermission + // in security policy. + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + field.setAccessible(true); // ignore Java accessibility + return null; + } + }); + + this.objectFactory = objectFactory; + } + + /** + * Inject a new value on the given instance + */ + public void inject(T instance) throws ObjectCreationException { + inject(instance, objectFactory.getInstance()); + } + + public void inject(T instance, Object value) { + try { + field.set(instance, value); + } catch (IllegalAccessException e) { + throw new ObjectCreationException("Field is not accessible [" + field + "]", e); + } + } + + public Class<?> getType() { + return field.getType(); + } + + public Type getGenericType() { + return field.getGenericType(); + } + + public void injectNull(T instance) throws ObjectCreationException { + inject(instance, null); + } + + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InjectionRuntimeException.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InjectionRuntimeException.java new file mode 100644 index 0000000000..8bc2dce76c --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InjectionRuntimeException.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.implementation.java.injection; + + +/** + * Root unchecked exception for the injection package + * + * @version $Rev$ $Date$ + * @tuscany.spi.extension.inheritfrom + */ +public abstract class InjectionRuntimeException extends RuntimeException { + private static final long serialVersionUID = -2264137603099898773L; + + public InjectionRuntimeException() { + super(); + } + + public InjectionRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + public InjectionRuntimeException(String message) { + super(message); + } + + public InjectionRuntimeException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/Injector.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/Injector.java new file mode 100644 index 0000000000..f0208c4e71 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/Injector.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.implementation.java.injection; + +import java.lang.reflect.Type; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; + +/** + * Implementations inject a pre-configured value on an instance + * + * @version $Rev$ $Date$ + */ +public interface Injector<T> { + + /** + * Inject a value on the given instance + */ + void inject(T instance) throws ObjectCreationException; + void injectNull(T instance) throws ObjectCreationException; + Class<?> getType(); + Type getGenericType(); + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InvalidAccessorException.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InvalidAccessorException.java new file mode 100644 index 0000000000..5aeebcca36 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/InvalidAccessorException.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.implementation.java.injection; + +/** + * @version $Rev$ $Date$ + */ +public class InvalidAccessorException extends InjectionRuntimeException { + private static final long serialVersionUID = 9196299279363310978L; + + public InvalidAccessorException() { + super(); + } + + public InvalidAccessorException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidAccessorException(String message) { + super(message); + } + + public InvalidAccessorException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/JavaPropertyValueObjectFactory.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/JavaPropertyValueObjectFactory.java new file mode 100644 index 0000000000..acacd23d8f --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/JavaPropertyValueObjectFactory.java @@ -0,0 +1,371 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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.implementation.java.injection; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +import org.apache.tuscany.sca.assembly.ComponentProperty; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.common.xml.dom.DOMHelper; +import org.apache.tuscany.sca.context.PropertyValueFactory; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.databinding.SimpleTypeMapper; +import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl; +import org.apache.tuscany.sca.databinding.xml.DOMDataBinding; +import org.apache.tuscany.sca.implementation.java.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.introspect.JavaIntrospectionHelper; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.TypeInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * + * @version $Rev$ $Date$ + */ +public class JavaPropertyValueObjectFactory implements PropertyValueFactory { + private Mediator mediator = null; + private SimpleTypeMapper simpleTypeMapper; + private boolean isSimpleType; + + public JavaPropertyValueObjectFactory(ExtensionPointRegistry registry) { + UtilityExtensionPoint utilityExtensionPoint = registry.getExtensionPoint(UtilityExtensionPoint.class); + this.mediator = utilityExtensionPoint.getUtility(Mediator.class); + this.simpleTypeMapper = utilityExtensionPoint.getUtility(SimpleTypeMapper.class); + } + + public JavaPropertyValueObjectFactory(Mediator mediator) { + this.mediator = mediator; + } + + public ObjectFactory createValueFactory(Property property, Object propertyValue, JavaElementImpl javaElement) { + Document doc = (Document)propertyValue; + List<Node> nodes = getValues(doc); + Class<?> javaType = JavaIntrospectionHelper.getBaseType(javaElement.getType(), javaElement.getGenericType()); + if (property.isMany()) { + if (javaElement.getType().isArray()) { + return new ArrayObjectFactoryImpl(property, nodes, javaType); + } else { + return new ListObjectFactoryImpl(property, nodes, javaType); + } + } else { + Object value = null; + if (!nodes.isEmpty()) { + value = nodes.get(0); + } + return new ObjectFactoryImpl(property, value, javaType); + + } + } + + public ObjectFactory createValueFactory(Property property, Object propertyValue, Class<?> javaType) { + Document doc = (Document)propertyValue; + List<Node> nodes = getValues(doc); + if (property.isMany()) { + return new ListObjectFactoryImpl(property, nodes, javaType); + } else { + Object value = null; + if (!nodes.isEmpty()) { + value = nodes.get(0); + } + return new ObjectFactoryImpl(property, value, javaType); + } + } + + public <B> B createPropertyValue(ComponentProperty property, Class<B> type) { + + validateTypes(property, type); + + ObjectFactory<B> factory = this.createValueFactory(property, property.getValue(), type); + return factory.getInstance(); + } + + private <B> void validateTypes(ComponentProperty property, Class<B> type) { + // JAXB seems to do some strange things with conversions, so + // we can't rely on the databinding conversion from Node->Java to catch + // incompatible types. + + DataType prop1 = property.getProperty().getDataType(); + + if ( (prop1 != null) && (type.isAssignableFrom(prop1.getPhysical())) ) { + return; + } else if ( simpleTypeMapper.getXMLType(type) != null ) { + if ( simpleTypeMapper.getXMLType(type).getQName().equals(property.getXSDType())) + return; + } else if ( isSimpleType(property) ) { + if ( type.isAssignableFrom(simpleTypeMapper.getJavaType(property.getXSDType()))) + return; + } + + throw new IllegalArgumentException("Property type " + prop1.getPhysical().getName() + " is not compatible with " + type.getName()); + + } + + abstract class ObjectFactoryImplBase implements ObjectFactory { + protected SimpleTypeMapper simpleTypeMapper = new SimpleTypeMapperImpl(); + protected Property property; + protected Object propertyValue; + protected Class<?> javaType; + protected DataType<XMLType> sourceDataType; + protected DataType<?> targetDataType; + + public ObjectFactoryImplBase(Property property, Object propertyValue, Class<?> javaType) { + this.property = property; + this.propertyValue = propertyValue; + this.javaType = javaType; + sourceDataType = + new DataTypeImpl<XMLType>(DOMDataBinding.NAME, Node.class, + new XMLType(null, this.property.getXSDType())); + + targetDataType = property.getDataType(); + if (targetDataType == null) { + TypeInfo typeInfo = null; + if (this.property.getXSDType() != null) { + if (simpleTypeMapper.isSimpleXSDType(this.property.getXSDType())) { + typeInfo = new TypeInfo(property.getXSDType(), true, null); + } else { + typeInfo = new TypeInfo(property.getXSDType(), false, null); + } + } else { + typeInfo = new TypeInfo(property.getXSDType(), false, null); + } + + XMLType xmlType = new XMLType(typeInfo); + String dataBinding = null; // (String)property.getExtensions().get(DataBinding.class.getName()); + if (dataBinding != null) { + targetDataType = new DataTypeImpl<XMLType>(dataBinding, javaType, xmlType); + } else { + targetDataType = new DataTypeImpl<XMLType>(dataBinding, javaType, xmlType); + mediator.getDataBindings().introspectType(targetDataType, null); + } + } + } + } + + class ObjectFactoryImpl extends ObjectFactoryImplBase { + private Object result = null; + + public ObjectFactoryImpl(Property property, Object propertyValue, Class<?> javaType) { + super(property, propertyValue, javaType); + } + + public Object getInstance() throws ObjectCreationException { + // TUSCANY-3791 + if (result != null){ + return result; + } + + if (isSimpleType) { + try { + result = simpleTypeMapper.toJavaObject(property.getXSDType(), (String)propertyValue, null); + } catch (NumberFormatException ex) { + throw new ObjectCreationException("Failed to create instance for property " + property.getName() + + " with value " + + propertyValue, ex); + } catch (IllegalArgumentException ex) { + throw new ObjectCreationException("Failed to create instance for property " + property.getName() + + " with value " + + propertyValue, ex); + } + } else { + result = mediator.mediate(propertyValue, sourceDataType, targetDataType, null); + } + return result; + } + } + + class ListObjectFactoryImpl extends ObjectFactoryImplBase { + private List result = null; + + public ListObjectFactoryImpl(Property property, List<?> propertyValues, Class<?> javaType) { + super(property, propertyValues, javaType); + } + + @SuppressWarnings("unchecked") + public List<?> getInstance() throws ObjectCreationException { + // TUSCANY-3791 + if (result != null){ + return result; + } + + if (isSimpleType) { + List<Object> values = new ArrayList<Object>(); + for (String aValue : (List<String>)propertyValue) { + try { + values.add(simpleTypeMapper.toJavaObject(property.getXSDType(), aValue, null)); + } catch (NumberFormatException ex) { + throw new ObjectCreationException("Failed to create instance for property " + property + .getName() + + " with value " + + aValue + + " from value list of " + + propertyValue, ex); + } catch (IllegalArgumentException ex) { + throw new ObjectCreationException("Failed to create instance for property " + property + .getName() + + " with value " + + aValue + + " from value list of " + + propertyValue, ex); + } + } + result = values; + } else { + List instances = new ArrayList(); + for (Node aValue : (List<Node>)propertyValue) { + instances.add(mediator.mediate(aValue, sourceDataType, targetDataType, null)); + } + result = instances; + } + + return result; + } + } + + class ArrayObjectFactoryImpl extends ObjectFactoryImplBase { + private Object result = null; + + public ArrayObjectFactoryImpl(Property property, List<?> propertyValues, Class<?> javaType) { + super(property, propertyValues, javaType); + } + + @SuppressWarnings("unchecked") + public Object getInstance() throws ObjectCreationException { + // TUSCANY-3791 + if (result != null){ + return result; + } + + if (isSimpleType) { + int count = 0; + Object values = Array.newInstance(javaType, ((List<Object>)propertyValue).size()); + for (String aValue : (List<String>)propertyValue) { + try { + Array.set(values, count++, simpleTypeMapper.toJavaObject(property.getXSDType(), aValue, null)); + } catch (NumberFormatException ex) { + throw new ObjectCreationException("Failed to create instance for property " + property + .getName() + + " with value " + + aValue + + " from value list of " + + propertyValue, ex); + } catch (IllegalArgumentException ex) { + throw new ObjectCreationException("Failed to create instance for property " + property + .getName() + + " with value " + + aValue + + " from value list of " + + propertyValue, ex); + } + } + result = values; + } else { + Object instances = Array.newInstance(javaType, ((List<Object>)propertyValue).size()); + int count = 0; + for (Node aValue : (List<Node>)propertyValue) { + Array.set(instances, count++, mediator.mediate(aValue, sourceDataType, targetDataType, null)); + } + result = instances; + } + + return result; + } + } + + /** + * Utility methods + */ + + /** + * + * @param property + * @return + */ + private boolean isSimpleType(Property property) { + if (property.getXSDType() != null) { + return simpleTypeMapper.isSimpleXSDType(property.getXSDType()); + } else { + if (property instanceof Document) { + Document doc = (Document)property; + Element element = doc.getDocumentElement(); + if (element.getChildNodes().getLength() == 1 && element.getChildNodes().item(0).getNodeType() == Element.TEXT_NODE) { + return true; + } + } + } + return false; + } + + /** + * Retrieve list of simple property values + * @param concatenatedValue + * @param javaType + * @return + */ + private static List<String> getSimplePropertyValues(String concatenatedValue, Class<?> javaType) { + List<String> propValues = new ArrayList<String>(); + StringTokenizer st = null; + if (javaType.getName().equals("java.lang.String")) { + st = new StringTokenizer(concatenatedValue, "\""); + } else { + st = new StringTokenizer(concatenatedValue); + } + String aToken = null; + while (st.hasMoreTokens()) { + aToken = st.nextToken(); + if (aToken.trim().length() > 0) { + propValues.add(aToken); + } + } + return propValues; + } + + /** + * Retrieve the list of complex property values + * @param document + * @return + */ + private static List<Node> getValues(Document document) { + List<Node> propValues = new ArrayList<Node>(); + if ( document == null ) + return propValues; + // The root is the property element + Element rootElement = document.getDocumentElement(); + + NodeList nodes = rootElement.getChildNodes(); + for (int count = 0; count < nodes.getLength(); ++count) { + Node node = nodes.item(count); + if (node.getNodeType() == Document.ELEMENT_NODE) { + propValues.add(DOMHelper.promote(node)); + } + } + return propValues; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ListMultiplicityObjectFactory.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ListMultiplicityObjectFactory.java new file mode 100644 index 0000000000..a0af933c71 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ListMultiplicityObjectFactory.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.implementation.java.injection; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; + +/** + * Resolves targets configured in a multiplicity by delegating to object factories and returning an <code>List</code> + * containing object instances + * + * @version $Rev$ $Date$ + */ +public class ListMultiplicityObjectFactory implements ObjectFactory<Collection<?>> { + + private Collection<ObjectFactory<?>> factories; + private Class<?> collectionType; + + public ListMultiplicityObjectFactory(List<ObjectFactory<?>> factories, Class<?> collectionType) { + assert factories != null : "Object factories were null"; + this.factories = factories; + this.collectionType = collectionType; + } + + public Collection<?> getInstance() throws ObjectCreationException { + Collection<Object> collection = null; + if (SortedSet.class.isAssignableFrom(collectionType)) { + collection = new TreeSet<Object>(); + } else if (Set.class.isAssignableFrom(collectionType)) { + collection = new HashSet<Object>(); + } else if (List.class.isAssignableFrom(collectionType)) { + collection = new ArrayList<Object>(); + } else { + collection = new ArrayList<Object>(); + } + for (ObjectFactory<?> factory : factories) { + collection.add(factory.getInstance()); + } + return collection; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/MethodInjector.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/MethodInjector.java new file mode 100644 index 0000000000..cd43a60ab6 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/MethodInjector.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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.implementation.java.injection; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; + +/** + * Injects a value created by an {@link org.apache.tuscany.sca.core.factory.ObjectFactory} using a given method + * + * @version $Rev$ $Date$ + */ +public class MethodInjector<T> implements Injector<T> { + private final Method method; + private final ObjectFactory<?> objectFactory; + + public MethodInjector(Method aMethod, ObjectFactory<?> objectFactory) { + assert aMethod != null; + assert objectFactory != null; + this.method = aMethod; + // Allow privileged access to set accessibility. Requires ReflectPermission in security + // policy. + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + method.setAccessible(true); + return null; + } + }); + this.objectFactory = objectFactory; + } + + public void inject(T instance) throws ObjectCreationException { + inject(instance, objectFactory.getInstance()); + } + + private void inject(T instance, Object value) { + try { + method.invoke(instance, value); + } catch (IllegalAccessException e) { + throw new ObjectCreationException("Method is not accessible [" + method + "]", e); + } catch (IllegalArgumentException e) { + throw new ObjectCreationException("Exception thrown by setter: " + method.getName(), e); + } catch (InvocationTargetException e) { + throw new ObjectCreationException("Exception thrown by setter: " + method.getName(), e); + } + } + + public Class<?> getType() { + return method.getParameterTypes()[0]; + } + + public Type getGenericType() { + return method.getGenericParameterTypes()[0]; + } + + public void injectNull(T instance) throws ObjectCreationException { + inject(instance, null); + } + + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/RequestContextObjectFactory.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/RequestContextObjectFactory.java new file mode 100644 index 0000000000..43fb5d6170 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/RequestContextObjectFactory.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.implementation.java.injection; + +import org.apache.tuscany.sca.context.RequestContextFactory; +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.oasisopen.sca.RequestContext; + +/** + * Creates instances of RequestContext for injection on component implementation instances + * + * @version $Rev$ $Date$ + */ +public class RequestContextObjectFactory implements ObjectFactory<RequestContext> { + private RequestContextFactory factory; + private RuntimeComponent component; + + public RequestContextObjectFactory(RequestContextFactory factory, RuntimeComponent component) { + this.factory = factory; + this.component = component; + } + + public RequestContext getInstance() throws ObjectCreationException { + return factory.createRequestContext(component); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceHost.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceHost.java new file mode 100644 index 0000000000..70c368a0e6 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceHost.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.implementation.java.injection; + +/** + * Interface implemented by host environments that allow for resolution of component implementation resources, e.g. + * items bound in a JNDI tree. + * + * @version $Rev$ $Date$ + */ +public interface ResourceHost { + + /** + * Resolve a resource matching the given type + * + * @param type the type of the resources + * @throws ResourceResolutionException if an error is encountered during resolution + */ + <T> T resolveResource(Class<T> type) throws ResourceResolutionException; + + /** + * Resolve a resource matching the given type and name + * + * @param type the type of the resources + * @param mappedName the mapped name of the resource + * @throws ResourceResolutionException if an error is encountered during resolution + */ + <T> T resolveResource(Class<T> type, String mappedName) throws ResourceResolutionException; + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceNotFoundException.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceNotFoundException.java new file mode 100644 index 0000000000..d5c1c7b69e --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceNotFoundException.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.implementation.java.injection; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; + +/** + * Denotes an exception thrown when a runtime resource is not found + * + * @version $Rev$ $Date$ + */ +public class ResourceNotFoundException extends ObjectCreationException { + private static final long serialVersionUID = 1L; + + public ResourceNotFoundException() { + super(); + } + + public ResourceNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public ResourceNotFoundException(String message) { + super(message); + } + + public ResourceNotFoundException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceObjectFactory.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceObjectFactory.java new file mode 100644 index 0000000000..8f55eb18bc --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceObjectFactory.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.implementation.java.injection; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; + +/** + * Resolves a runtime resource to be injected on a field or method of a Java component type marked with {@link + * javax.annotation.Resource}. If the mapped name of the resource is an absolute URI such as + * <code>sca://localhost</code> or <code>jndi://localhost</code> the host container namespace is searched; otherwise the + * URI is assumed to be relative and the parent composite is searched. If a mapped name is not provided, i.e. resolution + * is by type, the parent composite is first searched followed by the host namespace. + * + * @version $Rev$ $Date$ + */ +public class ResourceObjectFactory<T> implements ObjectFactory<T> { + + private Class<T> type; + private String mappedName; + private ResourceHost host; + private boolean optional; + + /** + * Instantiates a factory that resolves resources by type + * + * @param type the type of the resource to inject + * @param optional true if an error should be thrown if the resource is not found + * @param host the runtime resource provider + */ + public ResourceObjectFactory(Class<T> type, boolean optional, ResourceHost host) { + this(type, null, optional, host); + } + + /** + * Instantiates a factory that resolves resources by mapped name + * + * @param type the type of the resource to inject + * @param mappedName the resource name + * @param optional true if an error should be thrown if the resource is not found + * @param host the runtime resource provider + */ + public ResourceObjectFactory(Class<T> type, String mappedName, boolean optional, ResourceHost host) { + this.type = type; + this.host = host; + this.mappedName = mappedName; + this.optional = optional; + } + + public T getInstance() throws ObjectCreationException { + try { + T resource; + if (mappedName == null) { + resource = host.resolveResource(type); + if (!optional && resource == null) { + throw new ResourceNotFoundException("Resource not found: " + type.getName()); + } + } else { + resource = host.resolveResource(type, mappedName); + if (!optional && resource == null) { + throw new ResourceNotFoundException("Resource not found: " + mappedName); + } + } + return resource; + } catch (ResourceResolutionException e) { + throw new ObjectCreationException(e); + } + + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceResolutionException.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceResolutionException.java new file mode 100644 index 0000000000..f94b24762a --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/injection/ResourceResolutionException.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.implementation.java.injection; + + +/** + * @version $Rev$ $Date$ + */ +public class ResourceResolutionException extends Exception { + private static final long serialVersionUID = 13421352711315479L; + + public ResourceResolutionException() { + super(); + } + + public ResourceResolutionException(String message, Throwable cause) { + super(message, cause); + } + + public ResourceResolutionException(String message) { + super(message); + } + + public ResourceResolutionException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/EventInvocationException.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/EventInvocationException.java new file mode 100644 index 0000000000..25c09231c5 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/EventInvocationException.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.implementation.java.invocation; + +import org.apache.tuscany.sca.implementation.java.injection.InjectionRuntimeException; + +/** + * Denotes an error when invoking an event on an object + * + * @version $Rev$ $Date$ + */ +public class EventInvocationException extends InjectionRuntimeException { + private static final long serialVersionUID = 1480018831708211581L; + + public EventInvocationException() { + super(); + } + + public EventInvocationException(String message, Throwable cause) { + super(message, cause); + } + + public EventInvocationException(String message) { + super(message); + } + + public EventInvocationException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/EventInvoker.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/EventInvoker.java new file mode 100644 index 0000000000..e6ebb5abc3 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/EventInvoker.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.implementation.java.invocation; + +/** + * Performs an invocation on an instance + * + * @version $Rev$ $Date$ + */ +public interface EventInvoker<T> { + + /** + * Performs the invocation on a given instance + * + * @throws EventInvocationException + */ + void invokeEvent(T instance) throws EventInvocationException; +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/InvalidConversationSequenceException.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/InvalidConversationSequenceException.java new file mode 100644 index 0000000000..1c330ea913 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/InvalidConversationSequenceException.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.implementation.java.invocation; + + +/** + * Denotes an unknown operation sequence in a conversation + * + * @version $Rev$ $Date$ + */ +public class InvalidConversationSequenceException extends Exception { + private static final long serialVersionUID = -5744028391493899147L; + + public InvalidConversationSequenceException() { + super(); + } + + public InvalidConversationSequenceException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidConversationSequenceException(String message) { + super(message); + } + + public InvalidConversationSequenceException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaAsyncImplementationInvoker.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaAsyncImplementationInvoker.java new file mode 100644 index 0000000000..259e3a66ad --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaAsyncImplementationInvoker.java @@ -0,0 +1,233 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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.implementation.java.invocation; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.core.factory.InstanceWrapper; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.invocation.AsyncResponseException; +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.interfacedef.java.JavaOperation; +import org.apache.tuscany.sca.invocation.InterceptorAsync; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.InvokerAsyncResponse; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.oasisopen.sca.ResponseDispatch; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * Responsible for asynchronously dispatching an invocation to a Java component + * implementation instance + * + */ +public class JavaAsyncImplementationInvoker extends JavaImplementationInvoker implements InterceptorAsync { + + public JavaAsyncImplementationInvoker(Operation operation, Method method, RuntimeComponent component, + InterfaceContract interfaceContract) { + super( operation, method, component, interfaceContract); + assert method != null : "Operation method cannot be null"; + assert ((JavaOperation) operation).isAsyncServer() : "Operation must be async"; + } // end constructor + + public Message invoke(Message msg) { + Operation op = this.operation; + + Object payload = msg.getBody(); + + // Save the current thread context classloader + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + + try { + // The following call might create a new conversation, as a result, the msg.getConversationID() might + // return a new value + InstanceWrapper wrapper = scopeContainer.getWrapper(null); + + Object instance = wrapper.getInstance(); + + // Set the TCCL to the classloader used to load the implementation class + Thread.currentThread().setContextClassLoader(instance.getClass().getClassLoader()); + + // For an async server method, there is an extra input parameter, which is a DispatchResponse instance + // which is typed by the type of the response + Class<?> responseType = op.getOutputType().getPhysical(); + ResponseDispatch<?> dispatch = ResponseDispatchImpl.newInstance(responseType, msg ); + + Object ret; + Object[] payload2; + if (payload != null && !payload.getClass().isArray()) { + payload2 = new Object[2]; + payload2[0] = payload; + } else { + payload2 = new Object[ ((Object[])payload).length + 1 ]; + for( int i = 0; i < ((Object[])payload).length; i++) { + payload2[i] = ((Object[])payload)[i]; + } // end for + } + payload2[ payload2.length - 1 ] = dispatch; + + ret = method.invoke(instance, (Object[])payload2); + + throw new InvocationTargetException( new AsyncResponseException("AsyncResponse") ); + + } catch (InvocationTargetException e) { + Throwable cause = e.getTargetException(); + boolean isChecked = false; + for (DataType<?> d : operation.getFaultTypes()) { + if (d.getPhysical().isInstance(cause)) { + isChecked = true; + msg.setFaultBody(cause); + break; + } + } // end for + + if (!isChecked) { + if (cause instanceof RuntimeException) { + throw (RuntimeException)cause; + } + if (cause instanceof Error) { + throw (Error)cause; + } else { + throw new ServiceRuntimeException(cause.getMessage(), cause); + } + } // end if + + } catch (ObjectCreationException e) { + throw new ServiceRuntimeException(e.getMessage(), e); + } catch (Exception e) { + msg.setFaultBody(e); + } finally { + // set the tccl + Thread.currentThread().setContextClassLoader(tccl); + } + return msg; + } // end method invoke + + protected Invoker next; + protected InvokerAsyncResponse previous; + + public void setNext(Invoker next) { + this.next = next; + } + + public Invoker getNext() { + return next; + } + + public void invokeAsyncRequest(Message msg) throws Throwable { + processRequest(msg); + } // end method invokeAsyncRequest + + public void invokeAsyncResponse(Message msg) { + msg = processResponse(msg); + InvokerAsyncResponse thePrevious = (InvokerAsyncResponse)getPrevious(); + if (thePrevious != null ) thePrevious.invokeAsyncResponse(msg); + } // end method invokeAsyncResponse + + public void setPrevious(InvokerAsyncResponse previous) { + this.previous = previous; + } + + public InvokerAsyncResponse getPrevious() { + return previous; + } + + public Message processRequest(Message msg) { + Operation op = this.operation; + Object payload = msg.getBody(); + + // Replace TCCL with the class loader used to load the java class as per SCA Spec + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + + try { + InstanceWrapper wrapper = scopeContainer.getWrapper(null); + Object instance = wrapper.getInstance(); + + // Set the TCCL to the classloader used to load the implementation class + Thread.currentThread().setContextClassLoader(instance.getClass().getClassLoader()); + + // For an async server method, there is an extra input parameter, which is a DispatchResponse instance + // which is typed by the type of the response + Class<?> responseType = op.getOutputType().getPhysical(); + ResponseDispatch<?> dispatch = ResponseDispatchImpl.newInstance(responseType, msg ); + + Object[] payload2; + if (payload != null && !payload.getClass().isArray()) { + payload2 = new Object[2]; + payload2[0] = payload; + } else { + payload2 = new Object[ ((Object[])payload).length + 1 ]; + for( int i = 0; i < ((Object[])payload).length; i++) { + payload2[i] = ((Object[])payload)[i]; + } // end for + } + payload2[ payload2.length - 1 ] = dispatch; + + method.invoke(instance, (Object[])payload2); + + } catch (InvocationTargetException e) { + Throwable cause = e.getTargetException(); + boolean isChecked = false; + for (DataType<?> d : operation.getFaultTypes()) { + if (d.getPhysical().isInstance(cause)) { + isChecked = true; + // Ignore these errors since they should be returned asynchronously + break; + } + } // end for + + if (!isChecked) { + if (cause instanceof RuntimeException) { + throw (RuntimeException)cause; + } // end if + if (cause instanceof Error) { + throw (Error)cause; + } else { + throw new ServiceRuntimeException(cause.getMessage(), cause); + } // end if + } // end if + + } catch (Exception e) { + throw new ServiceRuntimeException(e.getMessage(), e); + } finally { + // set the tccl + Thread.currentThread().setContextClassLoader(tccl); + } + return msg; + } // end method processRequest + + public Message postProcessRequest(Message msg) { + return msg; + } + + public Message postProcessRequest(Message msg, Throwable e) + throws Throwable { + throw e; + } + + public Message processResponse(Message msg) { + return msg; + } // end method processResponse + +} // end class JavaAsyncImplementationInvoker diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaAsyncResponseInvokerImpl.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaAsyncResponseInvokerImpl.java new file mode 100644 index 0000000000..0bddda6965 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaAsyncResponseInvokerImpl.java @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.invocation; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import org.apache.tuscany.sca.core.invocation.AsyncFaultWrapper; +import org.apache.tuscany.sca.core.invocation.AsyncResponseHandler; +import org.apache.tuscany.sca.core.invocation.JDKAsyncResponseInvoker; +import org.apache.tuscany.sca.invocation.Message; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * Class which handles the asynchronous response message from an async service back to the client Java component + * + * This class provides a registration function which permits the reference invoking code to register the Future + * which is used to return the response to the Java component code + */ +public class JavaAsyncResponseInvokerImpl implements JDKAsyncResponseInvoker { + + // Map used to link between async requests and async responses + private ConcurrentMap<String, Object> asyncMessageMap; + + public JavaAsyncResponseInvokerImpl() { + + asyncMessageMap = new ConcurrentHashMap<String, Object>(); + } // end constructor + + /** + * Deal with the asynchronous response message + * @param msg - the response message + * + * The response message must contain a RELATES_TO id, which is used to identify the Future that represents + * the operation yet to complete. The Future is then completed with the content of the message. + * The Future either calls back to the application code, or it is expected that the application is polling + * the Future for its completion. + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + public void invokeAsyncResponse(Message msg) { + // Obtain the Message ID for this message + String relatesID = getMessageRelatesID( msg ); + if( relatesID == null ) + throw new ServiceRuntimeException("JavaAsyncResponseInvoker - response message has no RELATES_TO id"); + + // Look up the response object & remove it from the Map + Object responseHandler = asyncMessageMap.remove(relatesID); + + if( responseHandler == null ) + throw new ServiceRuntimeException("JavaAsyncResponseInvoker - no Future matches the RELATES_TO id: " + relatesID); + + // Invoke the response handler with the content of the message + // - in the case of a Java implementation, the response handler is a Future... + AsyncResponseHandler future = (AsyncResponseHandler) responseHandler; + + 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.setWrappedFault((AsyncFaultWrapper) response ); + } else if ( response instanceof Throwable ) { + future.setFault( (Throwable)response ); + } else { + future.setResponse(response); + } // end if + } // end if + + } // end method invokeAsyncResponse + + /** + * Registers an Async response, which provides an ID which identifies a given response + * and an object which can handle the response + * @param id - the ID + * @param responseHandler - the response handler object + */ + public void registerAsyncResponse( String id, Object responseHandler ) { + // Add the ID/response handler mapping into the table + if( id != null && responseHandler != null ) asyncMessageMap.put(id, responseHandler); + } // end method registerAsyncResponse + + /** + * Extracts the RELATES_TO header from the message + * @param msg - the Tuscany message + * @return - the value of the RELATES_TO header as a String + */ + private String getMessageRelatesID( Message msg ) { + return (String)msg.getHeaders().get("RELATES_TO"); + } // end method getMessageRelatesID + +} // end class JavaAsyncResponseInvoker diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaCallbackRuntimeWireProcessor.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaCallbackRuntimeWireProcessor.java new file mode 100644 index 0000000000..6cd16202ba --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaCallbackRuntimeWireProcessor.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.implementation.java.invocation; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.assembly.Contract; +import org.apache.tuscany.sca.assembly.Endpoint; +import org.apache.tuscany.sca.assembly.Implementation; +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.CallbackInterfaceInterceptor; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +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.invocation.InvocationChain; +import org.apache.tuscany.sca.invocation.Phase; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentReference; +import org.apache.tuscany.sca.runtime.RuntimeEndpoint; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; +import org.apache.tuscany.sca.runtime.RuntimeWireProcessor; + +/** + * @version $Rev$ $Date$ + */ +public class JavaCallbackRuntimeWireProcessor implements RuntimeWireProcessor { + private static final Logger logger = Logger.getLogger(JavaCallbackRuntimeWireProcessor.class.getName()); + private InterfaceContractMapper interfaceContractMapper; + private JavaInterfaceFactory javaInterfaceFactory; + + public JavaCallbackRuntimeWireProcessor(ExtensionPointRegistry registry) { + FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class); + this.javaInterfaceFactory = factories.getFactory(JavaInterfaceFactory.class); + + UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class); + this.interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class); + } + + /** + * @param interfaceContractMapper + * @param javaInterfaceFactory + */ + protected JavaCallbackRuntimeWireProcessor(InterfaceContractMapper interfaceContractMapper, + JavaInterfaceFactory javaInterfaceFactory) { + super(); + this.interfaceContractMapper = interfaceContractMapper; + this.javaInterfaceFactory = javaInterfaceFactory; + } + + + private boolean supportsCallbackInterface(Interface iface, JavaImplementation impl) { + if (iface instanceof JavaInterface) { + Class<?> ifaceClass = ((JavaInterface)iface).getJavaClass(); + if (ifaceClass.isAssignableFrom(impl.getJavaClass())) { + return true; + } + } + try { + Interface implType = javaInterfaceFactory.createJavaInterface(impl.getJavaClass()); + // Ignore the remotable/conversational testing + implType.setRemotable(iface.isRemotable()); + return interfaceContractMapper.isCompatibleSubset(iface, implType); + } catch (InvalidInterfaceException e) { + logger.log(Level.WARNING, e.getMessage(), e); + return false; + } + } + + public void process(RuntimeEndpoint endpoint) { + // No operation + } + + public void process(RuntimeEndpointReference endpointReference) { + if(!(endpointReference instanceof RuntimeEndpointReference)) { + return; + } + RuntimeEndpointReference epr = (RuntimeEndpointReference) endpointReference; + Contract contract = epr.getReference(); + if (!(contract instanceof RuntimeComponentReference)) { + return; + } + RuntimeComponent component = (RuntimeComponent) epr.getComponent(); + if (component == null) { + return; + } + Implementation implementation = component.getImplementation(); + if (!(implementation instanceof JavaImplementation)) { + return; + } + JavaImplementation javaImpl = (JavaImplementation)implementation; + Endpoint callbackEndpoint = epr.getCallbackEndpoint(); + if (callbackEndpoint != null) { + Interface iface = callbackEndpoint.getService().getInterfaceContract().getInterface(); + if (!supportsCallbackInterface(iface, javaImpl)) { + // callback to this impl is not possible, so ensure a callback object is set + for (InvocationChain chain : epr.getInvocationChains()) { + chain.addInterceptor(Phase.REFERENCE, new CallbackInterfaceInterceptor()); + } + } + } + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentContextFactory.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentContextFactory.java new file mode 100644 index 0000000000..f2a0d576db --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentContextFactory.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.implementation.java.invocation; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.oasisopen.sca.ComponentContext; + +/** + * @version $Rev$ $Date$ + */ +public class JavaComponentContextFactory implements ObjectFactory<ComponentContext> { + private final JavaComponentContextProvider component; + + + public JavaComponentContextFactory(JavaComponentContextProvider component) { + this.component = component; + } + + + public ComponentContext getInstance() throws ObjectCreationException { + return component.getComponent().getComponentContext(); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentContextProvider.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentContextProvider.java new file mode 100644 index 0000000000..1fa51315c3 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentContextProvider.java @@ -0,0 +1,399 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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.implementation.java.invocation; + +import java.lang.annotation.ElementType; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +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.ComponentProperty; +import org.apache.tuscany.sca.assembly.ComponentReference; +import org.apache.tuscany.sca.assembly.ComponentService; +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.assembly.Multiplicity; +import org.apache.tuscany.sca.assembly.Reference; +import org.apache.tuscany.sca.context.ComponentContextFactory; +import org.apache.tuscany.sca.context.PropertyValueFactory; +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.core.factory.InstanceWrapper; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.core.invocation.CallableReferenceObjectFactory; +import org.apache.tuscany.sca.core.invocation.CallbackReferenceObjectFactory; +import org.apache.tuscany.sca.core.invocation.CallbackWireObjectFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.invocation.WireObjectFactory; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.TargetResolutionException; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.implementation.java.JavaConstructorImpl; +import org.apache.tuscany.sca.implementation.java.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaResourceImpl; +import org.apache.tuscany.sca.implementation.java.JavaScopeImpl; +import org.apache.tuscany.sca.implementation.java.context.InstanceFactory; +import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory; +import org.apache.tuscany.sca.implementation.java.introspect.JavaIntrospectionHelper; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaOperation; +import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil; +import org.apache.tuscany.sca.invocation.Invoker; +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.ServiceReference; + +/** + * The runtime instantiation of Java component implementations + * + * @version $Rev$ $Date$ + */ +public class JavaComponentContextProvider { + private JavaPropertyValueObjectFactory propertyValueFactory; + private RuntimeComponent component; + private JavaInstanceFactoryProvider<?> instanceFactoryProvider; + private ProxyFactory proxyFactory; + private InstanceFactory instanceFactory; + private JavaScopeImpl scope; + + public JavaComponentContextProvider(RuntimeComponent component, + JavaInstanceFactoryProvider configuration, + DataBindingExtensionPoint dataBindingExtensionPoint, + PropertyValueFactory propertyValueObjectFactory, + ComponentContextFactory componentContextFactory, + RequestContextFactory requestContextFactory) { + super(); + this.instanceFactoryProvider = configuration; + this.proxyFactory = configuration.getProxyFactory(); + // if (componentContextFactory != null) { + // this.componentContext = componentContextFactory.createComponentContext(component, requestContextFactory); + // } else { + // this.componentContext = new ComponentContextImpl(this, requestContextFactory, this.proxyService); + // } + this.component = component; + this.propertyValueFactory = (JavaPropertyValueObjectFactory) propertyValueObjectFactory; + this.scope = ((JavaImplementation)component.getImplementation()).getJavaScope(); + } + + InstanceWrapper<?> createInstanceWrapper() throws ObjectCreationException { + if (instanceFactory == null) { + start(); + } + return instanceFactory.newInstance(); + } + + void configureProperties(List<ComponentProperty> definedProperties) { + for (ComponentProperty p : definedProperties) { + configureProperty(p); + } + } + + private void configureProperty(ComponentProperty configuredProperty) { + JavaElementImpl element = + instanceFactoryProvider.getImplementation().getPropertyMembers().get(configuredProperty.getName()); + + if (element != null && configuredProperty.getValue() != null) { + if (!(element.getAnchor() instanceof Constructor)) { + if(element.getElementType() == ElementType.FIELD) { + // Field field = (Field)element.getAnchor(); + instanceFactoryProvider.getInjectionSites().add(element); + /* + if(Modifier.isPublic(field.getModifiers())) { + instanceFactoryProvider.getInjectionSites().add(element); + } else if(field.getAnnotation(org.oasisopen.sca.annotation.Property.class) != null) { + instanceFactoryProvider.getInjectionSites().add(element); + } + */ + } else { + instanceFactoryProvider.getInjectionSites().add(element); + } + } + + //Class propertyJavaType = JavaIntrospectionHelper.getBaseType(element.getType(), element.getGenericType()); + ObjectFactory<?> propertyObjectFactory = + createPropertyValueFactory(configuredProperty, configuredProperty.getValue(), element); + instanceFactoryProvider.setObjectFactory(element, propertyObjectFactory); + + JavaConstructorImpl<?> constructor = instanceFactoryProvider.getImplementation().getConstructor(); + for(JavaElementImpl p: constructor.getParameters()){ + if(element.getName().equals(p.getName())) { + instanceFactoryProvider.setObjectFactory(p, propertyObjectFactory); + } + } + } + } + + void start() { + List<JavaElementImpl> callbackInjectionList = null; + + // If the component implementation is stateless, we need to inject the callbacks on service invocation + // rather than doing it once at the component level. + if ( scope.equals(JavaScopeImpl.STATELESS)) { + callbackInjectionList = instanceFactoryProvider.getCallbackInjectionSites(); + } else { + callbackInjectionList = instanceFactoryProvider.getInjectionSites(); + } + + if (!instanceFactoryProvider.getImplementation().getCallbackMembers().isEmpty()) { + Map<String, List<EndpointReference>> callbackWires = new HashMap<String, List<EndpointReference>>(); + for (ComponentService service : component.getServices()) { + + RuntimeComponentReference callbackReference = (RuntimeComponentReference)service.getCallbackReference(); + if (callbackReference != null) { + List<EndpointReference> wires = callbackReference.getEndpointReferences(); + if (!wires.isEmpty()) { + RuntimeEndpointReference epr = (RuntimeEndpointReference) wires.get(0); + callbackWires.put(epr.getComponentTypeReferenceInterfaceContract().getInterface().toString(), + wires); + } + } + } + + for (Map.Entry<String, Collection<JavaElementImpl>> entry : instanceFactoryProvider.getImplementation() + .getCallbackMembers().entrySet()) { + List<EndpointReference> wires = callbackWires.get(entry.getKey()); + if (wires == null) { + // this can happen when there are no client wires to a + // component that has a callback + continue; + } + for(JavaElementImpl element : entry.getValue()) { + Class<?> businessInterface = element.getType(); + ObjectFactory<?> factory = null; + if (ServiceReference.class.isAssignableFrom(element.getType())) { + businessInterface = + JavaIntrospectionHelper.getBusinessInterface(element.getType(), element.getGenericType()); + factory = + new CallbackReferenceObjectFactory(businessInterface, proxyFactory, wires); + } else { + factory = new CallbackWireObjectFactory(businessInterface, proxyFactory, wires); + } + if (!(element.getAnchor() instanceof Constructor)) { + callbackInjectionList.add(element); + } + instanceFactoryProvider.setObjectFactory(element, factory); + } + } + } + for (Reference ref : instanceFactoryProvider.getImplementation().getReferences()) { + JavaElementImpl element = + instanceFactoryProvider.getImplementation().getReferenceMembers().get(ref.getName()); + if (element != null) { + if (!(element.getAnchor() instanceof Constructor)) { + if(element.getElementType() == ElementType.FIELD) { + Field field = (Field)element.getAnchor(); + if(Modifier.isPublic(field.getModifiers())) { + instanceFactoryProvider.getInjectionSites().add(element); + } else if(field.getAnnotation(org.oasisopen.sca.annotation.Reference.class) != null) { + instanceFactoryProvider.getInjectionSites().add(element); + } + } else { + instanceFactoryProvider.getInjectionSites().add(element); + } + } + ComponentReference componentReference = null; + List<EndpointReference> wireList = null; + for (ComponentReference reference : component.getReferences()) { + if (reference.getName().equals(ref.getName())) { + wireList = ((RuntimeComponentReference)reference).getEndpointReferences(); + componentReference = reference; + break; + } + } + if (ref.getMultiplicity() == Multiplicity.ONE_N || ref.getMultiplicity() == Multiplicity.ZERO_N) { + List<ObjectFactory<?>> factories = new ArrayList<ObjectFactory<?>>(); + Class<?> baseType = + JavaIntrospectionHelper.getBaseType(element.getType(), element.getGenericType()); + for (int i = 0; i < wireList.size(); i++) { + ObjectFactory<?> factory = null; + if (ServiceReference.class.isAssignableFrom(baseType)) { + Type callableRefType = JavaIntrospectionHelper.getParameterType(element.getGenericType()); + // Type businessType = JavaIntrospectionHelper.getParameterType(callableRefType); + Class<?> businessInterface = + JavaIntrospectionHelper.getBusinessInterface(baseType, callableRefType); + factory = new CallableReferenceObjectFactory(businessInterface, (RuntimeEndpointReference) wireList.get(i)); + } else { + factory = createObjectFactory(baseType, wireList.get(i)); + } + factories.add(factory); + } + instanceFactoryProvider.setObjectFactories(element, factories); + JavaConstructorImpl<?> constructor = instanceFactoryProvider.getImplementation().getConstructor(); + for(JavaElementImpl p: constructor.getParameters()){ + if(element.getName().equals(p.getName())) { + instanceFactoryProvider.setObjectFactories(p, factories); + } + } + } else { + if (wireList == null && ref.getMultiplicity() == Multiplicity.ONE_ONE) { + throw new IllegalStateException("Required reference is missing: " + ref.getName()); + } + if (wireList != null && !wireList.isEmpty()) { + ObjectFactory<?> factory = null; + if (ServiceReference.class.isAssignableFrom(element.getType())) { + Class<?> businessInterface = + JavaIntrospectionHelper.getBusinessInterface(element.getType(), element + .getGenericType()); + factory = + new CallableReferenceObjectFactory(businessInterface, (RuntimeEndpointReference) wireList.get(0)); + } else { + factory = createObjectFactory(element.getType(), wireList.get(0)); + } + instanceFactoryProvider.setObjectFactory(element, factory); + JavaConstructorImpl<?> constructor = instanceFactoryProvider.getImplementation().getConstructor(); + for(JavaElementImpl p: constructor.getParameters()){ + if(element.getName().equals(p.getName())) { + instanceFactoryProvider.setObjectFactory(p, factory); + } + } + } + } + } + } + + //setUpPolicyHandlers(); + this.instanceFactory = instanceFactoryProvider.createFactory(); + + } + + void addResourceFactory(String name, ObjectFactory<?> factory) { + JavaResourceImpl resource = instanceFactoryProvider.getImplementation().getResources().get(name); + + if (resource != null && !(resource.getElement().getAnchor() instanceof Constructor)) { + instanceFactoryProvider.getInjectionSites().add(resource.getElement()); + } + + instanceFactoryProvider.setObjectFactory(resource.getElement(), factory); + } + + Object createInstance() throws ObjectCreationException { + return createInstanceWrapper().getInstance(); + } + + JavaInstanceFactoryProvider<?> getInstanceFactoryProvider() { + return instanceFactoryProvider; + } + + void stop() { + //cleanUpPolicyHandlers(); + } + + Invoker createInvoker(Operation operation, InterfaceContract interfaceContract) throws NoSuchMethodException { + Class<?> implClass = instanceFactoryProvider.getImplementationClass(); + + Method method = JavaInterfaceUtil.findMethod(implClass, operation); + if (operation instanceof JavaOperation && + ((JavaOperation) operation).isAsyncServer() ) { + return new JavaAsyncImplementationInvoker(operation, method, component, interfaceContract); + } else { + return new JavaImplementationInvoker(operation, method, component, interfaceContract); + } // end if + } // end + + private static class OptimizedObjectFactory<T> implements ObjectFactory<T> { + private ScopeContainer scopeContainer; + + public OptimizedObjectFactory(ScopeContainer scopeContainer) { + super(); + this.scopeContainer = scopeContainer; + } + + public T getInstance() throws ObjectCreationException { + try { + return (T)scopeContainer.getWrapper(null).getInstance(); + } catch (TargetResolutionException e) { + throw new ObjectCreationException(e); + } + } + + } + + private <B> ObjectFactory<B> createObjectFactory(Class<B> interfaze, EndpointReference wire) { + // FIXME: [rfeng] Disable the optimization for new as it needs more discussions + /* + boolean conversational = wire.getSource().getInterfaceContract().getInterface().isConversational(); + Binding binding = wire.getSource().getBinding(); + // Check if it's wireable binding for optimization + if (!conversational && binding instanceof OptimizableBinding) { + OptimizableBinding optimizableBinding = (OptimizableBinding)binding; + Component component = optimizableBinding.getTargetComponent(); + if (component != null) { + Implementation implementation = component.getImplementation(); + // Check if the target component is java component + if (implementation instanceof JavaImplementation) { + JavaImplementation javaImplementation = (JavaImplementation)implementation; + if (interfaze.isAssignableFrom(javaImplementation.getJavaClass())) { + ScopedRuntimeComponent scopedComponent = (ScopedRuntimeComponent)component; + ScopeContainer scopeContainer = scopedComponent.getScopeContainer(); + Scope scope = scopeContainer.getScope(); + if (scope == Scope.COMPOSITE || scope == Scope.STATELESS || scope == Scope.SYSTEM) { + boolean optimizable = true; + for (InvocationChain chain : wire.getInvocationChains()) { + if (chain.getHeadInvoker() != chain.getTailInvoker()) { + optimizable = false; + break; + } + } + if (optimizable) { + return new OptimizedObjectFactory<B>(scopeContainer); + } + } + } + } + } + } + */ + return new WireObjectFactory<B>(interfaze, (RuntimeEndpointReference) wire, proxyFactory); + } + + private ObjectFactory<?> createPropertyValueFactory(ComponentProperty property, + Object propertyValue, + JavaElementImpl javaElement) { + return propertyValueFactory.createValueFactory(property, propertyValue, javaElement); + } + + /** + * @return the component + */ + RuntimeComponent getComponent() { + return component; + } + + /*private void setUpPolicyHandlers() { + for (PolicyHandler policyHandler : policyHandlers.values()) { + policyHandler.setUp(component.getImplementation()); + } + } + + private void cleanUpPolicyHandlers() { + for (PolicyHandler policyHandler : policyHandlers.values() ) { + policyHandler.cleanUp(this); + } + }*/ + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentNameFactory.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentNameFactory.java new file mode 100644 index 0000000000..4a5ad98e5b --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentNameFactory.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.implementation.java.invocation; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; + +/** + * @version $Rev$ $Date$ + */ +public class JavaComponentNameFactory implements ObjectFactory<String> { + private final JavaComponentContextProvider componentContextProvider; + + + public JavaComponentNameFactory(JavaComponentContextProvider component) { + this.componentContextProvider = component; + } + + + public String getInstance() throws ObjectCreationException { + String uri = componentContextProvider.getComponent().getURI(); + return uri.substring(uri.lastIndexOf('/')+1); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java new file mode 100644 index 0000000000..0b97192cc6 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java @@ -0,0 +1,283 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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.implementation.java.invocation; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.ws.Holder; + +import org.apache.tuscany.sca.assembly.EndpointReference; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.core.scope.ScopeContainer; +import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.context.ReflectiveInstanceWrapper; +import org.apache.tuscany.sca.implementation.java.injection.Injector; +import org.apache.tuscany.sca.implementation.java.introspect.JavaIntrospectionHelper; +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.interfacedef.ParameterMode; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil; +import org.apache.tuscany.sca.invocation.DataExchangeSemantics; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.oasisopen.sca.ServiceReference; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * Responsible for synchronously dispatching an invocation to a Java component + * implementation instance + * + * @version $Rev$ $Date$ + */ +public class JavaImplementationInvoker implements Invoker, DataExchangeSemantics { + protected Operation operation; + protected Method method; + protected boolean allowsPBR; + + @SuppressWarnings("unchecked") + protected final ScopeContainer scopeContainer; + private final InterfaceContract interfaze; + + public JavaImplementationInvoker(Operation operation, Method method, RuntimeComponent component, InterfaceContract intf) { + assert method != null : "Operation method cannot be null"; + this.method = method; + this.operation = operation; + this.scopeContainer = ((ScopedRuntimeComponent)component).getScopeContainer(); + this.allowsPBR = ((JavaImplementation)component.getImplementation()).isAllowsPassByReference(method); + this.interfaze = intf; + } + + public JavaImplementationInvoker(Operation operation, RuntimeComponent component, InterfaceContract intf) { + // used if the method can't be computed statically in advance + this.operation = operation; + this.scopeContainer = ((ScopedRuntimeComponent)component).getScopeContainer(); + this.interfaze = intf; + } + + @SuppressWarnings("unchecked") + public Message invoke(Message msg) { + + Operation op = msg.getOperation(); + if (op == null) { + op = this.operation; + } + Object payload = msg.getBody(); + + Object contextId = null; + + EndpointReference from = msg.getFrom(); + + // store the current thread context classloader + // as we need to replace it with the class loader + // used to load the java class as per SCA Spec + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + + try { + // The following call might create a new conversation, as a result, the msg.getConversationID() might + // return a new value + ReflectiveInstanceWrapper wrapper = (ReflectiveInstanceWrapper) scopeContainer.getWrapper(contextId); + + // If there is a callback interface and the implementation is stateless, we need to + // inject callbacks at invocation time. For Composite scope, this has already been done. + if (( interfaze.getCallbackInterface() != null ) && (scopeContainer.getScope().equals(Scope.STATELESS))){ + injectCallbacks(wrapper, (JavaInterface)interfaze.getCallbackInterface()); + } + + Object instance = wrapper.getInstance(); + + // If the method couldn't be computed statically, or the instance being + // invoked is a user-specified callback object that doesn't implement + // the service interface from which the reflective method was obtained, + // compute the method object dynamically for this invocation. + Method imethod = method; + if (imethod == null || !imethod.getDeclaringClass().isInstance(instance)) { + try { + imethod = JavaInterfaceUtil.findMethod(instance.getClass(), operation); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException("Callback object does not provide method " + e.getMessage()); + } + } + + // Set the thread context classloader of the thread used to invoke an operation + // of a Java POJO component implementation is the class loader of the contribution + // that contains the POJO implementation class. + + Thread.currentThread().setContextClassLoader(instance.getClass().getClassLoader()); + + int argumentHolderCount = 0; + + // Holder pattern. Any payload parameters <T> which are should be in holders are placed in Holder<T>. + // Only check Holder for remotable interfaces + if (imethod != null && op.getInterface().isRemotable()) { + Object[] payloadArray = (Object[])payload; + List<Object> payloadList = new ArrayList<Object>(); + int nextIndex = 0; + for (ParameterMode mode : op.getParameterModes()) { + if (mode.equals(ParameterMode.IN)) { + payloadList.add(payloadArray[nextIndex++]); + } else if (mode.equals(ParameterMode.INOUT)) { + // Promote array params from [<T>] to [Holder<T>] + Object item = payloadArray[nextIndex++]; + Holder itemHolder = new Holder(item); + payloadList.add(itemHolder); + argumentHolderCount++; + } else { + // Create an empty Holder since we should not pass values for OUT parameters + payloadList.add(new Holder()); + argumentHolderCount++; + } + } + + // Maybe a bit odd to do but this way I don't have to worry about how the invoke if/else + // immediately following might need to be changed. + payload = payloadList.toArray(); + } + + Object ret; + if (payload != null && !payload.getClass().isArray()) { + ret = imethod.invoke(instance, payload); + } else { + ret = imethod.invoke(instance, (Object[])payload); + } + + scopeContainer.returnWrapper(wrapper, contextId); + + + if (argumentHolderCount > 0) { + + // Holder pattern. Any payload Holder<T> types are returned as part of the message body. + Object[] payloadArray = (Object[])payload; + + ArrayList<Object> holderOutputs = new ArrayList<Object>(); + ArrayList<Object> result = new ArrayList<Object>(); + if (imethod != null) { + + for (int i = 0, size = op.getParameterModes().size(); i < size; i++) { + if (ParameterMode.IN != op.getParameterModes().get(i)) { + // Demote array params from Holder<T> to <T>. + Holder<Object> item = (Holder<Object>)payloadArray[i]; + payloadArray[i] = item.value; + holderOutputs.add(payloadArray[i]); + } + } + + // + // Now we account for the fact that we may have a null because of a void return type, + // which is not part of the output DataType, and so should not be returned with the array + // of outputs, or we may have a null as value returned + // from a method with signature with return type other than void, which should be returned + // in the output array. + // + // The logic here is if we already have as many outputs in holders as we have outputs + // altogether, then we don't worry about the return value (which should be null). Might + // be simpler to just check for void, but the code in the Java introspector has a lot + // of quirks for handling parameterized types, and this seems simpler for now. + // + int holderOutputSize = holderOutputs.size(); + int numberOperationOutputs = op.getOutputType().getLogical().size(); + if (holderOutputSize == numberOperationOutputs) { + if (ret != null) { + throw new IllegalStateException("Number of holder outputs equal to number of operations outputs." + + "\nNum = " + holderOutputSize + ", but non-null return value seen: " + ret); + } + result = holderOutputs; + } else if (holderOutputSize == numberOperationOutputs - 1) { + result.add(ret); + result.addAll(1, holderOutputs); + } else { + throw new IllegalStateException("Number of holder outputs seen: " + holderOutputSize + + "\nNumber of operation outputs: " + numberOperationOutputs); + } + } + + msg.setBody(result.toArray()); + + } else { + msg.setBody(ret); + } + } catch (InvocationTargetException e) { + Throwable cause = e.getTargetException(); + boolean isChecked = false; + for (DataType<?> d : operation.getFaultTypes()) { + if (d.getPhysical().isInstance(cause)) { + isChecked = true; + msg.setFaultBody(cause); + break; + } + } + if (!isChecked) { + if (cause instanceof RuntimeException) { + throw (RuntimeException)cause; + } + if (cause instanceof Error) { + throw (Error)cause; + } else { + throw new ServiceRuntimeException(cause.getMessage(), cause); + } + } + + } catch (ObjectCreationException e) { + throw new ServiceRuntimeException(e.getMessage(), e); + } catch (Exception e) { + msg.setFaultBody(e); + } finally { + // set the tccl + Thread.currentThread().setContextClassLoader(tccl); + } + return msg; + } + + private void injectCallbacks(ReflectiveInstanceWrapper wrapper, + JavaInterface callbackInterface) { + + for (Injector injector : wrapper.getCallbackInjectors()) { + if (injector != null) { + try { + if (ServiceReference.class.isAssignableFrom(injector.getType())) { + Class<?> intf = JavaIntrospectionHelper.getBusinessInterface(injector.getType(), injector.getGenericType()); + if ( intf.isAssignableFrom(callbackInterface.getJavaClass())) { + injector.inject(wrapper.getInstance()); + } + } else if (injector.getType().isAssignableFrom(callbackInterface.getJavaClass())) { + injector.inject(wrapper.getInstance()); + } else { + injector.injectNull(wrapper.getInstance()); + } + } catch (Exception e) { + throw new ObjectCreationException("Exception invoking injector - " + e.getMessage(), e); + } + } + } + + } + + @Override + public boolean allowsPassByReference() { + return allowsPBR; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProvider.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProvider.java new file mode 100644 index 0000000000..215a796cc1 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProvider.java @@ -0,0 +1,182 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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.implementation.java.invocation; + +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.context.ComponentContextFactory; +import org.apache.tuscany.sca.context.PropertyValueFactory; +import org.apache.tuscany.sca.context.RequestContextFactory; +import org.apache.tuscany.sca.core.factory.InstanceWrapper; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.scope.Scope; +import org.apache.tuscany.sca.core.scope.ScopedImplementationProvider; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.JavaResourceImpl; +import org.apache.tuscany.sca.implementation.java.injection.RequestContextObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.ResourceHost; +import org.apache.tuscany.sca.implementation.java.injection.ResourceObjectFactory; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.InvokerAsyncRequest; +import org.apache.tuscany.sca.invocation.InvokerAsyncResponse; +import org.apache.tuscany.sca.provider.ImplementationAsyncProvider; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.oasisopen.sca.ComponentContext; +import org.oasisopen.sca.RequestContext; + +/** + * @version $Rev$ $Date$ + */ +public class JavaImplementationProvider implements ScopedImplementationProvider, ImplementationAsyncProvider { + private JavaImplementation implementation; + private JavaComponentContextProvider componentContextProvider; + private RequestContextFactory requestContextFactory; + private Scope scope; + + public JavaImplementationProvider(RuntimeComponent component, + JavaImplementation implementation, + ProxyFactory proxyService, + DataBindingExtensionPoint dataBindingRegistry, + PropertyValueFactory propertyValueObjectFactory, + ComponentContextFactory componentContextFactory, + RequestContextFactory requestContextFactory) { + super(); + this.implementation = implementation; + this.requestContextFactory = requestContextFactory; + + try { + JavaInstanceFactoryProvider configuration = new JavaInstanceFactoryProvider(implementation); + configuration.setProxyFactory(proxyService); + componentContextProvider = + new JavaComponentContextProvider(component, + configuration, + dataBindingRegistry, + propertyValueObjectFactory, + componentContextFactory, + requestContextFactory); + + this.scope = new Scope(implementation.getJavaScope().getScope()); + componentContextProvider.configureProperties(component.getProperties()); + handleResources(implementation, proxyService); + } catch (Exception e) { + throw new IllegalStateException(e); + } + + } + + private void handleResources(JavaImplementation componentType, ProxyFactory proxyService) { + for (JavaResourceImpl resource : componentType.getResources().values()) { + String name = resource.getName(); + + ObjectFactory<?> objectFactory = + (ObjectFactory<?>)componentContextProvider.getInstanceFactoryProvider().getFactories().get(resource.getElement()); + if (objectFactory == null) { + Class<?> type = resource.getElement().getType(); + if (ComponentContext.class.equals(type)) { + objectFactory = new JavaComponentContextFactory(componentContextProvider); + } else if (RequestContext.class.equals(type)) { + objectFactory = new RequestContextObjectFactory(requestContextFactory, componentContextProvider.getComponent()); + } else if (String.class.equals(type)) { + objectFactory = new JavaComponentNameFactory(componentContextProvider); + } else { + boolean optional = resource.isOptional(); + String mappedName = resource.getMappedName(); + objectFactory = createResourceObjectFactory(type, mappedName, optional, null); + } + } + componentContextProvider.addResourceFactory(name, objectFactory); + } + } + + private <T> ResourceObjectFactory<T> createResourceObjectFactory(Class<T> type, + String mappedName, + boolean optional, + ResourceHost host) { + return new ResourceObjectFactory<T>(type, mappedName, optional, host); + } + + public Invoker createInvoker(RuntimeComponentService service, Operation operation) { + try { + return componentContextProvider.createInvoker(operation, service.getInterfaceContract()); + } catch (NoSuchMethodException e) { + // It's possible that the instance being invoked is a user-specified + // callback object that isn't an instance of the component implementation + // class. As an attempt to deal with this, look up a method object from + // the service interface. This isn't foolproof, as it's possible that + // the service interface isn't a Java interface, or that the callback + // object has the right method signature without implementing the + // callback interface. There is code in JavaImplementationInvoker + // to deal with these possibilities. + Interface iface = service.getInterfaceContract().getInterface(); + if (iface instanceof JavaInterface) { + try { + Method method = JavaInterfaceUtil.findMethod(((JavaInterface)iface).getJavaClass(), operation); + return new JavaImplementationInvoker(operation, method, componentContextProvider.getComponent(), service.getInterfaceContract()); + } catch (NoSuchMethodException e1) { + throw new IllegalArgumentException(e1); + } + } else { + return new JavaImplementationInvoker(operation, componentContextProvider.getComponent(), service.getInterfaceContract()); + } + } + } + + public boolean supportsOneWayInvocation() { + return false; + } + + public Scope getScope() { + return scope; + } + + public void start() { + componentContextProvider.start(); + } + + public void stop() { + componentContextProvider.stop(); + } + + public InstanceWrapper<?> createInstanceWrapper() { + return componentContextProvider.createInstanceWrapper(); + } + + public boolean isEagerInit() { + return implementation.isEagerInit(); + } + + public InvokerAsyncRequest createAsyncInvoker(RuntimeComponentService service, Operation operation) { + // createInvoker should automatically create a JavaAsyncImplementationInvoker - if not, then it means + // that the service is not async and the result will be an exception caused by the class cast. + return (InvokerAsyncRequest) createInvoker( service, operation ); + } // end method createAsyncInvoker + + public InvokerAsyncResponse createAsyncResponseInvoker(Operation operation) { + return new JavaAsyncResponseInvokerImpl(); + } // end method createAsyncResponseInvoker + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProviderFactory.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProviderFactory.java new file mode 100644 index 0000000000..b59966a39e --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProviderFactory.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.implementation.java.invocation; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.tuscany.sca.context.ComponentContextFactory; +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.CglibProxyFactory; +import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.provider.ImplementationProvider; +import org.apache.tuscany.sca.provider.ImplementationProviderFactory; +import org.apache.tuscany.sca.runtime.RuntimeComponent; + +/** + * @version $Rev$ $Date$ + */ +public class JavaImplementationProviderFactory implements ImplementationProviderFactory<JavaImplementation> { + private static final Logger logger = Logger.getLogger(JavaImplementationProviderFactory.class.getName()); + private PropertyValueFactory propertyValueFactory; + private DataBindingExtensionPoint databindings; + private ProxyFactory proxyFactory; + private ComponentContextFactory componentContextFactory; + private RequestContextFactory requestContextFactory; + + public JavaImplementationProviderFactory(ExtensionPointRegistry registry) { + FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class); + MessageFactory messageFactory = factories.getFactory(MessageFactory.class); + + UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class); + InterfaceContractMapper interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class); + + ProxyFactoryExtensionPoint proxyFactories = registry.getExtensionPoint(ProxyFactoryExtensionPoint.class); + try { + proxyFactories.setClassProxyFactory(new CglibProxyFactory(messageFactory, interfaceContractMapper)); + } catch (NoClassDefFoundError e) { + logger.log(Level.WARNING, "Class-based proxy is not supported", e); + } + + databindings = registry.getExtensionPoint(DataBindingExtensionPoint.class); + propertyValueFactory = factories.getFactory(PropertyValueFactory.class); + + ContextFactoryExtensionPoint contextFactories = registry.getExtensionPoint(ContextFactoryExtensionPoint.class); + componentContextFactory = contextFactories.getFactory(ComponentContextFactory.class); + requestContextFactory = contextFactories.getFactory(RequestContextFactory.class); + + proxyFactory = ExtensibleProxyFactory.getInstance(registry); + } + + /* + public JavaImplementationProviderFactory(ProxyFactory proxyService, + DataBindingExtensionPoint dataBindingRegistry, + PropertyValueFactory propertyValueObjectFactory, + ComponentContextFactory componentContextFactory, + RequestContextFactory requestContextFactory) { + super(); + this.proxyFactory = proxyService; + this.databindings = dataBindingRegistry; + this.propertyValueFactory = propertyValueObjectFactory; + this.componentContextFactory = componentContextFactory; + this.requestContextFactory = requestContextFactory; + } + */ + + public ImplementationProvider createImplementationProvider(RuntimeComponent component, + JavaImplementation implementation) { + return new JavaImplementationProvider(component, + implementation, + proxyFactory, + databindings, + propertyValueFactory, + componentContextFactory, + requestContextFactory); + } + + public Class<JavaImplementation> getModelType() { + return JavaImplementation.class; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaInstanceFactoryProvider.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaInstanceFactoryProvider.java new file mode 100644 index 0000000000..e89b618cfe --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaInstanceFactoryProvider.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.implementation.java.invocation; + +import java.lang.annotation.ElementType; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.implementation.java.JavaConstructorImpl; +import org.apache.tuscany.sca.implementation.java.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.context.InstanceFactory; +import org.apache.tuscany.sca.implementation.java.context.InstanceFactoryProvider; +import org.apache.tuscany.sca.implementation.java.context.ReflectiveInstanceFactory; +import org.apache.tuscany.sca.implementation.java.injection.ArrayMultiplicityObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.FieldInjector; +import org.apache.tuscany.sca.implementation.java.injection.Injector; +import org.apache.tuscany.sca.implementation.java.injection.InvalidAccessorException; +import org.apache.tuscany.sca.implementation.java.injection.ListMultiplicityObjectFactory; +import org.apache.tuscany.sca.implementation.java.injection.MethodInjector; +import org.apache.tuscany.sca.implementation.java.introspect.JavaIntrospectionHelper; + +/** + * Encapsulates configuration for a Java-based atomic component + * + * @version $Rev$ $Date$ + */ +public class JavaInstanceFactoryProvider<T> implements InstanceFactoryProvider<T> { + private JavaImplementation definition; + private ProxyFactory proxyService; + + private final List<JavaElementImpl> injectionSites; + private final EventInvoker<T> initInvoker; + private final EventInvoker<T> destroyInvoker; + private final Map<JavaElementImpl, Object> factories = new HashMap<JavaElementImpl, Object>(); + private final List<JavaElementImpl> callbackInjectionSites; + + public JavaInstanceFactoryProvider(JavaImplementation definition) { + this.definition = definition; + this.initInvoker = definition.getInitMethod() == null ? null : new MethodEventInvoker<T>(definition + .getInitMethod()); + this.destroyInvoker = definition.getDestroyMethod() == null ? null : new MethodEventInvoker<T>(definition + .getDestroyMethod()); + injectionSites = new ArrayList<JavaElementImpl>(); + callbackInjectionSites = new ArrayList<JavaElementImpl>(); + } + + ProxyFactory getProxyFactory() { + return proxyService; + } + + void setProxyFactory(ProxyFactory proxyService) { + this.proxyService = proxyService; + } + + /** + * @return the definition + */ + JavaImplementation getImplementation() { + return definition; + } + + @SuppressWarnings("unchecked") + public InstanceFactory<T> createFactory() { + ObjectFactory<?>[] initArgs = getConstructorArgs(); + Injector<T>[] injectors = getInjectors(false); + Injector<T>[] callbackInjectors = getInjectors(true); + return new ReflectiveInstanceFactory<T>((Constructor<T>)definition.getConstructor().getConstructor(), + initArgs, injectors, callbackInjectors, initInvoker, destroyInvoker); + } + + + + private ObjectFactory<?>[] getConstructorArgs() { + JavaConstructorImpl<?> constructor = definition.getConstructor(); + ObjectFactory<?>[] initArgs = new ObjectFactory<?>[constructor.getParameters().length]; + for (int i = 0; i < initArgs.length; i++) { + ObjectFactory<?> factory = (ObjectFactory<?>)factories.get(constructor.getParameters()[i]); + assert factory != null; + initArgs[i] = factory; + } + return initArgs; + } + + + + @SuppressWarnings("unchecked") + private Injector<T>[] getInjectors(boolean callback) { + List<JavaElementImpl> sites = null; + if ( callback ) + sites = callbackInjectionSites; + else + sites = injectionSites; + + // work around JDK1.5 issue with allocating generic arrays + Injector<T>[] injectors = new Injector[sites.size()]; + + int i = 0; + for (JavaElementImpl element : sites) { + Object obj = factories.get(element); + if (obj != null) { + if (obj instanceof ObjectFactory) { + ObjectFactory<?> factory = (ObjectFactory<?>)obj; + Member member = (Member)element.getAnchor(); + if (element.getElementType() == ElementType.FIELD) { + injectors[i++] = new FieldInjector<T>((Field)member, factory); + } else if (element.getElementType() == ElementType.PARAMETER && member instanceof Method) { + injectors[i++] = new MethodInjector<T>((Method)member, factory); + } else if (member instanceof Constructor) { + // Ignore + } else { + throw new AssertionError(String.valueOf(element)); + } + } else { + injectors[i++] = createMultiplicityInjector(element, (List<ObjectFactory<?>>)obj); + } + } + } + return injectors; + } + + private Injector<T> createMultiplicityInjector(JavaElementImpl element, List<ObjectFactory<?>> factories) { + Class<?> interfaceType = JavaIntrospectionHelper.getBaseType(element.getType(), element.getGenericType()); + + if (element.getAnchor() instanceof Field) { + Field field = (Field)element.getAnchor(); + if (field.getType().isArray()) { + return new FieldInjector<T>(field, new ArrayMultiplicityObjectFactory(interfaceType, factories)); + } else { + return new FieldInjector<T>(field, new ListMultiplicityObjectFactory(factories, field.getType())); + } + } else if (element.getAnchor() instanceof Method) { + Method method = (Method)element.getAnchor(); + if (method.getParameterTypes()[0].isArray()) { + return new MethodInjector<T>(method, new ArrayMultiplicityObjectFactory(interfaceType, factories)); + } else { + return new MethodInjector<T>(method, new ListMultiplicityObjectFactory(factories, method.getParameterTypes()[0])); + } + } else { + throw new InvalidAccessorException("Member must be a field or method: " + element.getName()); + } + } + + @SuppressWarnings("unchecked") + public Class<T> getImplementationClass() { + return (Class<T>)definition.getJavaClass(); + } + + public void setObjectFactory(JavaElementImpl element, ObjectFactory<?> objectFactory) { + factories.put(element, objectFactory); + } + + public void setObjectFactories(JavaElementImpl element, List<ObjectFactory<?>> objectFactory) { + factories.put(element, objectFactory); + } + + /** + * @return the injectionSites + */ + List<JavaElementImpl> getInjectionSites() { + return injectionSites; + } + + /** + * @return the callbackInjectionSites + */ + public List<JavaElementImpl> getCallbackInjectionSites() { + return callbackInjectionSites; + } + + /** + * @return the factories + */ + Map<JavaElementImpl, Object> getFactories() { + return factories; + } + + + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/MethodEventInvoker.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/MethodEventInvoker.java new file mode 100644 index 0000000000..515a7c8a43 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/MethodEventInvoker.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.implementation.java.invocation; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + + +/** + * Performs an wire on a method of a given instance + * + * @version $Rev$ $Date$ + */ +public class MethodEventInvoker<T> implements EventInvoker<T> { + private final Method method; + + /** + * Instantiates an invoker for the given method + */ + public MethodEventInvoker(Method method) { + assert method != null; + this.method = method; + } + + public void invokeEvent(T instance) throws EventInvocationException { + try { + method.invoke(instance, (Object[]) null); + } catch (IllegalArgumentException e) { + String name = method.getName(); + throw new EventInvocationException("Exception thrown by event method [" + name + "]", e.getCause()); + } catch (IllegalAccessException e) { + String name = method.getName(); + throw new EventInvocationException("Method is not accessible [" + name + "]"); + } catch (InvocationTargetException e) { + String name = method.getName(); + throw new EventInvocationException("Exception thrown by event method [" + name + "]", e.getCause()); + } + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/NoConversationalContractException.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/NoConversationalContractException.java new file mode 100644 index 0000000000..dbc5c6b640 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/NoConversationalContractException.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.implementation.java.invocation; + + +/** + * Raised when a component has conversational scope but no conversational contract + * + * @version $Rev$ $Date$ + */ +public class NoConversationalContractException extends Exception { + private static final long serialVersionUID = -1157790036638157539L; + + public NoConversationalContractException(String message) { + super(message); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/ResponseDispatchImpl.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/ResponseDispatchImpl.java new file mode 100644 index 0000000000..343682d8b1 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/ResponseDispatchImpl.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.implementation.java.invocation; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +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.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.core.invocation.AsyncFaultWrapper; +import org.apache.tuscany.sca.core.invocation.AsyncResponseHandler; +import org.apache.tuscany.sca.core.invocation.AsyncResponseInvoker; +import org.apache.tuscany.sca.core.invocation.CallbackReferenceObjectFactory; +import org.apache.tuscany.sca.core.invocation.Constants; +import org.apache.tuscany.sca.core.invocation.ExtensibleProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.invocation.MessageFactory; +import org.apache.tuscany.sca.runtime.RuntimeEndpointReference; +import org.oasisopen.sca.ResponseDispatch; +import org.oasisopen.sca.ServiceReference; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * Implementation of the ResponseDispatch interface of the OASIS SCA Java API + * + * This is used for invocations of asynchronous services, where it is passed as a parameter on async service operations + * and it provides the path by which the service implementation returns the response to the request, or a Fault + * + * Note that this class is serializable and can be serialized, stored and deserialized by the service implementation + * + * @param <T> - type of the response message + */ +public class ResponseDispatchImpl<T> implements ResponseDispatch<T>, Serializable { + + /** + * Generated serialVersionUID value + */ + private static final long serialVersionUID = 300158355992568592L; + + // A latch used to ensure that the sendResponse() and sendFault() operations are used at most once + // The latch is initialized with the value "false" + private AtomicBoolean latch = new AtomicBoolean(); + + private final Lock lock = new ReentrantLock(); + private final Condition completed = lock.newCondition(); + + // The result + private transient volatile T response = null; + private transient volatile Throwable fault = null; + + private transient ExtensionPointRegistry registry; + private MessageFactory msgFactory; + + // Service Reference used for the callback + private volatile ServiceReference<AsyncResponseHandler<?>> callbackRef; + private AsyncResponseInvoker<?> respInvoker; + private String messageID; + + /** + * No-arg constructor for serialization purposes + */ + public ResponseDispatchImpl() { + super(); + } // end constructor + + public ResponseDispatchImpl( Message msg ) { + super(); + + respInvoker = (AsyncResponseInvoker<?>)msg.getHeaders().get(Constants.ASYNC_RESPONSE_INVOKER); + //if( respInvoker == null ) throw new ServiceRuntimeException("Async Implementation invoked with no response invoker"); + + if( respInvoker == null ) { + callbackRef = getAsyncCallbackRef( msg ); + } // end if + + messageID = (String) msg.getHeaders().get(Constants.MESSAGE_ID); + + } // end constructor + + public static <T> ResponseDispatchImpl<T> newInstance( Class<T> type, Message msg ) { + return new ResponseDispatchImpl<T>( msg ); + } + + /** + * Provide Context data for this ResponseDispatch that the service implementation can use + */ + public Map<String, Object> getContext() { + return null; + } + + /** + * Send a Fault. Must only be invoked once for this ResponseDispatch object + * @param e - the Fault to send + * @throws IllegalStateException if either the sendResponse method or the sendFault method have been called previously + */ + public void sendFault(Throwable e) { + if( sendOK() ) { + lock.lock(); + try { + fault = e; + completed.signalAll(); + } finally { + lock.unlock(); + } // end try + } else { + throw new IllegalStateException("sendResponse() or sendFault() has been called previously"); + } // end if + + // Use response invoker if present + if( respInvoker != null ) { + //respInvoker.invokeAsyncResponse(new AsyncFaultWrapper(e)); + respInvoker.invokeAsyncResponse(e, null); + return; + } // end if + + // Now dispatch the response to the callback... + AsyncResponseHandler<T> handler = (AsyncResponseHandler<T>) callbackRef.getService(); + setResponseHeaders(); + handler.setWrappedFault(new AsyncFaultWrapper(e)); + } // end method sendFault + + /** + * Send the response message. Must only be invoked once for this ResponseDispatch object + * @throws IllegalStateException if either the sendResponse method or the sendFault method have been called previously + * @param res - the response message, which is of type T + */ + @SuppressWarnings("unchecked") + public void sendResponse(T res) { + if( sendOK() ) { + lock.lock(); + try { + response = res; + completed.signalAll(); + } finally { + lock.unlock(); + } // end try + } else { + throw new IllegalStateException("sendResponse() or sendFault() has been called previously"); + } // end if + + // Now dispatch the response to the callback, if present... + if( callbackRef != null ) { + AsyncResponseHandler<T> handler = (AsyncResponseHandler<T>) callbackRef.getService(); + setResponseHeaders(); + handler.setResponse(res); + } // end if + + // Use response invoker if present + if( respInvoker != null ) { + respInvoker.invokeAsyncResponse(res, null); + return; + } // end if + } // end method sendResponse + + public T get(long timeout, TimeUnit unit) throws Throwable { + lock.lock(); + try { + // wait for result to be available + if( response == null && fault == null ) completed.await( timeout, unit); + if( response != null ) return response; + if( fault != null ) throw fault; + } finally { + lock.unlock(); + } // end try + + return null; + } // end method get + + /** + * Indicates that sending a response is OK - this is a transactional + * query in that it also updates the state of this ResponseDispatch, so + * that it will return true once and once only + * @return - true if it is OK to send the response, false otherwise + */ + private boolean sendOK() { + return latch.compareAndSet(false, true); + } + + /** + * Creates a service reference for the async callback, based on information contained in the supplied message + * @param msg - the incoming message + * @return - a CallBackServiceReference + */ + @SuppressWarnings("unchecked") + private ServiceReference<AsyncResponseHandler<?>> getAsyncCallbackRef( Message msg ) { + RuntimeEndpointReference callbackEPR = (RuntimeEndpointReference) msg.getHeaders().get(Constants.ASYNC_CALLBACK); + if( callbackEPR == null ) return null; + + CompositeContext compositeContext = callbackEPR.getCompositeContext(); + registry = compositeContext.getExtensionPointRegistry(); + ProxyFactory proxyFactory = ExtensibleProxyFactory.getInstance(registry); + msgFactory = getMessageFactory(); + List<EndpointReference> eprList = new ArrayList<EndpointReference>(); + eprList.add(callbackEPR); + ObjectFactory<?> factory = new CallbackReferenceObjectFactory(AsyncResponseHandler.class, proxyFactory, eprList); + + return (ServiceReference<AsyncResponseHandler<?>>) factory.getInstance(); + + } // end method getAsyncCallbackEPR + + /** + * Sets the values of various headers in the response message + */ + private void setResponseHeaders() { + // Is there an existing message context? + Message msgContext = ThreadMessageContext.getMessageContext(); + if( msgContext == null ) { + // Create a message context + msgContext = msgFactory.createMessage(); + } // end if + + // Add in the header for the RelatesTo Message ID + msgContext.getHeaders().put(Constants.RELATES_TO, messageID); + + ThreadMessageContext.setMessageContext(msgContext); + } // end method setResponseHeaders + + private MessageFactory getMessageFactory() { + FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class); + return modelFactories.getFactory(MessageFactory.class); + } // end method getMessageFactory +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.PropertyValueFactory b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.PropertyValueFactory new file mode 100644 index 0000000000..9d5f943f46 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.context.PropertyValueFactory @@ -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.implementation.java.injection.JavaPropertyValueObjectFactory
diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.definitions.xml.Definitions b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.definitions.xml.Definitions new file mode 100644 index 0000000000..2b67aa59ca --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.definitions.xml.Definitions @@ -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/implementation/java/definitions/definitions.xml
diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.implementation.java.introspect.JavaClassVisitor b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.implementation.java.introspect.JavaClassVisitor new file mode 100644 index 0000000000..e649b68466 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.implementation.java.introspect.JavaClassVisitor @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+# NOTE: The ranking attribute is important for the JavaClassVistors
+# Some visitors need to be called after the others
+org.apache.tuscany.sca.implementation.java.databinding.PropertyDataTypeProcessor;ranking=750
diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory new file mode 100644 index 0000000000..1c2626706b --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.provider.ImplementationProviderFactory @@ -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 implementation extension
+org.apache.tuscany.sca.implementation.java.invocation.JavaImplementationProviderFactory;model=org.apache.tuscany.sca.implementation.java.JavaImplementation
+
diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.RuntimeWireProcessor b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/resources/META-INF/services/org.apache.tuscany.sca.runtime.RuntimeWireProcessor new file mode 100644 index 0000000000..07008049e8 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/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.implementation.java.invocation.JavaCallbackRuntimeWireProcessor
diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/resources/org/apache/tuscany/sca/implementation/java/definitions/definitions.xml b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/resources/org/apache/tuscany/sca/implementation/java/definitions/definitions.xml new file mode 100644 index 0000000000..e790317458 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/main/resources/org/apache/tuscany/sca/implementation/java/definitions/definitions.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> + +<!-- $Rev$ $Date$ --> + +<sca:definitions xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" + targetNamespace="http://docs.oasis-open.org/ns/opencsa/sca/200912" + xmlns:sca="http://docs.oasis-open.org/ns/opencsa/sca/200912" + xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.1"> + + <sca:implementationType type="sca:implementation.java" mayProvide="" alwaysProvides=""/> + + </sca:definitions> diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/context/MultiplicityTestCase.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/context/MultiplicityTestCase.java new file mode 100644 index 0000000000..629ba8b321 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/context/MultiplicityTestCase.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.implementation.java.context; + +import org.junit.Test; + + + +/** + * Tests wires that are configured with a multiplicity + * + * @version $Rev$ $Date$ + */ +public class MultiplicityTestCase { + + @Test + public void testMultiplicity() throws Exception { + // TODO implement + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapperTestCase.java.fixme b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapperTestCase.java.fixme new file mode 100644 index 0000000000..628a308c86 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapperTestCase.java.fixme @@ -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.implementation.java.context; + +import static org.easymock.EasyMock.createMock; +import junit.framework.TestCase; + +import org.apache.tuscany.sca.core.scope.TargetDestructionException; +import org.apache.tuscany.sca.core.scope.TargetInitializationException; +import org.apache.tuscany.sca.implementation.java.invocation.EventInvoker; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class ReflectiveInstanceWrapperTestCase extends TestCase { + private ReflectiveInstanceWrapper<Object> wrapper; + private Object instance; + private EventInvoker<Object> initInvoker; + private EventInvoker<Object> destroyInvoker; + + public void testWithNoCallbacks() { + wrapper = new ReflectiveInstanceWrapper<Object>(instance, null, null); + try { + wrapper.start(); + } catch (TargetInitializationException e) { + fail(); + } + try { + wrapper.stop(); + } catch (TargetDestructionException e) { + fail(); + } + } + + public void testWithStartCallback() { + initInvoker.invokeEvent(instance); + EasyMock.replay(initInvoker); + wrapper = new ReflectiveInstanceWrapper<Object>(instance, initInvoker, null); + try { + wrapper.start(); + } catch (TargetInitializationException e) { + fail(); + } + EasyMock.verify(initInvoker); + } + + public void testWithStopCallback() { + destroyInvoker.invokeEvent(instance); + EasyMock.replay(destroyInvoker); + wrapper = new ReflectiveInstanceWrapper<Object>(instance, null, destroyInvoker); + try { + wrapper.stop(); + } catch (TargetDestructionException e) { + fail(); + } + EasyMock.verify(destroyInvoker); + } + + @Override + @SuppressWarnings("unchecked") + protected void setUp() throws Exception { + super.setUp(); + instance = new Object(); + initInvoker = createMock(EventInvoker.class); + destroyInvoker = createMock(EventInvoker.class); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/CallbackWireObjectFactoryTestCase.java.fixme b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/CallbackWireObjectFactoryTestCase.java.fixme new file mode 100644 index 0000000000..29dcfa8169 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/CallbackWireObjectFactoryTestCase.java.fixme @@ -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.implementation.java.injection; + +import static org.easymock.EasyMock.createMock; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.tuscany.sca.core.invocation.CallbackWireObjectFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.runtime.RuntimeWire; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class CallbackWireObjectFactoryTestCase extends TestCase { + + @SuppressWarnings({"unchecked"}) + public void testCreateInstance() throws Exception { + ProxyFactory service = createMock(ProxyFactory.class); + Foo foo = new Foo() { + }; + EasyMock.expect(service.createCallbackProxy(EasyMock.eq(Foo.class), EasyMock.isA(List.class))).andReturn(foo); + EasyMock.replay(service); + List<RuntimeWire> wires = new ArrayList<RuntimeWire>(); + CallbackWireObjectFactory factory = new CallbackWireObjectFactory(Foo.class, service, wires); + assertEquals(foo, factory.getInstance()); + EasyMock.verify(service); + } + + private interface Foo { + + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/FieldInjectorTestCase.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/FieldInjectorTestCase.java new file mode 100644 index 0000000000..098789f495 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/FieldInjectorTestCase.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.implementation.java.injection; + +import static org.junit.Assert.assertEquals; + +import java.lang.reflect.Field; + +import org.junit.Before; +import org.junit.Test; + +/** + * @version $Rev$ $Date$ + */ +public class FieldInjectorTestCase { + + protected Field protectedField; + + @Test + public void testIllegalAccess() throws Exception { + FieldInjector<Foo> injector = new FieldInjector<Foo>(protectedField, new SingletonObjectFactory<String>("foo")); + Foo foo = new Foo(); + injector.inject(foo); + assertEquals("foo", foo.hidden); + } + + + @Before + public void setUp() throws Exception { + protectedField = Foo.class.getDeclaredField("hidden"); + } + + private class Foo { + private String hidden; + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/JavaPropertyValueObjectFactoryTestCase.java.fixme b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/JavaPropertyValueObjectFactoryTestCase.java.fixme new file mode 100644 index 0000000000..366f21d9f0 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/JavaPropertyValueObjectFactoryTestCase.java.fixme @@ -0,0 +1,449 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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.implementation.java.injection; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.assembly.AssemblyFactory; +import org.apache.tuscany.sca.assembly.DefaultAssemblyFactory; +import org.apache.tuscany.sca.assembly.Property; +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.DefaultDataBindingExtensionPoint; +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl; +import org.apache.tuscany.sca.implementation.java.JavaElementImpl; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * This test case will test the JavaPropertyValueObjectFactory. + * + * @version $Rev$ $Date$ + */ +public class JavaPropertyValueObjectFactoryTestCase { + + /** + * The factory we should use for testing. + */ + private static JavaPropertyValueObjectFactory factory; + + /** + * The assembly factory used to create Properties. + */ + private static AssemblyFactory assemblyFactory; + + /** + * Test Setup. + */ + @BeforeClass + public static void setup() { + // Create the factory + Mediator mediator = EasyMock.createNiceMock(Mediator.class); + DataBindingExtensionPoint dpep = new DefaultDataBindingExtensionPoint(); + EasyMock.expect(mediator.getDataBindings()).andReturn(dpep).anyTimes(); + EasyMock.replay(mediator); + factory = new JavaPropertyValueObjectFactory(mediator); + + // Create the AssemblyFactory we should use + assemblyFactory = new DefaultAssemblyFactory(); + } + + /** + * A test that will attempt to inject positive, negative and zero into an + * int property. + */ + @Test + public void testIntegerInjectionValid() { + InjectionTestParams params = new InjectionTestParams(); + params.propertyName = "intField"; + params.xsdType = SimpleTypeMapperImpl.XSD_INT; + params.expectedType = Integer.TYPE; + + for (int i = -5; i <= 5; i++) { + params.propertyValue = Integer.toString(i); + params.expectedValueFromFactory = i; + doInjection(params); + } + } + + /** + * A test that will attempt to inject positive, negative and zero into an + * int property using a JavaElement. + */ + @Test + public void testIntegerInjectionValidWithJavaElement() { + InjectionTestParams params = new InjectionTestParams(); + params.propertyName = "intField"; + params.xsdType = SimpleTypeMapperImpl.XSD_INT; + params.expectedJavaElement = new JavaElementImpl(int.class); + + for (int i = -5; i <= 5; i++) { + params.propertyValue = Integer.toString(i); + params.expectedValueFromFactory = i; + doInjection(params); + } + } + + /** + * A test that will attempt to inject multiple int values into an + * int property. + */ + @Test + public void testIntegerArrayInjectionValid() { + InjectionTestParams params = new InjectionTestParams(); + params.propertyName = "intField"; + params.xsdType = SimpleTypeMapperImpl.XSD_INT; + params.isMany = true; + params.expectedType = int.class; + params.propertyValue = "1 2 3 4 5"; + params.expectedValueFromFactory = Arrays.asList(1, 2, 3, 4, 5); + doInjection(params); + } + + /** + * A test that will attempt to inject multiple int values into an + * int property using a JavaElement. + */ + @Test + public void testIntegerArrayInjectionValidWithJavaElement() { + InjectionTestParams params = new InjectionTestParams(); + params.propertyName = "intField"; + params.xsdType = SimpleTypeMapperImpl.XSD_INT; + params.isMany = true; + params.expectedJavaElement = new JavaElementImpl(int[].class); + params.propertyValue = "1 2 3 4 5"; + int[] expected = { 1, 2, 3, 4, 5 }; + params.expectedValueFromFactory = expected; + doInjection(params); + } + + /** + * A test that will attempt to inject a non-number into an + * int property. + */ + @Test + public void testIntegerInjectionBadNumberInvalid() { + InjectionTestParams params = new InjectionTestParams(); + params.propertyName = "intField"; + params.xsdType = SimpleTypeMapperImpl.XSD_INT; + params.expectedType = Integer.TYPE; + params.propertyValue = "a"; + params.exceptionExpected = true; + doInjection(params); + } + + /** + * A test that will attempt to inject a non-number into an + * int property using a JavaElement. + */ + @Test + public void testIntegerInjectionBadNumberInvalidWithJavaElement() { + InjectionTestParams params = new InjectionTestParams(); + params.propertyName = "intField"; + params.xsdType = SimpleTypeMapperImpl.XSD_INT; + params.expectedJavaElement = new JavaElementImpl(Integer.TYPE); + params.propertyValue = "a"; + params.exceptionExpected = true; + doInjection(params); + } + + /** + * A test that will attempt to inject multiple int values into an + * int property where one of the property values is not a number. + * The injection should throw ObjectCreationException + */ + @Test + public void testIntegerArrayInjectionBadNumberInvalid() { + InjectionTestParams params = new InjectionTestParams(); + params.propertyName = "intField"; + params.xsdType = SimpleTypeMapperImpl.XSD_INT; + params.isMany = true; + params.expectedType = int.class; + params.propertyValue = "1 2 aa 4 5"; + params.exceptionExpected = true; + doInjection(params); + } + + /** + * A test that will attempt to inject multiple int values into an + * int property using a JavaElement where one of the property + * values is not a number. + * The injection should throw ObjectCreationException + */ + @Test + public void testIntegerArrayInjectionBadNumberInvalidWithJavaElement() { + InjectionTestParams params = new InjectionTestParams(); + params.propertyName = "intField"; + params.xsdType = SimpleTypeMapperImpl.XSD_INT; + params.isMany = true; + params.expectedJavaElement = new JavaElementImpl(int[].class); + params.propertyValue = "1 2 aa 4 5"; + params.exceptionExpected = true; + doInjection(params); + } + + /** + * A test that will attempt to inject an empty string into an int property. + * The injection should throw ObjectCreationException + */ + @Test + public void testIntegerInjectionEmptyStringInvalid() { + InjectionTestParams params = new InjectionTestParams(); + params.propertyName = "intField"; + params.xsdType = SimpleTypeMapperImpl.XSD_INT; + params.expectedType = Integer.TYPE; + params.propertyValue = ""; + params.exceptionExpected = true; + doInjection(params); + } + + /** + * A test that will attempt to inject an empty string into an int property + * using a JavaElement. + * The injection should throw ObjectCreationException + */ + @Test + public void testIntegerInjectionEmptyStringInvalidWithJavaElement() { + InjectionTestParams params = new InjectionTestParams(); + params.propertyName = "intField"; + params.xsdType = SimpleTypeMapperImpl.XSD_INT; + params.expectedJavaElement = new JavaElementImpl(Integer.TYPE); + params.propertyValue = ""; + params.exceptionExpected = true; + doInjection(params); + } + + /** + * A test that will attempt to inject a String into a String + * property. + */ + @Test + public void testStringInjectionValid() { + InjectionTestParams params = new InjectionTestParams(); + params.propertyName = "StringField"; + params.xsdType = SimpleTypeMapperImpl.XSD_STRING; + params.expectedType = String.class; + + params.propertyValue = "Some Test String"; + params.expectedValueFromFactory = "Some Test String"; + doInjection(params); + } + + /** + * A test that will attempt to inject a String into a String + * property using a JavaElement. + */ + @Test + public void testStringInjectionValidWithJavaElement() { + InjectionTestParams params = new InjectionTestParams(); + params.propertyName = "StringField"; + params.xsdType = SimpleTypeMapperImpl.XSD_STRING; + params.expectedJavaElement = new JavaElementImpl(String.class); + + params.propertyValue = "Some Test String"; + params.expectedValueFromFactory = "Some Test String"; + doInjection(params); + } + + /** + * This class defines all the parameters for the Property Injection test. + */ + private class InjectionTestParams { + // Input parameters for the test + public boolean isMany = false; + public String propertyName; + public String propertyValue; + public QName xsdType; + + // Expected result for test + public Object expectedValueFromFactory; + public Class<?> expectedType; + public JavaElementImpl expectedJavaElement; + public boolean exceptionExpected = false; + } + + /** + * A test that will attempt to inject multiple String values into an + * String property. + */ + @Test + public void testStringArrayInjectionValid() { + InjectionTestParams params = new InjectionTestParams(); + params.propertyName = "StringField"; + params.xsdType = SimpleTypeMapperImpl.XSD_STRING; + params.isMany = true; + params.expectedType = String.class; + params.propertyValue = "\"String1\" \"String2\" \"String3\" \"String4\" \"String5\""; + params.expectedValueFromFactory = Arrays.asList( + "String1", "String2", "String3", "String4", "String5"); + doInjection(params); + } + + /** + * A test that will attempt to inject multiple String values into an + * String property using a JavaElement. + */ + @Test + public void testStringArrayInjectionValidWithJavaElement() { + InjectionTestParams params = new InjectionTestParams(); + params.propertyName = "StringField"; + params.xsdType = SimpleTypeMapperImpl.XSD_STRING; + params.isMany = true; + params.expectedJavaElement = new JavaElementImpl(String.class); + params.propertyValue = "\"String1\" \"String2\" \"String3\" \"String4\" \"String5\""; + params.expectedValueFromFactory = Arrays.asList( + "String1", "String2", "String3", "String4", "String5"); + doInjection(params); + } + + /** + * Utility method for testing creating properties with the + * JavaPropertyValueObjectFactory. + * + * @param testParams The parameters for the test + */ + private void doInjection(final InjectionTestParams testParams) { + // Create the property + Property prop = assemblyFactory.createProperty(); + prop.setMany(testParams.isMany); + prop.setName(testParams.propertyName); + prop.setXSDType(testParams.xsdType); + + // Mock up the XML that will contain the Property details + Document doc = EasyMock.createNiceMock(Document.class); + Element rootElement = EasyMock.createMock(Element.class); + EasyMock.expect(doc.getDocumentElement()).andReturn(rootElement); + NodeList nodeList = EasyMock.createMock(NodeList.class); + EasyMock.expect(rootElement.getChildNodes()).andReturn(nodeList).anyTimes(); + EasyMock.expect(nodeList.getLength()).andReturn(1); + Node node = EasyMock.createMock(Node.class); + EasyMock.expect(nodeList.item(0)).andReturn(node); + EasyMock.expect(node.getTextContent()).andReturn(testParams.propertyValue); + EasyMock.replay(doc, rootElement, nodeList, node); + + // Create a factory either using the Class or JavaElementImpl constructor + ObjectFactory<?> objectFactory; + if (testParams.expectedJavaElement != null) { + objectFactory = factory.createValueFactory(prop, doc, testParams.expectedJavaElement); + } else { + objectFactory = factory.createValueFactory(prop, doc, testParams.expectedType); + } + Assert.assertNotNull(objectFactory); + + // Lets test the factory + try { + // Create a new instance with the factory + Object value = objectFactory.getInstance(); + + // Did we expect an exception to be thrown? + if (testParams.exceptionExpected) { + Assert.fail("Test should have thrown ObjectCreationException"); + } + + // Make sure the result is of the correct type + if (testParams.expectedValueFromFactory instanceof Collection<?>) { + // Make sure the Collections contain the same type + Assert.assertTrue(value instanceof Collection<?>); + Iterator<?> iter1 = ((Collection<?>) testParams.expectedValueFromFactory).iterator(); + Iterator<?> iter2 = ((Collection<?>) value).iterator(); + Assert.assertEquals(iter1.next().getClass(), iter2.next().getClass()); + } else { + Assert.assertEquals(testParams.expectedValueFromFactory.getClass(), value.getClass()); + } + + // Validate the result + Assert.assertNotNull(value); + if (testParams.expectedValueFromFactory.getClass().isArray()) { + Assert.assertTrue(compareArrays(testParams.expectedValueFromFactory, value)); + } else { + Assert.assertEquals(testParams.expectedValueFromFactory, value); + } + } catch (ObjectCreationException ex) { + // Is this an expected exception? + if (testParams.exceptionExpected) { + // Make sure the exception error message contains the property name + Assert.assertTrue(ex.toString().indexOf(testParams.propertyName) != -1); + + // Make sure the exception error message contains the property value + if (testParams.propertyValue != null) { + if (testParams.isMany) { + // FIXME: No simple way to do this for multi-value properties + } else { + Assert.assertTrue(ex.toString().indexOf(testParams.propertyValue) != -1); + } + } + } else { + // Test failure. We were not expecting an exception + ex.printStackTrace(); + Assert.fail("Unexpected exception " + ex); + } + } + } + + /** + * Compares two Objects that are actually arrays to make sure that they are + * equal. + * + * @param array1 The first array + * @param array2 The second array + * @return True if they are equal. False if they are not + */ + private boolean compareArrays(final Object array1, final Object array2) { + // Check for primitive array types + if (array1 instanceof boolean[]) { + return Arrays.equals((boolean[]) array1, (boolean[]) array2); + } + if (array1 instanceof byte[]) { + return Arrays.equals((byte[]) array1, (byte[]) array2); + } + if (array1 instanceof char[]) { + return Arrays.equals((char[]) array1, (char[]) array2); + } + if (array1 instanceof double[]) { + return Arrays.equals((double[]) array1, (double[]) array2); + } + if (array1 instanceof float[]) { + return Arrays.equals((float[]) array1, (float[]) array2); + } + if (array1 instanceof int[]) { + return Arrays.equals((int[]) array1, (int[]) array2); + } + if (array1 instanceof long[]) { + return Arrays.equals((long[]) array1, (long[]) array2); + } + if (array1 instanceof short[]) { + return Arrays.equals((short[]) array1, (short[]) array2); + } + + // Not a primitive so must be an Object[] + return Arrays.equals((Object[]) array1, (Object[]) array2); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/MethodEventInvokerTestCase.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/MethodEventInvokerTestCase.java new file mode 100644 index 0000000000..e9cbce4390 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/MethodEventInvokerTestCase.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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.implementation.java.injection; + +import static org.junit.Assert.fail; + +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.implementation.java.invocation.EventInvocationException; +import org.apache.tuscany.sca.implementation.java.invocation.MethodEventInvoker; +import org.junit.Before; +import org.junit.Test; + +/** + * @version $Rev$ $Date$ + */ +public class MethodEventInvokerTestCase { + private Method privateMethod; + private Method exceptionMethod; + + @Test + public void testIllegalAccess() throws Exception { + MethodEventInvoker<MethodEventInvokerTestCase.Foo> injector = new MethodEventInvoker<Foo>(privateMethod); + try { + injector.invokeEvent(new Foo()); + fail(); + } catch (EventInvocationException e) { + // expected + } + } + + @Test + public void testException() throws Exception { + MethodEventInvoker<MethodEventInvokerTestCase.Foo> injector = new MethodEventInvoker<Foo>(exceptionMethod); + try { + injector.invokeEvent(new Foo()); + fail(); + } catch (RuntimeException e) { + // expected + } + } + + @Before + public void setUp() throws Exception { + privateMethod = MethodEventInvokerTestCase.Foo.class.getDeclaredMethod("hidden"); + exceptionMethod = MethodEventInvokerTestCase.Foo.class.getDeclaredMethod("exception"); + + } + + public class Foo { + + public void foo() { + } + + private void hidden() { + } + + public void exception() { + throw new RuntimeException(); + } + + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/MethodInjectorTestCase.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/MethodInjectorTestCase.java new file mode 100644 index 0000000000..19184d5204 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/MethodInjectorTestCase.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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.implementation.java.injection; + +import static org.junit.Assert.fail; + +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.junit.Before; +import org.junit.Test; + +/** + * @version $Rev$ $Date$ + */ +public class MethodInjectorTestCase { + private Method fooMethod; + private Method privateMethod; + private Method exceptionMethod; + + @Test + public void testIllegalArgument() throws Exception { + ObjectFactory<Object> factory = new SingletonObjectFactory<Object>(new Object()); + MethodInjector<Foo> injector = new MethodInjector<Foo>(fooMethod, factory); + try { + injector.inject(new Foo()); + fail(); + } catch (ObjectCreationException e) { + // expected + } + } + + @Test + public void testException() throws Exception { + ObjectFactory<Object> factory = new SingletonObjectFactory<Object>("foo"); + MethodInjector<Foo> injector = new MethodInjector<Foo>(exceptionMethod, factory); + try { + injector.inject(new Foo()); + fail(); + } catch (RuntimeException e) { + // expected + } + } + + @Before + public void setUp() throws Exception { + fooMethod = Foo.class.getMethod("foo", String.class); + privateMethod = Foo.class.getDeclaredMethod("hidden", String.class); + exceptionMethod = Foo.class.getDeclaredMethod("exception", String.class); + + } + + private class Foo { + + public void foo(String bar) { + } + + private void hidden(String bar) { + } + + public void exception(String bar) { + throw new RuntimeException(); + } + + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/ResourceObjectFactoryTestCase.java.fixme b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/ResourceObjectFactoryTestCase.java.fixme new file mode 100644 index 0000000000..ed7a0e7d03 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/ResourceObjectFactoryTestCase.java.fixme @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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.implementation.java.injection; + +import junit.framework.TestCase; + +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class ResourceObjectFactoryTestCase extends TestCase { + + public void testResolveFromHostByType() throws Exception { + ResourceHost host = EasyMock.createMock(ResourceHost.class); + EasyMock.expect(host.resolveResource(EasyMock.eq(String.class))).andReturn("foo"); + EasyMock.replay(host); + ResourceObjectFactory<String> factory = new ResourceObjectFactory<String>(String.class, false, host); + assertEquals("foo", factory.getInstance()); + EasyMock.verify(host); + } + + public void testResolveFromHostByName() throws Exception { + ResourceHost host = EasyMock.createMock(ResourceHost.class); + EasyMock.expect(host.resolveResource(EasyMock.eq(String.class), + EasyMock.eq("sca://localhost/bar"))).andReturn("foo"); + EasyMock.replay(host); + ResourceObjectFactory<String> factory = + new ResourceObjectFactory<String>(String.class, "sca://localhost/bar", false, host); + assertEquals("foo", factory.getInstance()); + EasyMock.verify(host); + } + + + public void testResolveFromParentThenResolveFromHostNotFound() throws Exception { + ResourceHost host = EasyMock.createMock(ResourceHost.class); + EasyMock.expect(host.resolveResource(EasyMock.eq(String.class))).andReturn(null); + EasyMock.replay(host); + ResourceObjectFactory<String> factory = new ResourceObjectFactory<String>(String.class, true, host); + assertNull(factory.getInstance()); + EasyMock.verify(host); + } + + public void testResolveByTypeNotFound() throws Exception { +// ResourceHost host = EasyMock.createMock(ResourceHost.class); +// EasyMock.expect(host.resolveResource(EasyMock.eq(String.class))).andReturn(null); +// EasyMock.replay(host); +// +// RuntimeWire wire = EasyMock.createMock(RuntimeWire.class); +// EasyMock.expect(wire.getTargetInstance()).andReturn(null); +// EasyMock.replay(wire); +// +// ResourceObjectFactory<String> factory = new ResourceObjectFactory<String>(String.class, false, host); +// try { +// factory.getInstance(); +// fail(); +// } catch (ResourceNotFoundException e) { +// //expected +// } +// EasyMock.verify(host); + } + + public void testResolveByTypeNotFoundOptional() throws Exception { + ResourceHost host = EasyMock.createMock(ResourceHost.class); + EasyMock.expect(host.resolveResource(EasyMock.eq(String.class))).andReturn(null); + EasyMock.replay(host); + ResourceObjectFactory<String> factory = new ResourceObjectFactory<String>(String.class, true, host); + assertNull(factory.getInstance()); + EasyMock.verify(host); + } + + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/SingletonObjectFactory.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/SingletonObjectFactory.java new file mode 100644 index 0000000000..c1650c3a83 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/SingletonObjectFactory.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.implementation.java.injection; + +import org.apache.tuscany.sca.core.factory.ObjectFactory; + +/** + * Implementation of ObjectFactory that returns a single instance, typically an immutable type. + * + * @version $Rev$ $Date$ + */ +public class SingletonObjectFactory<T> implements ObjectFactory<T> { + private final T instance; + + public SingletonObjectFactory(T instance) { + this.instance = instance; + } + + public T getInstance() { + return instance; + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/SingletonObjectFactoryTestCase.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/SingletonObjectFactoryTestCase.java new file mode 100644 index 0000000000..0bb222bad4 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/SingletonObjectFactoryTestCase.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.implementation.java.injection; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +/** + * @version $Rev$ $Date$ + */ +public class SingletonObjectFactoryTestCase { + + @Test + public void testSingleton() throws Exception { + Object o = new Object(); + SingletonObjectFactory<Object> factory = new SingletonObjectFactory<Object>(o); + assertEquals(o, factory.getInstance()); + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/TestObjectFactory.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/TestObjectFactory.java new file mode 100644 index 0000000000..de371e09bb --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/TestObjectFactory.java @@ -0,0 +1,120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.injection; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.factory.ObjectFactory; + +/** + * Creates new instances of a Java class + * + * @version $Rev$ $Date$ + * @see org.apache.tuscany.sca.implementation.java.injection.Injector + */ +public class TestObjectFactory<T> implements ObjectFactory<T> { + + private final Constructor<T> ctr; + private ObjectFactory[] initializerFactories; + + /** + * Creates the object factory + * + * @param ctr the constructor to use when instantiating a new object + */ + public TestObjectFactory(Constructor<T> ctr) { + assert ctr != null; + this.ctr = ctr; + initializerFactories = new ObjectFactory[ctr.getParameterTypes().length]; + } + + /** + * Creates the object factory + * + * @param ctr the constructor to use when instantiating a new object + * @param factories an ordered list of <code>ObjectFactory</code>s to use for returning constructor parameters + */ + public TestObjectFactory(Constructor<T> ctr, List<ObjectFactory> factories) { + assert ctr != null; + int params = ctr.getParameterTypes().length; + assert params == factories.size(); + this.ctr = ctr; + initializerFactories = new ObjectFactory[params]; + int i = 0; + for (ObjectFactory factory : factories) { + initializerFactories[i] = factory; + i++; + } + } + + /** + * Returns the ordered array of <code>ObjectFactory</code>s use in creating constructor parameters + */ + public ObjectFactory[] getInitializerFactories() { + return initializerFactories; + } + + /** + * Sets an <code>ObjectFactory</code>s to use in creating constructor parameter + * + * @param pos the constructor parameter position + * @param factory the object factory + */ + public void setInitializerFactory(int pos, ObjectFactory factory) { + assert pos < initializerFactories.length; + initializerFactories[pos] = factory; + } + + /** + * Creates a new instance of an object + */ + public T getInstance() throws ObjectCreationException { + int size = initializerFactories.length; + Object[] initargs = new Object[size]; + // create the constructor arg array + for (int i = 0; i < size; i++) { + ObjectFactory<?> objectFactory = initializerFactories[i]; + if (objectFactory == null) { + // this can happen if a reference is optional + initargs[i] = null; + } else { + initargs[i] = objectFactory.getInstance(); + } + } + try { + ctr.setAccessible(true); + return ctr.newInstance(initargs); + } catch (IllegalArgumentException e) { + String name = ctr.getName(); + throw new ObjectCreationException("Exception thrown by constructor: " + name, e); + } catch (InstantiationException e) { + String name = ctr.getDeclaringClass().getName(); + throw new AssertionError("Class is not instantiable [" + name + "]"); + } catch (IllegalAccessException e) { + String name = ctr.getName(); + throw new AssertionError("Constructor is not accessible [" + name + "]"); + } catch (InvocationTargetException e) { + String name = ctr.getName(); + throw new ObjectCreationException("Exception thrown by constructor: " + name, e); + } + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/TestObjectFactoryTestCase.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/TestObjectFactoryTestCase.java new file mode 100644 index 0000000000..ea9d15b3f6 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/injection/TestObjectFactoryTestCase.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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.implementation.java.injection; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.sca.core.factory.ObjectFactory; +import org.junit.Before; +import org.junit.Test; + +/** + * @version $Rev$ $Date$ + */ +public class TestObjectFactoryTestCase { + + private Constructor<Foo> ctor; + + @Test + public void testConstructorInjection() throws Exception { + List<ObjectFactory> initializers = new ArrayList<ObjectFactory>(); + initializers.add(new SingletonObjectFactory<String>("foo")); + TestObjectFactory<Foo> factory = new TestObjectFactory<Foo>(ctor, initializers); + Foo foo = factory.getInstance(); + assertEquals("foo", foo.foo); + } + + /** + * Verifies null parameters can be passed to a constructor. This is valid when a reference is optional during + * constructor injection + */ + @Test + public void testConstructorInjectionOptionalParam() throws Exception { + List<ObjectFactory> initializers = new ArrayList<ObjectFactory>(); + initializers.add(null); + TestObjectFactory<Foo> factory = new TestObjectFactory<Foo>(ctor, initializers); + Foo foo = factory.getInstance(); + assertNull(foo.foo); + } + + @Test + public void testConstructorInitializerInjection() throws Exception { + TestObjectFactory<Foo> factory = new TestObjectFactory<Foo>(ctor); + factory.setInitializerFactory(0, new SingletonObjectFactory<String>("foo")); + Foo foo = factory.getInstance(); + assertEquals("foo", foo.foo); + } + + @Before + public void setUp() throws Exception { + ctor = Foo.class.getConstructor(String.class); + } + + private static class Foo { + + private String foo; + + public Foo(String foo) { + this.foo = foo; + } + } +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Bean1.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Bean1.java new file mode 100644 index 0000000000..e993cdd382 --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Bean1.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.implementation.java.util; + + +/** + * + * @version $Rev$ $Date$ + */ +public class Bean1 extends SuperBean { + + public static final int ALL_BEAN1_FIELDS = 6 + ALL_SUPER_FIELDS; + public static final int ALL_BEAN1_PUBLIC_PROTECTED_FIELDS = 5 + ALL_SUPER_PUBLIC_PROTECTED_FIELDS; + public static final int ALL_BEAN1_METHODS = 4 + ALL_SUPER_METHODS - 1; + public String field3; + protected String field2; + private String field1; + + public void setMethod1(String param) { + } + + public void setMethod1(int param) { + } + + @Override + public void override(String param) throws Exception { + } + + + public void noOverride(String param) throws Exception { + } + + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Bean2.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Bean2.java new file mode 100644 index 0000000000..f5128f6a6c --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Bean2.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.implementation.java.util; + +import java.util.List; + +/** + * + * @version $Rev$ $Date$ + */ +public class Bean2 { + + private List methodList; + private List fieldList; + + public List getMethodList() { + return methodList; + } + + public void setMethodList(List list) { + methodList = list; + } + + public List getfieldList() { + return fieldList; + } + + public void setfieldList(List list) { + throw new RuntimeException("setter inadvertantly called"); + } + + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Entry.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Entry.java new file mode 100644 index 0000000000..a5e12d181c --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/Entry.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.implementation.java.util; + +/** + * Implementations are used in wiring tests + * + * @version $Rev$ $Date$ + */ +public interface Entry { + + String getString(); + + void setString(String val); +} + diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/JavaIntrospectionHelperTestCase.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/JavaIntrospectionHelperTestCase.java new file mode 100644 index 0000000000..9624865dcc --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/JavaIntrospectionHelperTestCase.java @@ -0,0 +1,189 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.implementation.java.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.tuscany.sca.implementation.java.introspect.JavaIntrospectionHelper; +import org.junit.Test; + +/** + * + * @version $Rev$ $Date$ + */ +public class JavaIntrospectionHelperTestCase { + + private List testNoGenericsList; + private List<String> testList; + private Map<String, Bean1> testMap; + private Entry[] testArray; + private String[] testStringArray; + + @Test + public void testBean1AllPublicProtectedFields() throws Exception { + Set<Field> beanFields = JavaIntrospectionHelper.getAllPublicAndProtectedFields(Bean1.class, true); + assertEquals(4, beanFields.size()); //Bean1.ALL_BEAN1_PUBLIC_PROTECTED_FIELDS + } + + @Test + public void testGetSuperAllMethods() throws Exception { + Set<Method> superBeanMethods = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(SuperBean.class, true); + assertEquals(SuperBean.ALL_SUPER_METHODS, superBeanMethods.size()); + } + + @Test + public void testGetBean1AllMethods() throws Exception { + Set<Method> beanMethods = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(Bean1.class, true); + assertEquals(Bean1.ALL_BEAN1_METHODS, beanMethods.size()); + } + + @Test + public void testOverrideMethod() throws Exception { + Set<Method> beanFields = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(Bean1.class, true); + boolean invoked = false; + for (Method method : beanFields) { + if (method.getName().equals("override")) { + method.invoke(new Bean1(), "foo"); + invoked = true; + } + } + if (!invoked) { + throw new Exception("Override never invoked"); + } + } + + @Test + public void testNoOverrideMethod() throws Exception { + Set<Method> beanFields = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(Bean1.class, true); + boolean found = false; + for (Method method : beanFields) { + if (method.getName().equals("noOverride") && method.getParameterTypes().length == 0) { + found = true; + } + } + if (!found) { + throw new Exception("No override not found"); + } + } + + @Test + public void testDefaultConstructor() throws Exception { + Constructor<Bean2> ctr = JavaIntrospectionHelper.getDefaultConstructor(Bean2.class); + assertEquals(ctr, Bean2.class.getConstructor()); + assertTrue(Bean2.class == ctr.newInstance((Object[]) null).getClass()); + } + + + @Test + public void testGetAllInterfaces() { + Set<Class<?>> interfaces = JavaIntrospectionHelper.getAllInterfaces(Z.class); + assertEquals(2, interfaces.size()); + assertTrue(interfaces.contains(W.class)); + assertTrue(interfaces.contains(W2.class)); + } + + + @Test + public void testGetAllInterfacesObject() { + Set<Class<?>> interfaces = JavaIntrospectionHelper.getAllInterfaces(Object.class); + assertEquals(0, interfaces.size()); + } + + @Test + public void testGetAllInterfacesNoInterfaces() { + Set<Class<?>> interfaces = JavaIntrospectionHelper.getAllInterfaces(NoInterface.class); + assertEquals(0, interfaces.size()); + } + + /** + * Tests generics introspection capabilities + */ + @Test + public void testGenerics() throws Exception { + + List classes = JavaIntrospectionHelper.getGenerics(getClass().getDeclaredField("testList").getGenericType()); + assertEquals(1, classes.size()); + assertEquals(String.class, classes.get(0)); + + classes = + JavaIntrospectionHelper.getGenerics(getClass().getDeclaredField("testNoGenericsList").getGenericType()); + assertEquals(0, classes.size()); + + classes = JavaIntrospectionHelper.getGenerics(getClass().getDeclaredField("testMap").getGenericType()); + assertEquals(2, classes.size()); + assertEquals(String.class, classes.get(0)); + assertEquals(Bean1.class, classes.get(1)); + + classes = JavaIntrospectionHelper + .getGenerics(getClass().getDeclaredMethod("fooMethod", Map.class).getGenericParameterTypes()[0]); + assertEquals(2, classes.size()); + assertEquals(String.class, classes.get(0)); + assertEquals(Bean1.class, classes.get(1)); + + classes = JavaIntrospectionHelper + .getGenerics(getClass().getDeclaredMethod("fooMethod", List.class).getGenericParameterTypes()[0]); + assertEquals(1, classes.size()); + assertEquals(String.class, classes.get(0)); + + } + + private void fooMethod(List<String> foo) { + + } + + private void fooMethod(Map<String, Bean1> foo) { + + } + + public void setTestArray(Entry[] array) { + } + + private interface W { + + } + + private interface W2 { + + } + + private class X implements W { + + } + + private class Y extends X implements W, W2 { + + } + + private class Z extends Y { + + } + + private class NoInterface { + + } + +} diff --git a/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/SuperBean.java b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/SuperBean.java new file mode 100644 index 0000000000..408cedb8be --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta3/modules/implementation-java-runtime/src/test/java/org/apache/tuscany/sca/implementation/java/util/SuperBean.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.implementation.java.util; + +/** + * @version $Rev$ $Date$ + */ +public class SuperBean { + + public static final int ALL_SUPER_FIELDS = 6; + public static final int ALL_SUPER_PUBLIC_PROTECTED_FIELDS = 5; + public static final int ALL_SUPER_METHODS = 4; + public String superField2; + + protected String superField3; + + private String superField1; + + public void setSuperMethod1(String param) { + } + + public void setSuperMethod1(int param) { + } + + public void override(String param) throws Exception { + throw new Exception("Override not handled"); + } + + public void noOverride() throws Exception { + } + +} |