diff options
Diffstat (limited to 'sca-java-1.x/branches/sca-java-M2/sca/kernel/core')
441 files changed, 44916 insertions, 0 deletions
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/.pmd b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/.pmd new file mode 100644 index 0000000000..ffc4fe2bbb --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/.pmd @@ -0,0 +1,20 @@ +<?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. +--> +<pmd><useProjectRuleSet>true</useProjectRuleSet><rules/></pmd> diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/.ruleset b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/.ruleset new file mode 100644 index 0000000000..ba9b5ce886 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/.ruleset @@ -0,0 +1,190 @@ +<?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. +--> +<ruleset name="pmd-eclipse"> + <description>PMD Plugin preferences rule set</description> + + + <rule ref="rulesets/basic.xml/BooleanInstantiation"/> + <rule ref="rulesets/basic.xml/CollapsibleIfStatements"/> + <rule ref="rulesets/basic.xml/DoubleCheckedLocking"/> +<!--<rule ref="rulesets/basic.xml/EmptyCatchBlock"/>--> +<!--<rule ref="rulesets/basic.xml/EmptyFinallyBlock"/>--> +<!--<rule ref="rulesets/basic.xml/EmptyIfStmt"/>--> + <rule ref="rulesets/basic.xml/EmptyStatementNotInLoop"/> +<!--<rule ref="rulesets/basic.xml/EmptyStaticInitializer"/>--> +<!--<rule ref="rulesets/basic.xml/EmptySwitchStatements"/>--> +<!--<rule ref="rulesets/basic.xml/EmptySynchronizedBlock"/>--> +<!--<rule ref="rulesets/basic.xml/EmptyTryBlock"/>--> +<!--<rule ref="rulesets/basic.xml/EmptyWhileStmt"/>--> + <rule ref="rulesets/basic.xml/ForLoopShouldBeWhileLoop"/> + <rule ref="rulesets/basic.xml/JumbledIncrementer"/> +<!--<rule ref="rulesets/basic.xml/OverrideBothEqualsAndHashcode"/>--> + <rule ref="rulesets/basic.xml/ReturnFromFinallyBlock"/> + <rule ref="rulesets/basic.xml/UnconditionalIfStatement"/> + <rule ref="rulesets/basic.xml/UnnecessaryConversionTemporary"/> + <rule ref="rulesets/basic.xml/UnnecessaryFinalModifier"/> + <rule ref="rulesets/basic.xml/UnnecessaryReturn"/> +<!--<rule ref="rulesets/basic.xml/UselessOverridingMethod"/>--> + +<!--<rule ref="rulesets/braces.xml/ForLoopsMustUseBraces"/>--> +<!--<rule ref="rulesets/braces.xml/IfElseStmtsMustUseBraces"/>--> +<!--<rule ref="rulesets/braces.xml/IfStmtsMustUseBraces"/>--> +<!--<rule ref="rulesets/braces.xml/WhileLoopsMustUseBraces"/>--> + +<!--<rule ref="rulesets/clone.xml/CloneMethodMustImplementCloneable"/>--> +<!--<rule ref="rulesets/clone.xml/CloneThrowsCloneNotSupportedException"/>--> +<!--<rule ref="rulesets/clone.xml/ProperCloneImplementation"/>--> + +<!--<rule ref="rulesets/codesize.xml/CyclomaticComplexity"/>--> +<!--<rule ref="rulesets/codesize.xml/ExcessiveClassLength"/>--> +<!--<rule ref="rulesets/codesize.xml/ExcessiveMethodLength"/>--> +<!--<rule ref="rulesets/codesize.xml/ExcessiveParameterList"/>--> +<!--<rule ref="rulesets/codesize.xml/ExcessivePublicCount"/>--> +<!--<rule ref="rulesets/codesize.xml/TooManyFields"/>--> + +<rule ref="rulesets/controversial.xml/AssignmentInOperand"/> +<!--<rule ref="rulesets/controversial.xml/AtLeastOneConstructor"/>--> +<!--<rule ref="rulesets/controversial.xml/CallSuperInConstructor"/>--> +<!--<rule ref="rulesets/controversial.xml/DontImportSun"/>--> +<!--<rule ref="rulesets/controversial.xml/NullAssignment"/>--> +<!--<rule ref="rulesets/controversial.xml/OnlyOneReturn"/>--> +<!--<rule ref="rulesets/controversial.xml/SingularField"/>--> +<!--<rule ref="rulesets/controversial.xml/SuspiciousOctalEscape"/>--> +<!--<rule ref="rulesets/controversial.xml/UnnecessaryConstructor"/>--> +<rule ref="rulesets/controversial.xml/UnnecessaryParentheses"/> +<!--<rule ref="rulesets/controversial.xml/UnusedModifier"/>--> + +<!--<rule ref="rulesets/coupling.xml/CouplingBetweenObjects"/>--> +<!--<rule ref="rulesets/coupling.xml/ExcessiveImports"/>--> +<!--<rule ref="rulesets/coupling.xml/LooseCoupling"/>--> + +<!--<rule ref="rulesets/design.xml/AbstractClassWithoutAbstractMethod"/>--> +<!--<rule ref="rulesets/design.xml/AccessorClassGeneration"/>--> +<!--<rule ref="rulesets/design.xml/AssignmentToNonFinalStatic"/>--> +<!--<rule ref="rulesets/design.xml/AvoidDeeplyNestedIfStmts"/>--> +<!--<rule ref="rulesets/design.xml/AvoidInstanceofChecksInCatchClause"/>--> +<rule ref="rulesets/design.xml/AvoidProtectedFieldInFinalClass"/> +<!--<rule ref="rulesets/design.xml/AvoidReassigningParameters"/>--> +<!--<rule ref="rulesets/design.xml/AvoidSynchronizedAtMethodLevel"/>--> +<!--<rule ref="rulesets/design.xml/BadComparison"/>--> +<!--<rule ref="rulesets/design.xml/CloseConnection"/>--> +<!--<rule ref="rulesets/design.xml/CompareObjectsWithEquals"/>--> +<!--<rule ref="rulesets/design.xml/ConfusingTernary"/>--> +<rule ref="rulesets/design.xml/ConstructorCallsOverridableMethod"/> +<!--<rule ref="rulesets/design.xml/DefaultLabelNotLastInSwitchStmt"/>--> +<!--<rule ref="rulesets/design.xml/FinalFieldCouldBeStatic"/>--> +<rule ref="rulesets/design.xml/IdempotentOperations"/> +<!--<rule ref="rulesets/design.xml/ImmutableField"/>--> +<!--<rule ref="rulesets/design.xml/InstantiationToGetClass"/>--> +<!--<rule ref="rulesets/design.xml/MissingBreakInSwitch"/>--> +<!--<rule ref="rulesets/design.xml/MissingStaticMethodInNonInstantiatableClass"/>--> +<!--<rule ref="rulesets/design.xml/NonCaseLabelInSwitchStatement"/>--> +<!--<rule ref="rulesets/design.xml/NonStaticInitializer"/>--> +<rule ref="rulesets/design.xml/OptimizableToArrayCall"/> +<rule ref="rulesets/design.xml/PositionLiteralsFirstInComparisons"/> +<rule ref="rulesets/design.xml/SimplifyBooleanExpressions"/> +<rule ref="rulesets/design.xml/SimplifyBooleanReturns"/> +<rule ref="rulesets/design.xml/SimplifyConditional"/> +<!--<rule ref="rulesets/design.xml/SwitchDensity"/>--> +<!--<rule ref="rulesets/design.xml/SwitchStmtsShouldHaveDefault"/>--> +<!--<rule ref="rulesets/design.xml/UnnecessaryLocalBeforeReturn"/>--> +<!--<rule ref="rulesets/design.xml/UseLocaleWithCaseConversions"/>--> +<!--<rule ref="rulesets/design.xml/UseNotifyAllInsteadOfNotify"/>--> +<!--<rule ref="rulesets/design.xml/UseSingleton"/>--> + +<!--<rule ref="rulesets/finalizers.xml/EmptyFinalizer"/>--> +<!--<rule ref="rulesets/finalizers.xml/FinalizeOnlyCallsSuperFinalize"/>--> +<!--<rule ref="rulesets/finalizers.xml/FinalizeOverloaded"/>--> +<!--<rule ref="rulesets/finalizers.xml/FinalizeDoesNotCallSuperFinalize"/>--> +<!--<rule ref="rulesets/finalizers.xml/FinalizeShouldBeProtected"/>--> +<!--<rule ref="rulesets/finalizers.xml/AvoidCallingFinalize"/>--> + +<!--<rule ref="rulesets/imports.xml/DuplicateImports"/>--> +<!--<rule ref="rulesets/imports.xml/DontImportJavaLang"/>--> +<!--<rule ref="rulesets/imports.xml/UnusedImports"/>--> +<!--<rule ref="rulesets/imports.xml/ImportFromSamePackage"/>--> + +<!--<rule ref="rulesets/javabeans.xml/BeanMembersShouldSerialize"/>--> +<!--<rule ref="rulesets/javabeans.xml/MissingSerialVersionUID"/>--> + +<!--<rule ref="rulesets/junit.xml/JUnitStaticSuite"/>--> +<!--<rule ref="rulesets/junit.xml/JUnitSpelling"/>--> +<!--<rule ref="rulesets/junit.xml/JUnitAssertionsShouldIncludeMessage"/>--> +<!--<rule ref="rulesets/junit.xml/JUnitTestsShouldIncludeAssert"/>--> +<!--<rule ref="rulesets/junit.xml/TestClassWithoutTestCases"/>--> +<!--<rule ref="rulesets/junit.xml/UnnecessaryBooleanAssertion"/>--> +<!--<rule ref="rulesets/junit.xml/UseAssertEqualsInsteadOfAssertTrue"/>--> +<!--<rule ref="rulesets/junit.xml/UseAssertSameInsteadOfAssertTrue"/>--> + + <!--<rule ref="rulesets/logging-java.xml/AvoidPrintStackTrace"/>--> + <!--<rule ref="rulesets/logging-java.xml/LoggerIsNotStaticFinal"/>--> + <!--<rule ref="rulesets/logging-java.xml/MoreThanOneLogger"/>--> + <!--<rule ref="rulesets/logging-java.xml/LoggerIsNotStaticFinal"/>--> + <!--<rule ref="rulesets/logging-java.xml/LogBlockWithoutIf"/>--> + <!--<rule ref="rulesets/logging-java.xml/SystemPrintln"/>--> + <!--<rule ref="rulesets/logging-jakarta-commons.xml/UseCorrectExceptionLogging"/>--> + <!--<rule ref="rulesets/logging-jakarta-commons.xml/ProperLogger"/>--> + + <!--<rule ref="rulesets/naming.xml/ShortVariable"/>--> + <!--<rule ref="rulesets/naming.xml/LongVariable"/>--> + <!--<rule ref="rulesets/naming.xml/ShortMethodName"/>--> + <!--<rule ref="rulesets/naming.xml/VariableNamingConventions"/>--> + <!--<rule ref="rulesets/naming.xml/MethodNamingConventions"/>--> + <!--<rule ref="rulesets/naming.xml/ClassNamingConventions"/>--> + <!--<rule ref="rulesets/naming.xml/AbstractNaming"/>--> + <!--<rule ref="rulesets/naming.xml/AvoidDollarSigns"/>--> + <!--<rule ref="rulesets/naming.xml/MethodWithSameNameAsEnclosingClass"/>--> + <!--<rule ref="rulesets/naming.xml/SuspiciousHashcodeMethodName"/>--> + <!--<rule ref="rulesets/naming.xml/SuspiciousConstantFieldName"/>--> + <!--<rule ref="rulesets/naming.xml/AvoidFieldNameMatchingTypeName"/>--> + <!--<rule ref="rulesets/naming.xml/AvoidFieldNameMatchingMethodName"/>--> + <!--<rule ref="rulesets/naming.xml/AvoidNonConstructorMethodsWithClassName"/>--> + <!--<rule ref="rulesets/naming.xml/NoPackage"/>--> + <!--<rule ref="rulesets/naming.xml/PackageCase"/>--> + + <!--<rule ref="rulesets/optimizations.xml/LocalVariableCouldBeFinal"/>--> + <!--<rule ref="rulesets/optimizations.xml/MethodArgumentCouldBeFinal"/>--> + <!--<rule ref="rulesets/optimizations.xml/AvoidInstantiatingObjectsInLoops"/>--> + <!--<rule ref="rulesets/optimizations.xml/UseArrayListInsteadOfVector"/>--> + <!--<rule ref="rulesets/optimizations.xml/SimplifyStartsWith"/>--> + <!--<rule ref="rulesets/optimizations.xml/UseStringBufferForStringAppends"/>--> + + <!--<rule ref="rulesets/strictexception.xml/AvoidCatchingThrowable"/>--> + <!--<rule ref="rulesets/strictexception.xml/SignatureDeclareThrowsException"/>--> + <!--<rule ref="rulesets/strictexception.xml/ExceptionAsFlowControl"/>--> + <!--<rule ref="rulesets/strictexception.xml/AvoidCatchingNPE"/>--> + <!--<rule ref="rulesets/strictexception.xml/AvoidThrowingRawExceptionTypes"/>--> + <!--<rule ref="rulesets/strictexception.xml/AvoidThrowingNullPointerException"/>--> + + <!--<rule ref="rulesets/strings.xml/AvoidDuplicateLiterals"/>--> + <!--<rule ref="rulesets/strings.xml/StringInstantiation"/>--> + <!--<rule ref="rulesets/strings.xml/StringToString"/>--> + <!--<rule ref="rulesets/strings.xml/AvoidConcatenatingNonLiteralsInStringBuffer"/>--> + <!--<rule ref="rulesets/strings.xml/UnnecessaryCaseChange"/>--> + + <!--<rule ref="rulesets/sunsecure.xml/MethodReturnsInternalArray"/>--> + <!--<rule ref="rulesets/sunsecure.xml/ArrayIsStoredDirectly"/>--> + + <rule ref="rulesets/unusedcode.xml/UnusedLocalVariable"/> + <rule ref="rulesets/unusedcode.xml/UnusedPrivateField"/> + <rule ref="rulesets/unusedcode.xml/UnusedPrivateMethod"/> + <!--<rule ref="rulesets/unusedcode.xml/UnusedFormalParameter"/>--> + +</ruleset> diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/LICENSE.txt b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/LICENSE.txt new file mode 100644 index 0000000000..0084319535 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/LICENSE.txt @@ -0,0 +1,202 @@ + + 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, serviceDefinition 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-1.x/branches/sca-java-M2/sca/kernel/core/NOTICE.txt b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/NOTICE.txt new file mode 100644 index 0000000000..d83ebbe236 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/NOTICE.txt @@ -0,0 +1,14 @@ +${pom.name} +Copyright (c) 2005 - 2006 The Apache Software Foundation + +Apache Tuscany is an effort undergoing incubation at The Apache Software +Foundation (ASF), sponsored by the Apache Web Services PMC. Incubation is +required of all newly accepted projects until a further review indicates that +the infrastructure, communications, and decision making process have stabilized +in a manner consistent with other successful ASF projects. While incubation +status is not necessarily a reflection of the completeness or stability of the +code, it does indicate that the project has yet to be fully endorsed by the ASF. + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/pom.xml b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/pom.xml new file mode 100644 index 0000000000..0a90fb8333 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/pom.xml @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<project> + <parent> + <groupId>org.apache.tuscany.sca.kernel</groupId> + <artifactId>parent</artifactId> + <version>1.0-incubator-M2-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <artifactId>core</artifactId> + <packaging>jar</packaging> + <name>Apache Tuscany SCA Core</name> + <description>Core Tuscany runtime.</description> + + <dependencies> + <dependency> + <groupId>org.apache.tuscany.sca.kernel</groupId> + <artifactId>tuscany-spi</artifactId> + <version>${pom.version}</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.apache.tuscany.sca.kernel</groupId> + <artifactId>tuscany-host-api</artifactId> + <version>${sca.version}</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.apache.tuscany</groupId> + <artifactId>commonj-api_r1.1</artifactId> + </dependency> + + <dependency> + <groupId>woodstox</groupId> + <artifactId>wstx-asl</artifactId> + </dependency> + + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>servlet-api</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.geronimo.specs</groupId> + <artifactId>geronimo-j2ee-connector_1.5_spec</artifactId> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + <dependency> + <groupId>org.easymock</groupId> + <artifactId>easymockclassextension</artifactId> + </dependency> + </dependencies> + + <build> + <resources> + <resource> + <directory>src/main/resources</directory> + <filtering>true</filtering> + </resource> + <resource> + <directory>${notice.dir}</directory> + <targetPath>META-INF</targetPath> + <filtering>true</filtering> + <includes> + <include>LICENSE.txt</include> + <include>NOTICE.txt</include> + </includes> + </resource> + </resources> + </build> +</project> diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/Bootstrapper.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/Bootstrapper.java new file mode 100644 index 0000000000..0f6b4a2c92 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/Bootstrapper.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.bootstrap; + +import org.apache.tuscany.host.MonitorFactory; +import org.apache.tuscany.spi.bootstrap.RuntimeComponent; +import org.apache.tuscany.spi.builder.Connector; +import org.apache.tuscany.spi.component.ScopeRegistry; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.deployer.Deployer; +import org.apache.tuscany.spi.implementation.java.Introspector; +import org.apache.tuscany.spi.loader.Loader; +import org.apache.tuscany.spi.loader.PropertyObjectFactory; + +/** + * Interface that abstracts the process used to create a running Tuscany system. Implementation of this may provide + * different mechanisms for creating the primoridal system components used to boot the core to the level where it can + * support end-user applications. + * + * @version $Rev$ $Date$ + */ +public interface Bootstrapper { + /** + * Return the MonitorFactory being used by the implementation to provide monitor interfaces for the primordial + * components. + * + * @return the MonitorFactory being used by the bootstrapper + */ + MonitorFactory getMonitorFactory(); + + /** + * Create the RuntimeComponent that forms the fundamental root of the component assembly. This component has two + * children: a {@link org.apache.tuscany.spi.component.CompositeComponent} that is the root for all system + * components, and a {@link org.apache.tuscany.spi.component.CompositeComponent} that is the root for all + * application components. + * + * @return a new RuntimeComponent; basically a new Tuscany instance + */ + RuntimeComponent createRuntime(); + + /** + * Create a Deployer that can be used to deploy the system definition. This will most likely only support a small + * subset of the available programming model. + * + * @return a new primordial Deployer + */ + Deployer createDeployer(); + + /** + * Create a Loader for parsing a system definition represented as a XML SCDL file. + * + * @param propertyFactory the StAXPropertyFactory to be used to parse property values + * @param introspector the introspector to be used to extract component type information from a Java class + * @return a new prmordial Loader + */ + Loader createLoader(PropertyObjectFactory propertyFactory, Introspector introspector); + + /** + * Create a ScopeRegistry that supports the Scopes supported for primordial components + * + * @param workContext the WorkContext the Scopes should use + * @return a new primordial ScopeRegistry + */ + ScopeRegistry createScopeRegistry(WorkContext workContext); + + /** + * Create a Connector that can wire together primordial components. + * + * @return a new primordial Connector + */ + Connector createConnector(); +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultBootstrapper.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultBootstrapper.java new file mode 100644 index 0000000000..d42e07cbb8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultBootstrapper.java @@ -0,0 +1,247 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.bootstrap; + +import javax.xml.stream.XMLInputFactory; + +import org.apache.tuscany.core.builder.BuilderRegistryImpl; +import org.apache.tuscany.core.builder.ConnectorImpl; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.component.scope.ModuleScopeObjectFactory; +import org.apache.tuscany.core.component.scope.ScopeRegistryImpl; +import org.apache.tuscany.core.deployer.DeployerImpl; +import org.apache.tuscany.core.idl.java.InterfaceJavaLoader; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.implementation.IntrospectionRegistryImpl; +import org.apache.tuscany.core.implementation.composite.CompositeComponentImpl; +import org.apache.tuscany.core.implementation.composite.CompositeLoader; +import org.apache.tuscany.core.implementation.processor.ConstructorProcessor; +import org.apache.tuscany.core.implementation.processor.DestroyProcessor; +import org.apache.tuscany.core.implementation.processor.HeuristicPojoProcessor; +import org.apache.tuscany.core.implementation.processor.ImplementationProcessorServiceImpl; +import org.apache.tuscany.core.implementation.processor.InitProcessor; +import org.apache.tuscany.core.implementation.processor.MonitorProcessor; +import org.apache.tuscany.core.implementation.processor.PropertyProcessor; +import org.apache.tuscany.core.implementation.processor.ReferenceProcessor; +import org.apache.tuscany.core.implementation.processor.ScopeProcessor; +import org.apache.tuscany.core.implementation.processor.ServiceProcessor; +import org.apache.tuscany.core.implementation.system.builder.SystemBindingBuilder; +import org.apache.tuscany.core.implementation.system.builder.SystemComponentBuilder; +import org.apache.tuscany.core.implementation.system.builder.SystemCompositeBuilder; +import org.apache.tuscany.core.implementation.system.loader.SystemBindingLoader; +import org.apache.tuscany.core.implementation.system.loader.SystemComponentTypeLoader; +import org.apache.tuscany.core.implementation.system.loader.SystemCompositeComponentTypeLoader; +import org.apache.tuscany.core.implementation.system.loader.SystemImplementationLoader; +import org.apache.tuscany.core.implementation.system.model.SystemBinding; +import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation; +import org.apache.tuscany.core.implementation.system.model.SystemImplementation; +import org.apache.tuscany.core.loader.ComponentLoader; +import org.apache.tuscany.core.loader.ComponentTypeElementLoader; +import org.apache.tuscany.core.loader.IncludeLoader; +import org.apache.tuscany.core.loader.LoaderRegistryImpl; +import org.apache.tuscany.core.loader.PropertyLoader; +import org.apache.tuscany.core.loader.ReferenceLoader; +import org.apache.tuscany.core.loader.ServiceLoader; +import org.apache.tuscany.core.property.PropertyObjectFactoryImpl; +import org.apache.tuscany.host.MonitorFactory; +import org.apache.tuscany.spi.bootstrap.ComponentNames; +import org.apache.tuscany.spi.bootstrap.RuntimeComponent; +import org.apache.tuscany.spi.builder.Builder; +import org.apache.tuscany.spi.builder.BuilderRegistry; +import org.apache.tuscany.spi.builder.Connector; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.ScopeRegistry; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.deployer.Deployer; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService; +import org.apache.tuscany.spi.implementation.java.Introspector; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.PropertyObjectFactory; + +/** + * A default implementation of a Bootstrapper. Please see the documentation on the individual methods for how the + * primordial components are created. + * + * @version $Rev$ $Date$ + */ +public class DefaultBootstrapper implements Bootstrapper { + private final MonitorFactory monitorFactory; + private final XMLInputFactory xmlFactory; + + /** + * Create a default bootstrapper. + * + * @param monitorFactory the MonitorFactory to be used to create monitors for the primordial components + * @param xmlFactory the XMLInputFactory to be used by the components to load XML artifacts + */ + public DefaultBootstrapper(MonitorFactory monitorFactory, XMLInputFactory xmlFactory) { + this.monitorFactory = monitorFactory; + this.xmlFactory = xmlFactory; + } + + /** + * Returns the MonitorFactory being used by this bootstrapper. + * + * @return the MonitorFactory being used by this bootstrapper + */ + public MonitorFactory getMonitorFactory() { + return monitorFactory; + } + + /** + * Create the RuntimeComponent that will form the root of the component tree. Returns an new instance of a {@link + * DefaultRuntime} with the system and application root components initialized with default composite components. + * + * @return a newly created root for the component tree + */ + public RuntimeComponent createRuntime() { + DefaultRuntime runtime = new DefaultRuntime(); + CompositeComponent systemComponent = + new CompositeComponentImpl(ComponentNames.TUSCANY_SYSTEM, runtime, null, null); + runtime.setSystemComponent(systemComponent); + CompositeComponent rootComponent = + new CompositeComponentImpl(ComponentNames.TUSCANY_ROOT, runtime, null, null); + runtime.setRootComponent(rootComponent); + return runtime; + } + + /** + * Create primordial deployer that can be used to load the system definition. + * + * @return the primordial deployer + */ + public Deployer createDeployer() { + ScopeRegistry scopeRegistry = createScopeRegistry(new WorkContextImpl()); + Builder builder = createBuilder(scopeRegistry); + JavaInterfaceProcessorRegistry interfaceIntrospector = new JavaInterfaceProcessorRegistryImpl(); + Introspector introspector = createIntrospector(interfaceIntrospector); + LoaderRegistry loader = createLoader(new PropertyObjectFactoryImpl(), introspector); + return new DeployerImpl(xmlFactory, loader, builder); + } + + /** + * Create a basic ScopeRegistry containing the ScopeContainers that are available to components in the system + * definition. The implementation returned only support MODULE scope. + * + * @param workContext the WorkContext the scopes should use + * @return a new ScopeRegistry + */ + public ScopeRegistry createScopeRegistry(WorkContext workContext) { + ScopeRegistry scopeRegistry = new ScopeRegistryImpl(workContext); + new ModuleScopeObjectFactory(scopeRegistry); // self-registers + return scopeRegistry; + } + + /** + * Create a Loader that can be used to parse an XML file containing the SCDL for the system definition. The + * following Implementation types are supported: <ul> <li>SystemImplementation</li> + * <li>SystemCompositeImplementation</li> </ul> and the following SCDL elements are supported: <ul> + * <li>composite</li> <li>component</li> <li>componentType</li> <li>interface.java</li> <li>property</li> + * <li>reference</li> <li>service</li> <li>implementation.system</li> <li>binding.system</li> </ul> Note the Java + * component type and the WSDL interface type are not supported. + * + * @param propertyFactory the StAXPropertyFactory to be used for parsing Property values + * @param introspector the Introspector to be used to inspect component implementations + * @return a new StAX XML loader + */ + public LoaderRegistry createLoader(PropertyObjectFactory propertyFactory, Introspector introspector) { + LoaderRegistryImpl loaderRegistry = + new LoaderRegistryImpl(monitorFactory.getMonitor(LoaderRegistryImpl.Monitor.class)); + + // register component type loaders + loaderRegistry.registerLoader(SystemImplementation.class, + new SystemComponentTypeLoader(introspector)); + loaderRegistry.registerLoader(SystemCompositeImplementation.class, + new SystemCompositeComponentTypeLoader(loaderRegistry)); + + // register element loaders + registerLoader(loaderRegistry, new ComponentLoader(loaderRegistry, propertyFactory)); + registerLoader(loaderRegistry, new ComponentTypeElementLoader(loaderRegistry)); + registerLoader(loaderRegistry, new CompositeLoader(loaderRegistry, null)); + registerLoader(loaderRegistry, new IncludeLoader(loaderRegistry)); + registerLoader(loaderRegistry, + new InterfaceJavaLoader(loaderRegistry, new JavaInterfaceProcessorRegistryImpl())); + registerLoader(loaderRegistry, new PropertyLoader(loaderRegistry)); + registerLoader(loaderRegistry, new ReferenceLoader(loaderRegistry)); + registerLoader(loaderRegistry, new ServiceLoader(loaderRegistry)); + registerLoader(loaderRegistry, new SystemImplementationLoader(loaderRegistry)); + registerLoader(loaderRegistry, new SystemBindingLoader(loaderRegistry)); + return loaderRegistry; + } + + /** + * Create new Introspector for extracting a ComponentType definition from a Java class. + * + * @return a new Introspector + */ + public Introspector createIntrospector(JavaInterfaceProcessorRegistry registry) { + ImplementationProcessorService service = new ImplementationProcessorServiceImpl(registry); + IntrospectionRegistryImpl introspectionRegistry = + new IntrospectionRegistryImpl(monitorFactory.getMonitor(IntrospectionRegistryImpl.Monitor.class)); + introspectionRegistry.registerProcessor(new ConstructorProcessor(service)); + introspectionRegistry.registerProcessor(new DestroyProcessor()); + introspectionRegistry.registerProcessor(new InitProcessor()); + introspectionRegistry.registerProcessor(new ScopeProcessor()); + introspectionRegistry.registerProcessor(new PropertyProcessor(service)); + introspectionRegistry.registerProcessor(new ReferenceProcessor(registry)); + introspectionRegistry.registerProcessor(new ServiceProcessor(service)); + introspectionRegistry.registerProcessor(new HeuristicPojoProcessor(service)); + introspectionRegistry.registerProcessor(new MonitorProcessor(monitorFactory, service)); + return introspectionRegistry; + } + + /** + * Create a new Connector that can be used to wire primordial components together. + * + * @return a new Connector + */ + public Connector createConnector() { + return new ConnectorImpl(); + } + + /** + * Helper method for registering a loader with the registry. The Loader is registered once for the QName returned by + * its {@link LoaderExtension#getXMLType()} method. + * + * @param registry the LoaderRegistry to register with + * @param loader the Loader to register + */ + protected void registerLoader(LoaderRegistry registry, LoaderExtension<?> loader) { + registry.registerLoader(loader.getXMLType(), loader); + } + + /** + * Create a Builder that can be used to build the components in the system definition. The default implementation + * only supports implementations from the system programming model. + * + * @param scopeRegistry the ScopeRegistry defining the component scopes that will be supported + * @return a new Builder + */ + private Builder createBuilder(ScopeRegistry scopeRegistry) { + BuilderRegistry builderRegistry = new BuilderRegistryImpl(scopeRegistry); + SystemCompositeBuilder builder = new SystemCompositeBuilder(builderRegistry, createConnector()); + builderRegistry.register(SystemCompositeImplementation.class, builder); + builderRegistry.register(SystemImplementation.class, new SystemComponentBuilder()); + builderRegistry.register(SystemBinding.class, new SystemBindingBuilder()); + return builderRegistry; + } + +}
\ No newline at end of file diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultRuntime.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultRuntime.java new file mode 100644 index 0000000000..78a317df2c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/bootstrap/DefaultRuntime.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.bootstrap; + +import java.util.HashMap; +import java.util.Map; + +import org.w3c.dom.Document; + +import org.apache.tuscany.spi.bootstrap.ComponentNames; +import org.apache.tuscany.spi.bootstrap.RuntimeComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.Deployer; + +import org.apache.tuscany.core.implementation.composite.CompositeComponentImpl; + +/** + * The default implementation of the Tuscany runtime component + * + * @version $Rev$ $Date$ + */ +public class DefaultRuntime extends CompositeComponentImpl implements RuntimeComponent { + private CompositeComponent rootComponent; + private CompositeComponent systemComponent; + + /** + * Initialize a default runtime with an empty set of Property values. + */ + public DefaultRuntime() { + this(new HashMap<String, Document>()); + } + + /** + * Initialize a runtime with the a set of properties + * + * @param runtimeProperties Property values for the runtime itself + */ + public DefaultRuntime(Map<String, Document> runtimeProperties) { + super(ComponentNames.TUSCANY_RUNTIME, null, null, runtimeProperties); + } + + protected void setRootComponent(CompositeComponent rootComponent) { + this.rootComponent = rootComponent; + } + + protected void setSystemComponent(CompositeComponent systemComponent) { + this.systemComponent = systemComponent; + } + + public CompositeComponent getRootComponent() { + return rootComponent; + } + + public CompositeComponent getSystemComponent() { + return systemComponent; + } + + public Deployer getDeployer() { + return systemComponent.resolveExternalInstance(Deployer.class); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/BuilderRegistryImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/BuilderRegistryImpl.java new file mode 100644 index 0000000000..c899af1a13 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/BuilderRegistryImpl.java @@ -0,0 +1,202 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; + +import org.osoa.sca.annotations.Init; +import org.osoa.sca.annotations.Scope; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.builder.BindingBuilder; +import org.apache.tuscany.spi.builder.BindlessBuilder; +import org.apache.tuscany.spi.builder.BuilderConfigException; +import org.apache.tuscany.spi.builder.BuilderRegistry; +import org.apache.tuscany.spi.builder.ComponentBuilder; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.Reference; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.ScopeRegistry; +import org.apache.tuscany.spi.component.Service; +import org.apache.tuscany.spi.component.SystemAtomicComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.model.Binding; +import org.apache.tuscany.spi.model.BindlessServiceDefinition; +import org.apache.tuscany.spi.model.BoundReferenceDefinition; +import org.apache.tuscany.spi.model.BoundServiceDefinition; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.ComponentType; +import org.apache.tuscany.spi.model.Implementation; +import org.apache.tuscany.spi.model.ReferenceDefinition; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.WireService; + +/** + * The default builder registry in the runtime + * + * @version $Rev$ $Date$ + */ +@Scope("MODULE") +public class BuilderRegistryImpl implements BuilderRegistry { + + protected WireService wireService; + protected ScopeRegistry scopeRegistry; + + private final Map<Class<? extends Implementation<?>>, + ComponentBuilder<? extends Implementation<?>>> componentBuilders = + new HashMap<Class<? extends Implementation<?>>, ComponentBuilder<? extends Implementation<?>>>(); + private final Map<Class<? extends Binding>, + BindingBuilder<? extends Binding>> bindingBuilders = + new HashMap<Class<? extends Binding>, BindingBuilder<? extends Binding>>(); + private BindlessBuilder bindlessBuilder; + + public BuilderRegistryImpl() { + } + + public BuilderRegistryImpl(ScopeRegistry scopeRegistry) { + this.scopeRegistry = scopeRegistry; + } + + @Init(eager = true) + public void init() { + } + + @Autowire + public void setScopeRegistry(ScopeRegistry scopeRegistry) { + this.scopeRegistry = scopeRegistry; + } + + @Autowire + public void setWireService(WireService wireService) { + this.wireService = wireService; + } + + public <I extends Implementation<?>> void register(Class<I> implClass, ComponentBuilder<I> builder) { + componentBuilders.put(implClass, builder); + } + + public <I extends Implementation<?>> void unregister(Class<I> implClass) { + componentBuilders.remove(implClass); + } + + @SuppressWarnings("unchecked") + public <I extends Implementation<?>> Component build(CompositeComponent parent, + ComponentDefinition<I> componentDefinition, + DeploymentContext deploymentContext) { + Class<?> implClass = componentDefinition.getImplementation().getClass(); + ComponentBuilder<I> componentBuilder = (ComponentBuilder<I>) componentBuilders.get(implClass); + if (componentBuilder == null) { + BuilderConfigException e = new BuilderConfigException("No builder registered for implementation"); + e.setIdentifier(implClass.getName()); + e.addContextName(componentDefinition.getName()); + throw e; + } + + Component component = componentBuilder.build(parent, componentDefinition, deploymentContext); + ComponentType<?, ?, ?> componentType = componentDefinition.getImplementation().getComponentType(); + assert componentType != null : "Component type must be set"; + // create wires for the component + if (wireService != null && !(component instanceof SystemAtomicComponent)) { + wireService.createWires(component, componentDefinition); + } + return component; + } + + @SuppressWarnings("unchecked") + public <B extends Binding> void register(BindingBuilder<B> builder) { + Type[] interfaces = builder.getClass().getGenericInterfaces(); + for (Type type : interfaces) { + if (!(type instanceof ParameterizedType)) { + continue; + } + ParameterizedType interfaceType = (ParameterizedType) type; + if (!BindingBuilder.class.equals(interfaceType.getRawType())) { + continue; + } + Class<B> implClass = (Class<B>) interfaceType.getActualTypeArguments()[0]; + register(implClass, builder); + return; + } + throw new IllegalArgumentException("builder is not generified"); + } + + public <B extends Binding> void register(Class<B> implClass, BindingBuilder<B> builder) { + bindingBuilders.put(implClass, builder); + } + + public void register(BindlessBuilder builder) { + bindlessBuilder = builder; + } + + @SuppressWarnings("unchecked") + public <B extends Binding> SCAObject build(CompositeComponent parent, + BoundServiceDefinition<B> boundServiceDefinition, + DeploymentContext deploymentContext) { + Class<?> bindingClass = boundServiceDefinition.getBinding().getClass(); + BindingBuilder<B> bindingBuilder = (BindingBuilder<B>) bindingBuilders.get(bindingClass); + SCAObject object = bindingBuilder.build(parent, boundServiceDefinition, deploymentContext); + if (wireService != null) { + // wireService.createWires((Service) object, boundServiceDefinition); + String path = boundServiceDefinition.getTarget().getPath(); + ServiceContract<?> contract = boundServiceDefinition.getServiceContract(); + wireService.createWires((Service)object, path, contract); + } + return object; + } + + @SuppressWarnings("unchecked") + public <B extends Binding> SCAObject build(CompositeComponent parent, + BoundReferenceDefinition<B> boundReferenceDefinition, + DeploymentContext deploymentContext) { + Class<B> bindingClass = (Class<B>) boundReferenceDefinition.getBinding().getClass(); + BindingBuilder<B> bindingBuilder = (BindingBuilder<B>) bindingBuilders.get(bindingClass); + SCAObject object = bindingBuilder.build(parent, boundReferenceDefinition, deploymentContext); + // create wires for the component + if (wireService != null) { + wireService.createWires((Reference) object, boundReferenceDefinition.getServiceContract()); + } + return object; + } + + public SCAObject build(CompositeComponent parent, + BindlessServiceDefinition serviceDefinition, + DeploymentContext deploymentContext) { + SCAObject object = bindlessBuilder.build(parent, serviceDefinition, deploymentContext); + if (wireService != null) { + String path = serviceDefinition.getTarget().getPath(); + ServiceContract<?> contract = serviceDefinition.getServiceContract(); + wireService.createWires((Service)object, path, contract); + } + return object; + } + + public SCAObject build(CompositeComponent parent, + ReferenceDefinition referenceDefinition, + DeploymentContext deploymentContext) { + SCAObject object = bindlessBuilder.build(parent, referenceDefinition, deploymentContext); + if (wireService != null) { + wireService.createWires((Reference) object, referenceDefinition.getServiceContract()); + } + return object; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/ConnectorImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/ConnectorImpl.java new file mode 100644 index 0000000000..5194bc5905 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/ConnectorImpl.java @@ -0,0 +1,484 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import java.util.List; +import java.util.Map; + +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.spi.QualifiedName; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.builder.BuilderConfigException; +import org.apache.tuscany.spi.builder.Connector; +import org.apache.tuscany.spi.builder.WirePostProcessorRegistry; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.ComponentRuntimeException; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.Reference; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.Service; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.services.work.WorkScheduler; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.IncompatibleServiceContractException; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.TargetInvoker; +import org.apache.tuscany.spi.wire.WireService; + +import org.apache.tuscany.core.implementation.composite.CompositeReference; +import org.apache.tuscany.core.implementation.composite.CompositeService; +import org.apache.tuscany.core.wire.NonBlockingBridgingInterceptor; +import org.apache.tuscany.core.wire.OutboundAutowire; +import org.apache.tuscany.core.wire.SynchronousBridgingInterceptor; + +/** + * The default connector implmentation + * + * @version $$Rev$$ $$Date$$ + */ +public class ConnectorImpl implements Connector { + + private WirePostProcessorRegistry postProcessorRegistry; + private WireService wireService; + private WorkContext workContext; + private WorkScheduler scheduler; + + public ConnectorImpl() { + } + + @Constructor({"wireService", "processorRegistry", "scheduler", "workContext"}) + public ConnectorImpl(@Autowire WireService wireService, + @Autowire WirePostProcessorRegistry processorRegistry, + @Autowire WorkScheduler scheduler, + @Autowire WorkContext workContext) { + this.postProcessorRegistry = processorRegistry; + this.wireService = wireService; + this.scheduler = scheduler; + this.workContext = workContext; + } + + public void connect(SCAObject source) { + CompositeComponent parent = source.getParent(); + if (source instanceof AtomicComponent) { + AtomicComponent sourceComponent = (AtomicComponent) source; + // connect outbound wires for component references to their targets + for (List<OutboundWire> referenceWires : sourceComponent.getOutboundWires().values()) { + for (OutboundWire outboundWire : referenceWires) { + if (outboundWire instanceof OutboundAutowire) { + continue; + } + try { + SCAObject target; + if (sourceComponent.isSystem()) { + target = parent.getSystemChild(outboundWire.getTargetName().getPartName()); + } else { + target = parent.getChild(outboundWire.getTargetName().getPartName()); + } + connect(sourceComponent, outboundWire, target); + } catch (BuilderConfigException e) { + e.addContextName(source.getName()); + e.addContextName(parent.getName()); + throw e; + } + } + } + // connect inbound wires + for (InboundWire inboundWire : sourceComponent.getInboundWires().values()) { + for (InboundInvocationChain chain : inboundWire.getInvocationChains().values()) { + Operation<?> operation = chain.getOperation(); + String serviceName = inboundWire.getServiceName(); + TargetInvoker invoker = sourceComponent.createTargetInvoker(serviceName, operation); + chain.setTargetInvoker(invoker); + chain.prepare(); + } + } + } else if (source instanceof Reference) { + Reference reference = (Reference) source; + InboundWire inboundWire = reference.getInboundWire(); + Map<Operation<?>, InboundInvocationChain> inboundChains = inboundWire.getInvocationChains(); + for (InboundInvocationChain chain : inboundChains.values()) { + //TODO handle async + // add target invoker on inbound side + ServiceContract contract = inboundWire.getServiceContract(); + Operation operation = chain.getOperation(); + TargetInvoker invoker = reference.createTargetInvoker(contract, operation); + chain.setTargetInvoker(invoker); + chain.prepare(); + } + OutboundWire outboundWire = reference.getOutboundWire(); + // connect the reference's inbound and outbound wires + connect(inboundWire, outboundWire, true); + + if (reference instanceof CompositeReference) { + // For a composite reference only, since its outbound wire comes + // from its parent composite, + // the corresponding target would not lie in its parent but + // rather in its parent's parent + parent = parent.getParent(); + assert parent != null : "Parent of parent was null"; + SCAObject target = parent.getChild(outboundWire.getTargetName().getPartName()); + connect((Component)parent, outboundWire, target); + } + } else if (source instanceof Service) { + Service service = (Service) source; + InboundWire inboundWire = service.getInboundWire(); + OutboundWire outboundWire = service.getOutboundWire(); + // For a composite reference only, since its outbound wire comes from its parent composite, + // the corresponding target would not lie in its parent but rather in its parent's parent + if (source instanceof CompositeReference) { + parent = parent.getParent(); + assert parent != null : "Parent of parent was null"; + } + SCAObject target; + if (service.isSystem()) { + target = parent.getSystemChild(outboundWire.getTargetName().getPartName()); + } else { + target = parent.getChild(outboundWire.getTargetName().getPartName()); + } + // connect the outbound service wire to the target + connect(service, outboundWire, target); + // NB: this connect must be done after the outbound service chain is connected to its target above + if (!(source instanceof CompositeService)) { + //REVIEW JFM: do we need this to be special for composites? + connect(inboundWire, outboundWire, true); + } + } + } + + public void connect(InboundWire sourceWire, OutboundWire targetWire, boolean optimizable) + throws BuilderConfigException { + Map<Operation<?>, OutboundInvocationChain> targetChains = targetWire.getInvocationChains(); + // perform optimization, if possible + if (optimizable && sourceWire.getInvocationChains().isEmpty() && targetChains.isEmpty()) { + sourceWire.setTargetWire(targetWire); + if (postProcessorRegistry != null) { + // run wire post-processors + postProcessorRegistry.process(sourceWire, targetWire); + } + return; + } + for (InboundInvocationChain inboundChain : sourceWire.getInvocationChains().values()) { + // match wire chains + OutboundInvocationChain outboundChain = targetChains.get(inboundChain.getOperation()); + if (outboundChain == null) { + BuilderConfigException e = new BuilderConfigException("Incompatible source and target interfaces"); + e.setIdentifier(sourceWire.getServiceName()); + throw e; + } + connect(inboundChain, outboundChain); + } + if (postProcessorRegistry != null) { + // run wire post-processors + postProcessorRegistry.process(sourceWire, targetWire); + } + } + + /** + * Connects the source outbound wire to a corresponding target inbound wire + * + * @param sourceWire the source wire to connect + * @param targetWire the target wire to connect to + * @param optimizable true if the wire connection can be optimized + */ + void connect(OutboundWire sourceWire, InboundWire targetWire, boolean optimizable) { + SCAObject source = sourceWire.getContainer(); + SCAObject target = targetWire.getContainer(); + ServiceContract contract = sourceWire.getServiceContract(); + Map<Operation<?>, InboundInvocationChain> targetChains = targetWire.getInvocationChains(); + // perform optimization, if possible + // REVIEW: (kentaminator@gmail.com) shouldn't this check whether the interceptors in the + // source & target chains are marked as optimizable? (and if so, optimize them away?) + if (optimizable && sourceWire.getInvocationChains().isEmpty() && targetChains.isEmpty()) { + sourceWire.setTargetWire(targetWire); + if (postProcessorRegistry != null) { + // run wire post-processors + postProcessorRegistry.process(sourceWire, targetWire); + } + return; + } + // match outbound to inbound chains + for (OutboundInvocationChain outboundChain : sourceWire.getInvocationChains().values()) { + Operation<?> operation = outboundChain.getOperation(); + InboundInvocationChain inboundChain = targetChains.get(operation); + if (inboundChain == null) { + BuilderConfigException e = + new BuilderConfigException("Incompatible source and target interfaces for reference"); + e.setIdentifier(sourceWire.getReferenceName()); + throw e; + } + Operation<?> inboundOperation = inboundChain.getOperation(); + boolean isOneWayOperation = operation.isNonBlocking(); + boolean operationHasCallback = contract.getCallbackName() != null; + if (isOneWayOperation && operationHasCallback) { + throw new ComponentRuntimeException("Operation cannot be marked one-way and have a callback"); + } + TargetInvoker invoker = null; + if (target instanceof Component) { + Component component = (Component) target; + if (isOneWayOperation || operationHasCallback) { + invoker = component.createAsyncTargetInvoker(targetWire, inboundOperation); + } else { + String portName = sourceWire.getTargetName().getPortName(); + invoker = component.createTargetInvoker(portName, inboundOperation); + } + } else if (target instanceof Reference) { + Reference reference = (Reference) target; + if (!(reference instanceof CompositeReference) && operationHasCallback) { + // Notice that for bound references we only use async target invokers for callback operations + invoker = reference.createAsyncTargetInvoker(sourceWire, inboundOperation); + } else { + ServiceContract targetContract = targetWire.getServiceContract(); + invoker = reference.createTargetInvoker(targetContract, inboundOperation); + } + } else if (target instanceof CompositeService) { + CompositeService compServ = (CompositeService) target; + invoker = compServ.createTargetInvoker(targetWire.getServiceContract(), inboundChain.getOperation()); + } + + if (source instanceof Service && !(source instanceof CompositeService)) { + // services are a special case: invoker must go on the inbound chain + if (target instanceof Component && (isOneWayOperation || operationHasCallback)) { + // if the target is a component and the operation is non-blocking + connect(outboundChain, inboundChain, null, true); + } else { + connect(outboundChain, inboundChain, null, false); + } + Service service = (Service) source; + InboundInvocationChain chain = service.getInboundWire().getInvocationChains().get(operation); + chain.setTargetInvoker(invoker); + } else { + if (target instanceof Component && (isOneWayOperation || operationHasCallback)) { + // if the target is a component and the operation is non-blocking + connect(outboundChain, inboundChain, invoker, true); + } else { + connect(outboundChain, inboundChain, invoker, false); + } + } + } + + // create source callback chains and connect them if target callback chains exist + Map<Operation<?>, OutboundInvocationChain> sourceCallbackChains = + targetWire.getSourceCallbackInvocationChains(source.getName()); + for (InboundInvocationChain inboundChain : sourceWire.getTargetCallbackInvocationChains().values()) { + Operation<?> operation = inboundChain.getOperation(); + if (sourceCallbackChains != null && sourceCallbackChains.get(operation) != null) { + String name = operation.getName(); + BuilderConfigException e = + new BuilderConfigException("Source callback chain should not exist for operation [" + name + "]"); + e.setIdentifier(sourceWire.getReferenceName()); + throw e; + } + + Operation targetOp = + (Operation)targetWire.getServiceContract().getCallbackOperations().get(operation.getName()); + OutboundInvocationChain outboundChain = wireService.createOutboundChain(targetOp); + targetWire.addSourceCallbackInvocationChain(source.getName(), targetOp, outboundChain); + if (source instanceof Component) { + Component component = (Component) source; + TargetInvoker invoker = component.createTargetInvoker(null, operation); + connect(outboundChain, inboundChain, invoker, false); + } else if (source instanceof CompositeReference) { + CompositeReference compRef = (CompositeReference) source; + ServiceContract sourceContract = sourceWire.getServiceContract(); + TargetInvoker invoker = compRef.createCallbackTargetInvoker(sourceContract, operation); + connect(outboundChain, inboundChain, invoker, false); + } else if (source instanceof Service) { + Service service = (Service) source; + ServiceContract sourceContract = sourceWire.getServiceContract(); + TargetInvoker invoker = service.createCallbackTargetInvoker(sourceContract, operation); + connect(outboundChain, inboundChain, invoker, false); + } + } + if (postProcessorRegistry != null) { + // run wire post-processors + postProcessorRegistry.process(sourceWire, targetWire); + } + } + + /** + * Connects a source to target chain + * + * @param sourceChain the source chain + * @param targetChain the target chain + * @param invoker the invoker to place on the source chain for dispatching invocations + * @param nonBlocking true if the operation is non-blocking + */ + void connect(OutboundInvocationChain sourceChain, + InboundInvocationChain targetChain, + TargetInvoker invoker, + boolean nonBlocking) { + Interceptor head = targetChain.getHeadInterceptor(); + if (head == null) { + BuilderConfigException e = new BuilderConfigException("No interceptor for operation"); + e.setIdentifier(targetChain.getOperation().getName()); + throw e; + } + if (nonBlocking) { + sourceChain.setTargetInterceptor(new NonBlockingBridgingInterceptor(scheduler, workContext, head)); + } else { + sourceChain.setTargetInterceptor(new SynchronousBridgingInterceptor(head)); + } + sourceChain.prepare(); //FIXME prepare should be moved out + sourceChain.setTargetInvoker(invoker); + } + + + /** + * Connects an inbound source chain to an outbound target chain + * + * @param sourceChain + * @param targetChain + */ + void connect(InboundInvocationChain sourceChain, OutboundInvocationChain targetChain) { + // invocations from inbound to outbound chains are always syncrhonius as they occur in services and references + sourceChain.addInterceptor(new SynchronousBridgingInterceptor(targetChain.getHeadInterceptor())); + } + + /** + * Connects an component's outbound wire to its target in a composite. Valid targets are either + * <code>AtomicComponent</code>s contained in the composite, or <code>References</code> of the composite. + * + * @param sourceWire + * @throws BuilderConfigException + */ + private void connect(SCAObject source, OutboundWire sourceWire, SCAObject target) throws BuilderConfigException { + assert sourceWire.getTargetName() != null : "Wire target name was null"; + QualifiedName targetName = sourceWire.getTargetName(); + + if (target instanceof AtomicComponent) { + AtomicComponent targetComponent = (AtomicComponent) target; + InboundWire targetWire = targetComponent.getInboundWire(targetName.getPortName()); + if (targetWire == null) { + String refName = sourceWire.getReferenceName(); + BuilderConfigException e = new BuilderConfigException("No target service for reference " + refName); + e.setIdentifier(targetName.getPortName()); + throw e; + } + checkIfWireable(sourceWire, targetWire); + boolean optimizable = isOptimizable(source.getScope(), target.getScope()); + connect(sourceWire, targetWire, optimizable); + } else if (target instanceof Reference) { + InboundWire targetWire = ((Reference) target).getInboundWire(); + assert targetWire != null; + checkIfWireable(sourceWire, targetWire); + boolean optimizable = isOptimizable(source.getScope(), target.getScope()); + connect(sourceWire, targetWire, optimizable); + } else if (target instanceof CompositeComponent) { + CompositeComponent composite = (CompositeComponent) target; + InboundWire targetWire = null; + if (source.isSystem()) { + for (Object child : composite.getSystemChildren()) { + if (child instanceof CompositeService) { + CompositeService compServ = (CompositeService) child; + targetWire = compServ.getInboundWire(); + assert targetWire != null; + Class<?> sourceInterface = sourceWire.getServiceContract().getInterfaceClass(); + Class<?> targetInterface = targetWire.getServiceContract().getInterfaceClass(); + if (sourceInterface.isAssignableFrom(targetInterface)) { + target = compServ; + break; + } else { + targetWire = null; + } + } + } + } else { + for (Object child : composite.getChildren()) { + if (child instanceof CompositeService) { + CompositeService compServ = (CompositeService) child; + targetWire = compServ.getInboundWire(); + assert targetWire != null; + Class<?> sourceInterface = sourceWire.getServiceContract().getInterfaceClass(); + Class<?> targetInterface = targetWire.getServiceContract().getInterfaceClass(); + if (sourceInterface.isAssignableFrom(targetInterface)) { + target = compServ; + break; + } else { + targetWire = null; + } + } + } + } + if (targetWire == null) { + throw new BuilderConfigException("No target composite service in composite"); + } + boolean optimizable = isOptimizable(source.getScope(), target.getScope()); + connect(sourceWire, targetWire, optimizable); + } else { + String name = sourceWire.getReferenceName(); + BuilderConfigException e = new BuilderConfigException("Invalid target type for reference " + name); + e.setIdentifier(targetName.getQualifiedName()); + throw e; + } + } + + private void checkIfWireable(OutboundWire sourceWire, InboundWire targetWire) { + if (wireService == null) { + Class<?> sourceInterface = sourceWire.getServiceContract().getInterfaceClass(); + Class<?> targetInterface = targetWire.getServiceContract().getInterfaceClass(); + if (!sourceInterface.isAssignableFrom(targetInterface)) { + throw new BuilderConfigException("Incompatible source and target interfaces"); + } + } else { + try { + wireService.checkCompatibility(sourceWire.getServiceContract(), targetWire + .getServiceContract(), false); + } catch (IncompatibleServiceContractException e) { + throw new BuilderConfigException("Incompatible source and target interfaces", e); + } + } + } + + private boolean isOptimizable(Scope pReferrer, Scope pReferee) { + if (pReferrer == Scope.UNDEFINED || pReferee == Scope.UNDEFINED) { + return false; + } + if (pReferee == pReferrer) { + return true; + } else if (pReferrer == Scope.STATELESS) { + return true; + } else if (pReferee == Scope.STATELESS) { + return true; + } else if (pReferrer == Scope.REQUEST && pReferee == Scope.SESSION) { + return true; + } else if (pReferrer == Scope.REQUEST && pReferee == Scope.MODULE) { + return true; + } else if (pReferrer == Scope.REQUEST && pReferee == Scope.COMPOSITE) { + return true; + } else if (pReferrer == Scope.SESSION && pReferee == Scope.MODULE) { + return true; + } else if (pReferrer == Scope.SESSION && pReferee == Scope.COMPOSITE) { + return true; + } else if (pReferrer == Scope.COMPOSITE && pReferee == Scope.MODULE) { + // case where a service context points to a module scoped component + return true; + } else { + return pReferrer == Scope.MODULE && pReferee == Scope.COMPOSITE; + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/WirePostProcessorRegistryImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/WirePostProcessorRegistryImpl.java new file mode 100644 index 0000000000..c1aeb62079 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/builder/WirePostProcessorRegistryImpl.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.spi.builder.WirePostProcessor; +import org.apache.tuscany.spi.builder.WirePostProcessorRegistry; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundWire; + +/** + * The default implementation of a <code>WirePostProcessor</code> + * + * @version $Rev$ $Date$ + */ +public class WirePostProcessorRegistryImpl implements WirePostProcessorRegistry { + + private final List<WirePostProcessor> processors = new ArrayList<WirePostProcessor>(); + + public void process(OutboundWire source, InboundWire target) { + for (WirePostProcessor processor : processors) { + processor.process(source, target); + } + } + + public void process(InboundWire source, OutboundWire target) { + for (WirePostProcessor processor : processors) { + processor.process(source, target); + } + } + + public void register(WirePostProcessor processor) { + processors.add(processor); + } + + public void unregister(WirePostProcessor processor) { + processors.remove(processor); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/ComponentInitException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/ComponentInitException.java new file mode 100644 index 0000000000..e1ad3a6fea --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/ComponentInitException.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.core.component; + +import org.apache.tuscany.spi.component.ComponentRuntimeException; + +/** + * Denotes an error initializing a component + * + * @version $$Rev$$ $$Date$$ + */ +public class ComponentInitException extends ComponentRuntimeException { + public ComponentInitException() { + } + + public ComponentInitException(String message) { + super(message); + } + + public ComponentInitException(String message, Throwable cause) { + super(message, cause); + } + + public ComponentInitException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/ScopeIdentifier.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/ScopeIdentifier.java new file mode 100644 index 0000000000..35125b85ef --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/ScopeIdentifier.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component; + +/** + * Implementations enable lazy retrieval of a scope id associated with a request, i.e. an id (and presumably a context) + * do not have to be generated if the scope is never accessed. Identifiers are associated with the current request + * thread and keyed on scope type. + * + * @version $Rev$ $Date$ + * @see org.apache.tuscany.spi.component.WorkContext + */ +public interface ScopeIdentifier { + + /** + * Returns the scope id for the request. + */ + Object getIdentifier(); +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/WorkContextImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/WorkContextImpl.java new file mode 100644 index 0000000000..0b0a48cb99 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/WorkContextImpl.java @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.WorkContext; + +/** + * An implementation of an {@link org.apache.tuscany.spi.component.WorkContext} that handles event-to-thread + * associations using an <code>InheritableThreadLocal</code> + * + * @version $Rev$ $Date$ + */ +public class WorkContextImpl implements WorkContext { + + private static final Object REMOTE_CONTEXT = new Object(); + private static final Object MESSAGE_ID = new Object(); + private static final Object CORRELATION_ID = new Object(); + + // TODO implement propagation strategy for creating new threads + + //A map ( associated with the current thread) of scope identifiers keyed on the event context id type. + //The scope identifier may be a {@link ScopeIdentifier} or an opaque id + + // [rfeng] We cannot use InheritableThreadLocal for message ids here since it's shared by parent and children + private ThreadLocal<Map<Object, Object>> workContext = new ThreadLocal<Map<Object, Object>>(); + + // [rfeng] Session id requires InheritableThreadLocal + private ThreadLocal<Map<Object, Object>> inheritableContext = new InheritableThreadLocal<Map<Object, Object>>(); + + public WorkContextImpl() { + super(); + } + + public Object getCurrentMessageId() { + Map<Object, Object> map = workContext.get(); + if (map == null) { + return null; + } + return map.get(MESSAGE_ID); + } + + public void setCurrentMessageId(Object messageId) { + Map<Object, Object> map = workContext.get(); + if (map == null) { + map = new HashMap<Object, Object>(); + workContext.set(map); + } + map.put(MESSAGE_ID, messageId); + } + + public Object getCurrentCorrelationId() { + Map<Object, Object> map = workContext.get(); + if (map == null) { + return null; + } + return map.get(CORRELATION_ID); + } + + public void setCurrentCorrelationId(Object correlationId) { + Map<Object, Object> map = workContext.get(); + if (map == null) { + map = new HashMap<Object, Object>(); + workContext.set(map); + } + map.put(CORRELATION_ID, correlationId); + } + + public CompositeComponent getRemoteComponent() { + Map<Object, Object> map = workContext.get(); + if (map == null) { + return null; + } + return (CompositeComponent) map.get(REMOTE_CONTEXT); + } + + + public void setRemoteComponent(CompositeComponent component) { + Map<Object, Object> map = workContext.get(); + if (map == null) { + map = new HashMap<Object, Object>(); + workContext.set(map); + } + map.put(REMOTE_CONTEXT, component); + } + + public Object getIdentifier(Object type) { + Map<Object, Object> map = inheritableContext.get(); + if (map == null) { + return null; + } + Object currentId = map.get(type); + if (currentId instanceof ScopeIdentifier) { + currentId = ((ScopeIdentifier) currentId).getIdentifier(); + // once we have accessed the id, replace the lazy wrapper + map.put(type, currentId); + } + return currentId; + } + + public void setIdentifier(Object type, Object identifier) { + Map<Object, Object> map = inheritableContext.get(); + if (map == null) { + map = new HashMap<Object, Object>(); + inheritableContext.set(map); + } + map.put(type, identifier); + } + + public void clearIdentifier(Object type) { + if (type == null) { + return; + } + Map map = inheritableContext.get(); + if (map != null) { + map.remove(type); + } + } + + public void clearIdentifiers() { + inheritableContext.remove(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/AbstractEvent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/AbstractEvent.java new file mode 100644 index 0000000000..6df5b67dea --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/AbstractEvent.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.core.component.event; + +import org.apache.tuscany.spi.event.Event; + +/** + * A basic implementation of a runtime event + * + * @version $$Rev$$ $$Date$$ + */ +public abstract class AbstractEvent implements Event { + + protected transient Object source; + + public AbstractEvent(Object source) { + assert source != null : "Source id was null"; + this.source = source; + } + + public Object getSource() { + return source; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/AbstractRequestEvent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/AbstractRequestEvent.java new file mode 100644 index 0000000000..762b917600 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/AbstractRequestEvent.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +/** + * Base implementation of a request event + * + * @version $$Rev$$ $$Date$$ + */ +public abstract class AbstractRequestEvent extends AbstractEvent implements RequestEvent { + + /** + * Creates a new event + * + * @param source the source of the event + */ + public AbstractRequestEvent(Object source) { + super(source); + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeEvent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeEvent.java new file mode 100644 index 0000000000..ce058404da --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeEvent.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.core.component.event; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.event.Event; + +/** + * Implemented by runtime events associated with a composite, e.g. lifecycle events + * + * @version $$Rev$$ $$Date$$ + */ +public interface CompositeEvent extends Event { + + CompositeComponent getComposite(); + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStart.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStart.java new file mode 100644 index 0000000000..9920a2febf --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStart.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.core.component.event; + +import org.apache.tuscany.spi.component.CompositeComponent; + +/** + * Propagated when a composite starts + * + * @version $$Rev$$ $$Date$$ + */ +public class CompositeStart extends AbstractEvent implements CompositeEvent { + + private CompositeComponent component; + + /** + * Creates a module stop event + * + * @param source the source of the event + * @param component the composite component associated the module being stopped + */ + public CompositeStart(Object source, CompositeComponent component) { + super(source); + this.component = component; + } + + public CompositeComponent getComposite() { + return component; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStop.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStop.java new file mode 100644 index 0000000000..58be209783 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/CompositeStop.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.core.component.event; + +import org.apache.tuscany.spi.component.CompositeComponent; + +/** + * Propagated when a composite stops + * + * @version $$Rev$$ $$Date$$ + */ +public class CompositeStop extends AbstractEvent implements CompositeEvent { + + private CompositeComponent component; + + /** + * Creates a module stop event + * + * @param source the source of the event + * @param component the composite component associated the module being stopped + */ + public CompositeStop(Object source, CompositeComponent component) { + super(source); + this.component = component; + } + + public CompositeComponent getComposite() { + return component; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestEnded.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestEnded.java new file mode 100644 index 0000000000..01bd769031 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestEnded.java @@ -0,0 +1,38 @@ +/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.component.event;
+
+/**
+ * Propagated when an HTTP-based request has ended.
+ *
+ * @version $$Rev: 430937 $$ $$Date: 2006-08-11 21:17:56 -0400 (Fri, 11 Aug 2006) $$
+ */
+public class HttpRequestEnded extends HttpSessionEvent {
+
+ /**
+ * Creates a new event
+ *
+ * @param source the source of the event
+ * @param id the id of the HTTP session being ended
+ */
+ public HttpRequestEnded(Object source, Object id) {
+ super(source, id);
+ }
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestStart.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestStart.java new file mode 100644 index 0000000000..9d0ff80dd7 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpRequestStart.java @@ -0,0 +1,38 @@ +/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.core.component.event;
+
+/**
+ * Propagated when an HTTP-based request has started
+ *
+ * @version $$Rev: 430937 $$ $$Date: 2006-08-11 21:17:56 -0400 (Fri, 11 Aug 2006) $$
+ */
+public class HttpRequestStart extends HttpSessionEvent {
+
+ /**
+ * Creates a new event
+ *
+ * @param source the source of the event
+ * @param id the id of the HTTP session being ended
+ */
+ public HttpRequestStart(Object source, Object id) {
+ super(source, id);
+ }
+
+}
diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEnd.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEnd.java new file mode 100644 index 0000000000..7f2bebe94a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEnd.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +/** + * Propagated when an HTTP-based session is expired + * + * @version $$Rev$$ $$Date$$ + */ +public class HttpSessionEnd extends HttpSessionEvent { + + /** + * Creates a new event + * + * @param source the source of the event + * @param id the id of the HTTP session being ended + */ + public HttpSessionEnd(Object source, Object id) { + super(source, id); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEvent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEvent.java new file mode 100644 index 0000000000..ed245d0930 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionEvent.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.core.component.event; + +/** + * A base implementation of HTTP-based session events in the runtime + * + * @version $$Rev$$ $$Date$$ + */ +public abstract class HttpSessionEvent extends AbstractEvent { + + private Object id; + + public HttpSessionEvent(Object source, Object id) { + super(source); + assert id != null : "Session id was null"; + this.id = id; + } + + + public Object getSource() { + return source; + } + + public Object getId() { + return id; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionStart.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionStart.java new file mode 100644 index 0000000000..7f9c0fadea --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/HttpSessionStart.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +/** + * Propagated when an HTTP-based session has started + * + * @version $$Rev$$ $$Date$$ + */ +public class HttpSessionStart extends HttpSessionEvent { + + /** + * Creates a new event + * + * @param source the source of the event + * @param id the id of the HTTP session being ended + */ + public HttpSessionStart(Object source, Object id) { + super(source, id); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestEnd.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestEnd.java new file mode 100644 index 0000000000..25856e86f8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestEnd.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +/** + * Propagated when a request completes or is ended + * + * @version $$Rev$$ $$Date$$ + */ +public class RequestEnd extends AbstractRequestEvent { + + /** + * Creates a new event + * + * @param source the source of the event + */ + public RequestEnd(Object source) { + super(source); + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestEvent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestEvent.java new file mode 100644 index 0000000000..9a6d767236 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestEvent.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +/** + * Implemented by runtime events associated request + * + * @version $$Rev$$ $$Date$$ + */ +public interface RequestEvent { + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestStart.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestStart.java new file mode 100644 index 0000000000..466f52551a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/event/RequestStart.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.event; + +/** + * Propagated when a request is started in the runtime + * + * @version $$Rev$$ $$Date$$ + */ +public class RequestStart extends AbstractRequestEvent { + + /** + * Creates a new event + * + * @param source the source of the event + */ + public RequestStart(Object source) { + super(source); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/AbstractScopeContainer.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/AbstractScopeContainer.java new file mode 100644 index 0000000000..50b0f927d8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/AbstractScopeContainer.java @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.apache.tuscany.spi.AbstractLifecycle; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.event.Event; +import org.apache.tuscany.spi.event.EventFilter; +import org.apache.tuscany.spi.event.RuntimeEventListener; +import org.apache.tuscany.spi.event.TrueFilter; + +/** + * Implements functionality common to scope contexts. + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractScopeContainer extends AbstractLifecycle implements ScopeContainer { + private static final EventFilter TRUE_FILTER = new TrueFilter(); + + // The event context the scope container is associated with + protected WorkContext workContext; + private final String name; + private Map<EventFilter, List<RuntimeEventListener>> listeners; + + public AbstractScopeContainer(String name, WorkContext workContext) { + this.name = name; + this.workContext = workContext; + } + + public String getName() { + return name; + } + + public void setWorkContext(WorkContext workContext) { + this.workContext = workContext; + } + + public void addListener(RuntimeEventListener listener) { + addListener(TRUE_FILTER, listener); + } + + public void removeListener(RuntimeEventListener listener) { + assert listener != null : "Listener cannot be null"; + synchronized (getListeners()) { + for (List<RuntimeEventListener> currentList : getListeners().values()) { + for (RuntimeEventListener current : currentList) { + if (current == listener) { + currentList.remove(current); + return; + } + } + } + } + } + + public void addListener(EventFilter filter, RuntimeEventListener listener) { + assert listener != null : "Listener cannot be null"; + synchronized (getListeners()) { + List<RuntimeEventListener> list = getListeners().get(filter); + if (list == null) { + list = new CopyOnWriteArrayList<RuntimeEventListener>(); + listeners.put(filter, list); + } + list.add(listener); + } + } + + public void publish(Event event) { + assert event != null : "Event object was null"; + for (Map.Entry<EventFilter, List<RuntimeEventListener>> entry : getListeners().entrySet()) { + if (entry.getKey().match(event)) { + for (RuntimeEventListener listener : entry.getValue()) { + listener.onEvent(event); + } + } + } + } + + public Object getInstance(AtomicComponent component) throws TargetException { + InstanceWrapper ctx = getInstanceWrapper(component); + if (ctx != null) { + if (ctx.getLifecycleState() == UNINITIALIZED) { + ctx.start(); + } + return ctx.getInstance(); + } + return null; + } + + protected Map<EventFilter, List<RuntimeEventListener>> getListeners() { + if (listeners == null) { + listeners = new ConcurrentHashMap<EventFilter, List<RuntimeEventListener>>(); + } + return listeners; + } + + protected void checkInit() { + if (getLifecycleState() != RUNNING) { + throw new IllegalStateException("Scope not running [" + getLifecycleState() + "]"); + } + } + + protected WorkContext getWorkContext() { + return workContext; + } + + public String toString() { + return "ScopeContainer [" + name + "] in state [" + super.toString() + ']'; + } + + protected abstract InstanceWrapper getInstanceWrapper(AtomicComponent component); +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeContainer.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeContainer.java new file mode 100644 index 0000000000..ae197c3504 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeContainer.java @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.event.Event; +import org.apache.tuscany.spi.model.Scope; + +import org.apache.tuscany.core.component.event.HttpSessionEnd; +import org.apache.tuscany.core.component.event.HttpSessionStart; + +/** + * A scope context which manages atomic component instances keyed on HTTP session + * + * @version $Rev$ $Date$ + */ +public class HttpSessionScopeContainer extends AbstractScopeContainer { + + public static final Object HTTP_IDENTIFIER = new Object(); + + private final Map<AtomicComponent, Map<Object, InstanceWrapper>> contexts; + private final Map<Object, List<InstanceWrapper>> destroyQueues; + + public HttpSessionScopeContainer() { + this(null); + } + + public HttpSessionScopeContainer(WorkContext workContext) { + super("Session Scope", workContext); + contexts = new ConcurrentHashMap<AtomicComponent, Map<Object, InstanceWrapper>>(); + destroyQueues = new ConcurrentHashMap<Object, List<InstanceWrapper>>(); + } + + public Scope getScope() { + return Scope.SESSION; + } + + public void onEvent(Event event) { + checkInit(); + if (event instanceof HttpSessionStart) { + Object key = ((HttpSessionStart) event).getId(); + workContext.setIdentifier(HTTP_IDENTIFIER, key); + for (Map.Entry<AtomicComponent, Map<Object, InstanceWrapper>> entry : contexts.entrySet()) { + if (entry.getKey().isEagerInit()) { + + getInstance(entry.getKey(), key); + } + } + } else if (event instanceof HttpSessionEnd) { + Object key = ((HttpSessionEnd) event).getId(); + shutdownInstances(key); + workContext.clearIdentifier(key); + } + } + + public synchronized void start() { + if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) { + throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]"); + } + lifecycleState = RUNNING; + } + + public synchronized void stop() { + contexts.clear(); + synchronized (destroyQueues) { + destroyQueues.clear(); + } + lifecycleState = STOPPED; + } + + public void register(AtomicComponent component) { + contexts.put(component, new ConcurrentHashMap<Object, InstanceWrapper>()); + component.addListener(this); + + } + + protected InstanceWrapper getInstanceWrapper(AtomicComponent component) throws TargetException { + Object key = workContext.getIdentifier(HTTP_IDENTIFIER); + assert key != null : "HTTP session key not bound in work component"; + return getInstance(component, key); + } + + private InstanceWrapper getInstance(AtomicComponent component, Object key) { + Map<Object, InstanceWrapper> wrappers = contexts.get(component); + InstanceWrapper ctx = wrappers.get(key); + if (ctx == null) { + ctx = new InstanceWrapperImpl(component, component.createInstance()); + ctx.start(); + wrappers.put(key, ctx); + List<InstanceWrapper> destroyQueue = destroyQueues.get(key); + if (destroyQueue == null) { + destroyQueue = new ArrayList<InstanceWrapper>(); + destroyQueues.put(key, destroyQueue); + } + synchronized (destroyQueue) { + destroyQueue.add(ctx); + } + } + return ctx; + + } + + private void shutdownInstances(Object key) { + List<InstanceWrapper> destroyQueue = destroyQueues.remove(key); + if (destroyQueue != null) { + for (Map<Object, InstanceWrapper> map : contexts.values()) { + map.remove(key); + } + ListIterator<InstanceWrapper> iter = destroyQueue.listIterator(destroyQueue.size()); + synchronized (destroyQueue) { + while (iter.hasPrevious()) { + try { + iter.previous().stop(); + } catch (TargetException e) { + // TODO send a monitoring event + } + } + } + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeObjectFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeObjectFactory.java new file mode 100644 index 0000000000..6901c429f1 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/HttpSessionScopeObjectFactory.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.core.component.scope; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.ScopeRegistry; +import org.apache.tuscany.spi.model.Scope; +import org.osoa.sca.annotations.Init; + +/** + * Creates a new HTTP session scope context + * + * @version $$Rev$$ $$Date$$ + */ +public class HttpSessionScopeObjectFactory implements ObjectFactory<HttpSessionScopeContainer> { + + public HttpSessionScopeObjectFactory(@Autowire ScopeRegistry registry) { + registry.registerFactory(Scope.SESSION, this); + } + + @Init(eager = true) + public void init() { + } + + + public HttpSessionScopeContainer getInstance() throws ObjectCreationException { + return new HttpSessionScopeContainer(); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapper.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapper.java new file mode 100644 index 0000000000..88fbcd2c7c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapper.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.core.component.scope; + +import org.apache.tuscany.spi.Lifecycle; + +/** + * Provides lifecycle management for an implementation instance associated with an {@link + * org.apache.tuscany.spi.component.AtomicComponent} for use by the atomic context's associated {@link + * org.apache.tuscany.spi.component.ScopeContainer} + * + * @version $Rev$ $Date$ + */ +public interface InstanceWrapper extends Lifecycle { + + Object getInstance(); + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapperImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapperImpl.java new file mode 100644 index 0000000000..f8c1b6490f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/InstanceWrapperImpl.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.apache.tuscany.spi.AbstractLifecycle; +import org.apache.tuscany.spi.CoreRuntimeException; +import org.apache.tuscany.spi.component.AtomicComponent; + +/** + * Default implementation of an <code>InstanceWrapper</code> + * + * @version $$Rev$$ $$Date$$ + */ +public class InstanceWrapperImpl extends AbstractLifecycle implements InstanceWrapper { + + private Object instance; + private AtomicComponent component; + + public InstanceWrapperImpl(AtomicComponent component, Object instance) { + assert component != null; + assert instance != null; + this.component = component; + this.instance = instance; + } + + public Object getInstance() { + checkInit(); + return instance; + } + + public void start() throws CoreRuntimeException { + try { + component.init(instance); + lifecycleState = RUNNING; + } catch (RuntimeException e) { + lifecycleState = ERROR; + throw e; + } + } + + public void stop() throws CoreRuntimeException { + checkInit(); + component.destroy(instance); + } + + protected void checkInit() { + if (getLifecycleState() != RUNNING) { + throw new IllegalStateException("Scope not running [" + getLifecycleState() + "]"); + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ModuleScopeContainer.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ModuleScopeContainer.java new file mode 100644 index 0000000000..6458b9f12a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ModuleScopeContainer.java @@ -0,0 +1,163 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.spi.AbstractLifecycle; +import org.apache.tuscany.spi.CoreRuntimeException; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.event.Event; +import org.apache.tuscany.spi.model.Scope; + +import org.apache.tuscany.core.component.event.CompositeStart; +import org.apache.tuscany.core.component.event.CompositeStop; + +/** + * A scope context which manages atomic component instances keyed by module + * + * @version $Rev$ $Date$ + */ +public class ModuleScopeContainer extends AbstractScopeContainer { + + private static final InstanceWrapper EMPTY = new EmptyWrapper(); + private static final ComponentInitComparator COMPARATOR = new ComponentInitComparator(); + + private final Map<AtomicComponent, InstanceWrapper> instanceWrappers; + + // the queue of instanceWrappers to destroy, in the order that their instances were created + private final List<InstanceWrapper> destroyQueue; + + public ModuleScopeContainer() { + this(null); + } + + public ModuleScopeContainer(WorkContext workContext) { + super("Module Scope", workContext); + instanceWrappers = new ConcurrentHashMap<AtomicComponent, InstanceWrapper>(); + destroyQueue = new ArrayList<InstanceWrapper>(); + } + + public Scope getScope() { + return Scope.MODULE; + } + + public void onEvent(Event event) { + checkInit(); + if (event instanceof CompositeStart) { + eagerInitComponents(); + lifecycleState = RUNNING; + } else if (event instanceof CompositeStop) { + shutdownContexts(); + } + } + + public synchronized void start() { + if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) { + throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]"); + } + lifecycleState = RUNNING; + } + + public synchronized void stop() { + checkInit(); + instanceWrappers.clear(); + synchronized (destroyQueue) { + destroyQueue.clear(); + } + lifecycleState = STOPPED; + } + + /** + * Notifies instanceWrappers of a shutdown in reverse order to which they were started + */ + private void shutdownContexts() { + if (destroyQueue.size() == 0) { + return; + } + synchronized (destroyQueue) { + // shutdown destroyable instances in reverse instantiation order + ListIterator<InstanceWrapper> iter = destroyQueue.listIterator(destroyQueue.size()); + while (iter.hasPrevious()) { + iter.previous().stop(); + } + destroyQueue.clear(); + } + } + + public void register(AtomicComponent component) { + checkInit(); + instanceWrappers.put(component, EMPTY); + } + + protected InstanceWrapper getInstanceWrapper(AtomicComponent component) throws TargetException { + checkInit(); + InstanceWrapper ctx = instanceWrappers.get(component); + assert ctx != null : "Component not registered with scope: " + component; + if (ctx == EMPTY) { + ctx = new InstanceWrapperImpl(component, component.createInstance()); + ctx.start(); + instanceWrappers.put(component, ctx); + synchronized (destroyQueue) { + destroyQueue.add(ctx); + } + } + return ctx; + } + + private void eagerInitComponents() throws CoreRuntimeException { + List<AtomicComponent> componentList = new ArrayList<AtomicComponent>(instanceWrappers.keySet()); + Collections.sort(componentList, COMPARATOR); + // start each group + for (AtomicComponent component : componentList) { + if (component.getInitLevel() <= 0) { + // Don't eagerly init + continue; + } + // the instance could have been created from a depth-first traversal + InstanceWrapper ctx = instanceWrappers.get(component); + if (ctx == EMPTY) { + ctx = new InstanceWrapperImpl(component, component.createInstance()); + ctx.start(); + instanceWrappers.put(component, ctx); + destroyQueue.add(ctx); + } + } + } + + private static class ComponentInitComparator implements Comparator<AtomicComponent> { + public int compare(AtomicComponent o1, AtomicComponent o2) { + return o1.getInitLevel() - o2.getInitLevel(); + } + } + + private static class EmptyWrapper extends AbstractLifecycle implements InstanceWrapper { + public Object getInstance() { + return null; + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ModuleScopeObjectFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ModuleScopeObjectFactory.java new file mode 100644 index 0000000000..c73edbfda6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ModuleScopeObjectFactory.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.core.component.scope; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.component.ScopeRegistry; +import org.apache.tuscany.spi.annotation.Autowire; +import org.osoa.sca.annotations.Init; + +/** + * Creates a new module scope context + * + * @version $$Rev$$ $$Date$$ + */ +public class ModuleScopeObjectFactory implements ObjectFactory<ModuleScopeContainer> { + + public ModuleScopeObjectFactory(@Autowire ScopeRegistry registry) { + registry.registerFactory(Scope.MODULE, this); + } + + @Init(eager = true) + public void init() { + } + + public ModuleScopeContainer getInstance() throws ObjectCreationException { + return new ModuleScopeContainer(); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeContainer.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeContainer.java new file mode 100644 index 0000000000..23ab4b4100 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeContainer.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.event.Event; +import org.apache.tuscany.spi.model.Scope; + +import org.apache.tuscany.core.component.event.RequestEnd; +import org.apache.tuscany.core.component.event.RequestStart; + +/** + * A scope context which manages atomic component instances keyed on the current request context + * + * @version $Rev$ $Date$ + */ +public class RequestScopeContainer extends AbstractScopeContainer { + + private final Map<AtomicComponent, Map<Thread, InstanceWrapper>> contexts; + private final Map<Thread, List<InstanceWrapper>> destroyQueues; + + public RequestScopeContainer() { + this(null); + } + + public RequestScopeContainer(WorkContext workContext) { + super("Request Scope", workContext); + contexts = new ConcurrentHashMap<AtomicComponent, Map<Thread, InstanceWrapper>>(); + destroyQueues = new ConcurrentHashMap<Thread, List<InstanceWrapper>>(); + } + + public Scope getScope() { + return Scope.REQUEST; + } + + public void onEvent(Event event) { + checkInit(); + if (event instanceof RequestStart) { + for (Map.Entry<AtomicComponent, Map<Thread, InstanceWrapper>> entry : contexts.entrySet()) { + if (entry.getKey().isEagerInit()) { + getInstance(entry.getKey()); + } + } + } else if (event instanceof RequestEnd) { + shutdownInstances(Thread.currentThread()); + } + } + + public synchronized void start() { + if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) { + throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]"); + } + lifecycleState = RUNNING; + } + + public synchronized void stop() { + contexts.clear(); + synchronized (destroyQueues) { + destroyQueues.clear(); + } + lifecycleState = STOPPED; + } + + public void register(AtomicComponent component) { + contexts.put(component, new ConcurrentHashMap<Thread, InstanceWrapper>()); + } + + protected InstanceWrapper getInstanceWrapper(AtomicComponent component) throws TargetException { + Map<Thread, InstanceWrapper> instanceContextMap = contexts.get(component); + assert instanceContextMap != null : "Atomic component not registered"; + InstanceWrapper ctx = instanceContextMap.get(Thread.currentThread()); + if (ctx == null) { + ctx = new InstanceWrapperImpl(component, component.createInstance()); + ctx.start(); + instanceContextMap.put(Thread.currentThread(), ctx); + List<InstanceWrapper> destroyQueue = destroyQueues.get(Thread.currentThread()); + if (destroyQueue == null) { + destroyQueue = new ArrayList<InstanceWrapper>(); + destroyQueues.put(Thread.currentThread(), destroyQueue); + } + synchronized (destroyQueue) { + destroyQueue.add(ctx); + } + } + return ctx; + } + + private void shutdownInstances(Thread key) { + List<InstanceWrapper> destroyQueue = destroyQueues.remove(key); + if (destroyQueue != null && destroyQueue.size() > 0) { + Thread thread = Thread.currentThread(); + for (Map<Thread, InstanceWrapper> map : contexts.values()) { + map.remove(thread); + } + ListIterator<InstanceWrapper> iter = destroyQueue.listIterator(destroyQueue.size()); + synchronized (destroyQueue) { + while (iter.hasPrevious()) { + try { + iter.previous().stop(); + } catch (TargetException e) { + // TODO send a monitoring event + } + } + } + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeObjectFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeObjectFactory.java new file mode 100644 index 0000000000..727e76e340 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/RequestScopeObjectFactory.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.core.component.scope; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; + +/** + * Creates a new request scope context + * + * @version $$Rev$$ $$Date$$ + */ +public class RequestScopeObjectFactory implements ObjectFactory<RequestScopeContainer> { + + public RequestScopeContainer getInstance() throws ObjectCreationException { + return new RequestScopeContainer(); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ScopeRegistryImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ScopeRegistryImpl.java new file mode 100644 index 0000000000..91faf3e777 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/ScopeRegistryImpl.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.component.ScopeNotFoundException; +import org.apache.tuscany.spi.component.ScopeRegistry; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.model.Scope; + +/** + * The default implementation of a scope registry + * + * @version $Rev$ $Date$ + */ +public class ScopeRegistryImpl implements ScopeRegistry { + + private final Map<Scope, ScopeContainer> scopeCache = + new ConcurrentHashMap<Scope, ScopeContainer>(); + private final Map<Scope, ObjectFactory<? extends ScopeContainer>> factoryCache = + new ConcurrentHashMap<Scope, ObjectFactory<? extends ScopeContainer>>(); + private WorkContext workContext; + + public ScopeRegistryImpl(WorkContext workContext) { + assert workContext != null; + this.workContext = workContext; + } + + // TODO remove and replace with CDI + public ScopeRegistryImpl() { + } + + @Autowire + public void setWorkContext(WorkContext workContext) { + this.workContext = workContext; + } + + public ScopeContainer getScopeContainer(Scope scope) { + assert Scope.MODULE != scope : "Cannot get MODULE scope from the registry"; + ScopeContainer container = scopeCache.get(scope); + if (container == null) { + ObjectFactory<? extends ScopeContainer> factory = factoryCache.get(scope); + if (factory == null) { + ScopeNotFoundException e = new ScopeNotFoundException("Scope object factory not registered for scope"); + e.setIdentifier(scope.getScope()); + + throw e; + } + container = factory.getInstance(); + container.setWorkContext(workContext); + container.start(); + scopeCache.put(scope, container); + } + return container; + } + + public <T extends ScopeContainer> void registerFactory(Scope scope, ObjectFactory<T> factory) { + factoryCache.put(scope, factory); + } + + public void deregisterFactory(Scope scope) { + factoryCache.remove(scope); + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeContainer.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeContainer.java new file mode 100644 index 0000000000..edc3b69241 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeContainer.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.event.Event; +import org.apache.tuscany.spi.model.Scope; + +/** + * A scope context which manages stateless atomic component instances in a non-pooled fashion + * + * @version $Rev$ $Date$ + */ +public class StatelessScopeContainer extends AbstractScopeContainer { + + public StatelessScopeContainer() { + this(null); + } + + public StatelessScopeContainer(WorkContext workContext) { + super("Stateless scope", workContext); + } + + public Scope getScope() { + return Scope.STATELESS; + } + + public synchronized void start() { + if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) { + throw new IllegalStateException("Scope must be in UNINITIALIZED or STOPPED state [" + lifecycleState + "]"); + } + lifecycleState = RUNNING; + } + + public synchronized void stop() { + if (lifecycleState != RUNNING) { + throw new IllegalStateException("Scope in wrong state [" + lifecycleState + "]"); + } + lifecycleState = STOPPED; + } + + public void onEvent(Event event) { + } + + public void register(AtomicComponent component) { + checkInit(); + } + + protected InstanceWrapper getInstanceWrapper(AtomicComponent component) throws TargetException { + InstanceWrapper ctx = new InstanceWrapperImpl(component, component.createInstance()); + ctx.start(); + return ctx; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeObjectFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeObjectFactory.java new file mode 100644 index 0000000000..446f57b11a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/component/scope/StatelessScopeObjectFactory.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.core.component.scope; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.component.ScopeRegistry; +import org.apache.tuscany.spi.annotation.Autowire; +import org.osoa.sca.annotations.Init; + +/** + * Creates a new stateless scope context + * + * @version $$Rev$$ $$Date$$ + */ +public class StatelessScopeObjectFactory implements ObjectFactory<StatelessScopeContainer> { + + public StatelessScopeObjectFactory(@Autowire ScopeRegistry registry) { + registry.registerFactory(Scope.STATELESS, this); + } + + @Init(eager = true) + public void init() { + } + + public StatelessScopeContainer getInstance() throws ObjectCreationException { + return new StatelessScopeContainer(); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingInteceptor.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingInteceptor.java new file mode 100644 index 0000000000..d7627d11b1 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingInteceptor.java @@ -0,0 +1,129 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.databinding.Mediator; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.InvocationRuntimeException; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.RuntimeWire; + +/** + * An interceptor to transform data accross databindings on the wire + */ +public class DataBindingInteceptor implements Interceptor { + private Interceptor next; + + private CompositeComponent compositeComponent; + + private Operation<?> sourceOperation; + + private Operation<?> targetOperation; + + private Mediator mediator; + + public DataBindingInteceptor(RuntimeWire sourceWire, Operation<?> sourceOperation, RuntimeWire targetWire, + Operation<?> targetOperation) { + super(); + // this.sourceWire = sourceWire; + this.sourceOperation = sourceOperation; + // this.targetWire = targetWire; + this.targetOperation = targetOperation; + this.compositeComponent = (CompositeComponent) sourceWire.getContainer().getParent(); + } + + /** + * @see org.apache.tuscany.spi.wire.Interceptor#getNext() + */ + public Interceptor getNext() { + return next; + } + + /** + * @see org.apache.tuscany.spi.wire.Interceptor#invoke(org.apache.tuscany.spi.wire.Message) + */ + public Message invoke(Message msg) { + Object input = transform(msg.getBody(), sourceOperation.getInputType(), targetOperation.getInputType()); + msg.setBody(input); + Message resultMsg = next.invoke(msg); + Object result = resultMsg.getBody(); + // FIXME: How to deal with faults? + if (resultMsg.isFault()) { + // We need to figure out what fault type it is and then transform it back the source fault type + throw new InvocationRuntimeException((Throwable) result); + } else if (result != null) { + // FIXME: Should we fix the Operation model so that getOutputType returns DataType<DataType<T>>? + DataType<DataType> targetType = + new DataType<DataType>("idl:output", Object.class, targetOperation.getOutputType()); + + targetType.setMetadata(Operation.class.getName(), targetOperation.getOutputType().getMetadata( + Operation.class.getName())); + DataType<DataType> sourceType = + new DataType<DataType>("idl:output", Object.class, sourceOperation.getOutputType()); + sourceType.setMetadata(Operation.class.getName(), sourceOperation.getOutputType().getMetadata( + Operation.class.getName())); + + result = transform(result, targetType, sourceType); + resultMsg.setBody(result); + } + return resultMsg; + } + + private Object transform(Object source, DataType sourceType, DataType targetType) { + if (source == null) { + // Shortcut for null value + return null; + } + if (sourceType == targetType || (sourceType != null && sourceType.equals(targetType))) { + return source; + } + Map<Class<?>, Object> metadata = new HashMap<Class<?>, Object>(); + metadata.put(CompositeComponent.class, compositeComponent); + return mediator.mediate(source, sourceType, targetType, metadata); + } + + /** + * @see org.apache.tuscany.spi.wire.Interceptor#isOptimizable() + */ + public boolean isOptimizable() { + return false; + } + + /** + * @see org.apache.tuscany.spi.wire.Interceptor#setNext(org.apache.tuscany.spi.wire.Interceptor) + */ + public void setNext(Interceptor next) { + this.next = next; + } + + /** + * @param mediator the mediator to set + */ + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingJavaInterfaceProcessor.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingJavaInterfaceProcessor.java new file mode 100644 index 0000000000..9e4b4abfed --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingJavaInterfaceProcessor.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.xml.datatype.Duration; +import javax.xml.datatype.XMLGregorianCalendar; + +import org.apache.tuscany.api.annotation.DataContext; +import org.apache.tuscany.api.annotation.DataType; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorExtension; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.model.Operation; + +/** + * The databinding annotation processor for java interfaces + */ +public class DataBindingJavaInterfaceProcessor extends JavaInterfaceProcessorExtension { + + private static final String SIMPLE_JAVA_OBJECTS = "java.lang.Object"; + + private static final Class[] SIMPLE_JAVA_TYPES = + {Byte.class, Character.class, Short.class, Integer.class, Long.class, Float.class, Double.class, + Date.class, Calendar.class, GregorianCalendar.class, Duration.class, XMLGregorianCalendar.class}; + + private static final Set<Class> SIMPLE_TYPE_SET = new HashSet<Class>(Arrays.asList(SIMPLE_JAVA_TYPES)); + + public void visitInterface(Class<?> clazz, Class<?> callbackClass, JavaServiceContract contract) + throws InvalidServiceContractException { + Map<String, Operation<Type>> operations = contract.getOperations(); + processInterface(clazz, contract, operations); + if (callbackClass != null) { + Map<String, Operation<Type>> callbackOperations = contract.getCallbackOperations(); + processInterface(callbackClass, contract, callbackOperations); + } + } + + private void processInterface(Class<?> clazz, + JavaServiceContract contract, + Map<String, Operation<Type>> operations) { + DataType interfaceDataType = clazz.getAnnotation(DataType.class); + if (interfaceDataType != null) { + contract.setDataBinding(interfaceDataType.name()); + // FIXME: [rfeng] Keep data context as metadata? + for (DataContext c : interfaceDataType.context()) { + contract.setMetaData(c.key(), c.value()); + } + } + for (Method method : clazz.getMethods()) { + Operation<?> operation = operations.get(method.getName()); + DataType operationDataType = method.getAnnotation(DataType.class); + + if (operationDataType != null) { + operation.setDataBinding(operationDataType.name()); + // FIXME: [rfeng] Keep data context as metadata? + for (DataContext c : operationDataType.context()) { + operation.setMetaData(c.key(), c.value()); + } + } + + String dataBinding = operation.getDataBinding(); + + // FIXME: We need a better way to identify simple java types + for (org.apache.tuscany.spi.model.DataType<?> d : operation.getInputType().getLogical()) { + adjustSimpleType(d, dataBinding); + } + if (operation.getOutputType() != null) { + adjustSimpleType(operation.getOutputType(), dataBinding); + } + for (org.apache.tuscany.spi.model.DataType<?> d : operation.getFaultTypes()) { + adjustSimpleType(d, dataBinding); + } + } + } + + private void adjustSimpleType(org.apache.tuscany.spi.model.DataType<?> dataType, String dataBinding) { + Type type = dataType.getPhysical(); + if (!(type instanceof Class)) { + return; + } + Class cls = (Class)dataType.getPhysical(); + if (cls.isPrimitive() || SIMPLE_TYPE_SET.contains(cls)) { + dataType.setDataBinding(SIMPLE_JAVA_OBJECTS); + } else if (cls == String.class && (dataBinding == null || !dataBinding.equals(String.class.getName()))) { + // Identify the String as a simple type + dataType.setDataBinding(SIMPLE_JAVA_OBJECTS); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingRegistryImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingRegistryImpl.java new file mode 100644 index 0000000000..f2ff257e7e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingRegistryImpl.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.core.databinding.impl; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.databinding.DataBinding; +import org.apache.tuscany.spi.databinding.DataBindingRegistry; +import org.apache.tuscany.spi.model.DataType; +import org.osoa.sca.annotations.Init; + +/** + * The default implementation of a data binding registry + */ +public class DataBindingRegistryImpl implements DataBindingRegistry { + private final Map<String, DataBinding> bindings = new HashMap<String, DataBinding>(); + + public DataBinding getDataBinding(String id) { + if (id == null) { + return null; + } + return bindings.get(id.toLowerCase()); + } + + public void register(DataBinding dataBinding) { + bindings.put(dataBinding.getName().toLowerCase(), dataBinding); + } + + public DataBinding unregister(String id) { + if (id == null) { + return null; + } + return bindings.remove(id.toLowerCase()); + } + + @Init(eager = true) + public void init() { + } + + public DataType introspectType(Class<?> javaType) { + DataType dataType = null; + for (DataBinding binding : bindings.values()) { + dataType = binding.introspect(javaType); + if (dataType != null) { + return dataType; + } + } + return null; + } + + public DataType introspectType(Object value) { + DataType dataType = null; + for (DataBinding binding : bindings.values()) { + dataType = binding.introspect(value); + if (dataType != null) { + return dataType; + } + } + return null; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingWirePostProcessor.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingWirePostProcessor.java new file mode 100644 index 0000000000..947887b460 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataBindingWirePostProcessor.java @@ -0,0 +1,153 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import java.util.Map; +import java.util.Set; + +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.builder.WirePostProcessorExtension; +import org.apache.tuscany.spi.component.Reference; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.databinding.Mediator; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; + +/** + * This processor is responsible to add an interceptor to invocation chain if + * the source and target operations have different databinding requirements + */ +public class DataBindingWirePostProcessor extends WirePostProcessorExtension { + private Mediator mediator; + + @Constructor({"mediator"}) + public DataBindingWirePostProcessor(@Autowire Mediator mediator) { + super(); + this.mediator = mediator; + } + + public void process(OutboundWire source, InboundWire target) { + Map<Operation<?>, OutboundInvocationChain> chains = source.getInvocationChains(); + for (Map.Entry<Operation<?>, OutboundInvocationChain> entry : chains.entrySet()) { + Operation<?> sourceOperation = entry.getKey(); + Operation<?> targetOperation = + getTargetOperation(target.getInvocationChains().keySet(), sourceOperation.getName()); + String sourceDataBinding = getDataBinding(sourceOperation); + String targetDataBinding = getDataBinding(targetOperation); + if (sourceDataBinding == null || targetDataBinding == null + || !sourceDataBinding.equals(targetDataBinding)) { + // Add the interceptor to the source side because multiple + // references can be wired + // to the same service + DataBindingInteceptor interceptor = + new DataBindingInteceptor(source, sourceOperation, target, targetOperation); + interceptor.setMediator(mediator); + entry.getValue().addInterceptor(0, interceptor); + } + } + + // Check if there's a callback + Map callbackOperations = source.getServiceContract().getCallbackOperations(); + if (callbackOperations == null || callbackOperations.isEmpty()) { + return; + } + Object targetAddress = source.getContainer().getName(); + Map<Operation<?>, OutboundInvocationChain> callbackChains = + target.getSourceCallbackInvocationChains(targetAddress); + for (Map.Entry<Operation<?>, OutboundInvocationChain> entry : callbackChains.entrySet()) { + Operation<?> sourceOperation = entry.getKey(); + Operation<?> targetOperation = + getTargetOperation(source.getTargetCallbackInvocationChains().keySet(), sourceOperation + .getName()); + String sourceDataBinding = getDataBinding(sourceOperation); + String targetDataBinding = getDataBinding(targetOperation); + if (sourceDataBinding == null || targetDataBinding == null + || !sourceDataBinding.equals(targetDataBinding)) { + // Add the interceptor to the source side because multiple + // references can be wired + // to the same service + DataBindingInteceptor interceptor = + new DataBindingInteceptor(source, sourceOperation, target, targetOperation); + interceptor.setMediator(mediator); + entry.getValue().addInterceptor(0, interceptor); + } + } + } + + public void process(InboundWire source, OutboundWire target) { + SCAObject container = source.getContainer(); + // Either Service or Reference + boolean isReference = container instanceof Reference; + + Map<Operation<?>, InboundInvocationChain> chains = source.getInvocationChains(); + for (Map.Entry<Operation<?>, InboundInvocationChain> entry : chains.entrySet()) { + Operation<?> sourceOperation = entry.getKey(); + Operation<?> targetOperation = + getTargetOperation(target.getInvocationChains().keySet(), sourceOperation.getName()); + String sourceDataBinding = getDataBinding(sourceOperation); + String targetDataBinding = getDataBinding(targetOperation); + if (sourceDataBinding == null || targetDataBinding == null + || !sourceDataBinding.equals(targetDataBinding)) { + // Add the interceptor to the source side + DataBindingInteceptor interceptor = + new DataBindingInteceptor(source, sourceOperation, target, targetOperation); + interceptor.setMediator(mediator); + if (isReference) { + // FIXME: We need a better way to position the interceptors + target.getInvocationChains().get(targetOperation).addInterceptor(0, interceptor); + Interceptor tail = entry.getValue().getTailInterceptor(); + if (tail != null) { + // HACK to relink the bridging interceptor + tail.setNext(interceptor); + } + } else { + entry.getValue().addInterceptor(0, interceptor); + } + + } + } + } + + private Operation getTargetOperation(Set<Operation<?>> operations, String operationName) { + for (Operation<?> op : operations) { + if (op.getName().equals(operationName)) { + return op; + } + } + return null; + } + + private String getDataBinding(Operation<?> operation) { + String dataBinding = operation.getDataBinding(); + if (dataBinding == null) { + ServiceContract<?> serviceContract = operation.getServiceContract(); + dataBinding = serviceContract.getDataBinding(); + } + return dataBinding; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataTypeLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataTypeLoader.java new file mode 100644 index 0000000000..8b3296a017 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DataTypeLoader.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.impl; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.InvalidValueException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.LoaderUtil; +import org.apache.tuscany.spi.model.DataType; +import org.osoa.sca.annotations.Constructor; + +/** + * The StAX loader for data type + */ +public class DataTypeLoader extends LoaderExtension<DataType> { + public static final QName DATA_BINDING = + new QName("http://incubator.apache.org/tuscany/xmlns/databinding/1.0-incubator-M2", "databinding"); + + @Constructor({"registry"}) + public DataTypeLoader(@Autowire LoaderRegistry registry) { + super(registry); + } + + @Override + public QName getXMLType() { + return DATA_BINDING; + } + + public DataType load(CompositeComponent parent, + XMLStreamReader reader, + DeploymentContext deploymentContext) throws XMLStreamException, LoaderException { + assert DATA_BINDING.equals(reader.getName()); + String name = reader.getAttributeValue(null, "name"); + LoaderUtil.skipToEndElement(reader); + if (name == null) { + throw new InvalidValueException("The 'name' attrbiute is required"); + } + DataType dataType = new DataType<Class>(name, Object.class, Object.class); + return dataType; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DirectedGraph.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DirectedGraph.java new file mode 100755 index 0000000000..02adf5860c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/DirectedGraph.java @@ -0,0 +1,357 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.impl; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Directed, weighted graph + * + * @param <V> The type of vertex object + * @param <E> The type of edge object + */ +public class DirectedGraph<V, E> { + private final Map<V, Vertex> vertices = new HashMap<V, Vertex>(); + + /** + * Key for the shortest path cache + */ + private final class VertexPair { + private Vertex source; + + private Vertex target; + + /** + * @param source + * @param target + */ + private VertexPair(Vertex source, Vertex target) { + super(); + this.source = source; + this.target = target; + } + + public boolean equals(Object object) { + if (!VertexPair.class.isInstance(object)) { + return false; + } + VertexPair pair = (VertexPair)object; + return source == pair.source && target == pair.target; + } + + public int hashCode() { + int x = source == null ? 0 : source.hashCode(); + int y = target == null ? 0 : target.hashCode(); + return x ^ y; + } + + } + + private final Map<VertexPair, Path> paths = new HashMap<VertexPair, Path>(); + + /** + * Vertex of a graph + */ + public final class Vertex { + private V value; + + // TODO: Do we want to support multiple edges for a vertex pair? If so, + // we should use a List instead of Map + private Map<Vertex, Edge> outEdges = new HashMap<Vertex, Edge>(); + + private Vertex(V value) { + this.value = value; + } + + public String toString() { + return "(" + value + ")"; + } + + public V getValue() { + return value; + } + + public Map<Vertex, Edge> getOutEdges() { + return outEdges; + } + + } + + /** + * An Edge connects two vertices in one direction + */ + public final class Edge { + private Vertex sourceVertex; + + private Vertex targetVertex; + + private E value; + + private int weight; + + public Edge(Vertex source, Vertex target, E value, int weight) { + this.sourceVertex = source; + this.targetVertex = target; + this.value = value; + this.weight = weight; + } + + public String toString() { + return sourceVertex + "->" + targetVertex + "[" + value + "," + weight + "]"; + } + + public E getValue() { + return value; + } + + public void setValue(E value) { + this.value = value; + } + + public Vertex getTargetVertex() { + return targetVertex; + } + + public void setTargetVertex(Vertex vertex) { + this.targetVertex = vertex; + } + + public int getWeight() { + return weight; + } + + public void setWeight(int weight) { + this.weight = weight; + } + + public Vertex getSourceVertex() { + return sourceVertex; + } + + public void setSourceVertex(Vertex sourceVertex) { + this.sourceVertex = sourceVertex; + } + } + + private final class Node implements Comparable<Node> { + + private long distance = Integer.MAX_VALUE; + + private Node previous; // NOPMD by rfeng on 9/26/06 9:17 PM + + private Vertex vertex; // NOPMD by rfeng on 9/26/06 9:17 PM + + private Node(Vertex vertex) { + this.vertex = vertex; + } + + public int compareTo(Node o) { + return (distance > o.distance) ? 1 : ((distance == o.distance) ? 0 : -1); + } + } + + public void addEdge(V source, V target, E edgeValue, int weight) { + Vertex s = getVertex(source); + if (s == null) { + s = new Vertex(source); + vertices.put(source, s); + } + Vertex t = getVertex(target); + if (t == null) { + t = new Vertex(target); + vertices.put(target, t); + } + Edge edge = new Edge(s, t, edgeValue, weight); + s.outEdges.put(t, edge); + } + + public Vertex getVertex(V source) { + Vertex s = vertices.get(source); + return s; + } + + public boolean removeEdge(V source, V target) { + Vertex s = getVertex(source); + if (s == null) { + return false; + } + + Vertex t = getVertex(target); + if (t == null) { + return false; + } + + return s.outEdges.remove(t) != null; + + } + + public Edge getEdge(Vertex source, Vertex target) { + return source.outEdges.get(target); + } + + public Edge getEdge(V source, V target) { + return getEdge(getVertex(source), getVertex(target)); + } + + /** + * Get the shortes path from the source vertex to the target vertex using + * Dijkstra's algorithm. If there's no path, null will be returned. If the + * source is the same as the target, it returns a path with empty edges with + * weight 0. + * + * @param sourceValue The value identifies the source + * @param targetValue The value identifies the target + * @return The shortest path + */ + public Path getShortestPath(V sourceValue, V targetValue) { + Vertex source = getVertex(sourceValue); + if (source == null) { + return null; + } + Vertex target = getVertex(targetValue); + if (target == null) { + return null; + } + + VertexPair pair = new VertexPair(source, target); + if (paths.containsKey(pair)) { + return paths.get(pair); + } + + // HACK: To support same vertex + if (source == target) { + Path path = new Path(); + Edge edge = getEdge(source, target); + if (edge != null) { + path.addEdge(edge); + } + paths.put(pair, path); + return path; + } + + Map<Vertex, Node> nodes = new HashMap<Vertex, Node>(); + for (Vertex v : vertices.values()) { + Node node = new Node(v); + if (v == source) { + node.distance = 0; + } + nodes.put(v, node); + } + + Set<Node> otherNodes = new HashSet<Node>(nodes.values()); + Set<Node> nodesOnPath = new HashSet<Node>(); + while (!otherNodes.isEmpty()) { + Node nextNode = extractMin(otherNodes); + if (nextNode.vertex == target) { + Path path = getPath(nextNode); + paths.put(pair, path); // Cache it + return path; + } + nodesOnPath.add(nextNode); + for (Edge edge : nextNode.vertex.outEdges.values()) { + Node adjacentNode = nodes.get(edge.targetVertex); + if (nextNode.distance + edge.weight < adjacentNode.distance) { + adjacentNode.distance = nextNode.distance + edge.weight; + adjacentNode.previous = nextNode; + } + } + } + paths.put(pair, null); // Cache it + return null; + } + + /** + * Searches for the vertex u in the vertex set Q that has the least d[u] + * value. That vertex is removed from the set Q and returned to the user. + * + * @param nodes + * @return + */ + private Node extractMin(Set<Node> nodes) { + Node node = Collections.min(nodes); + nodes.remove(node); + return node; + } + + /** + * The path between two vertices + */ + public final class Path { + private List<Edge> edges = new LinkedList<Edge>(); + + private int weight; + + public int getWeight() { + return weight; + } + + public List<Edge> getEdges() { + return edges; + } + + public void addEdge(Edge edge) { + edges.add(0, edge); + weight += edge.weight; + } + + public String toString() { + return edges + ", " + weight; + } + } + + private Path getPath(Node t) { + if (t.distance == Integer.MAX_VALUE) { + return null; + } + Path path = new Path(); + Node u = t; + while (u.previous != null) { + Edge edge = getEdge(u.previous.vertex, u.vertex); + path.addEdge(edge); + u = u.previous; + } + return path; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + for (Vertex v : vertices.values()) { + sb.append(v.outEdges.values()).append("\n"); + } + return sb.toString(); + } + + public Map<V, Vertex> getVertices() { + return vertices; + } + + public void addGraph(DirectedGraph<V, E> otherGraph) { + for (Vertex v : otherGraph.vertices.values()) { + for (Edge e : v.outEdges.values()) { + addEdge(e.sourceVertex.value, e.targetVertex.value, e.value, e.weight); + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Input2InputTransformer.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Input2InputTransformer.java new file mode 100644 index 0000000000..81cf3a9e3d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Input2InputTransformer.java @@ -0,0 +1,216 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.databinding.DataBinding; +import org.apache.tuscany.spi.databinding.DataBindingRegistry; +import org.apache.tuscany.spi.databinding.Mediator; +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.WrapperHandler; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.apache.tuscany.spi.idl.ElementInfo; +import org.apache.tuscany.spi.idl.WrapperInfo; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.Operation; +import org.osoa.sca.annotations.Service; + +/** + * This is a special transformer to transform the input from one IDL to the + * other one + */ +@Service(Transformer.class) +public class Input2InputTransformer extends TransformerExtension<Object[], Object[]> implements + PullTransformer<Object[], Object[]> { + + private static final String IDL_INPUT = "idl:input"; + + protected DataBindingRegistry dataBindingRegistry; + + protected Mediator mediator; + + public Input2InputTransformer() { + super(); + } + + @Override + public String getSourceDataBinding() { + return IDL_INPUT; + } + + @Override + public String getTargetDataBinding() { + return IDL_INPUT; + } + + /** + * @param mediator the mediator to set + */ + @Autowire + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } + + /** + * @param dataBindingRegistry the dataBindingRegistry to set + */ + @Autowire + public void setDataBindingRegistry(DataBindingRegistry dataBindingRegistry) { + this.dataBindingRegistry = dataBindingRegistry; + } + + /** + * @see org.apache.tuscany.spi.databinding.extension.TransformerExtension#getSourceType() + */ + @Override + protected Class getSourceType() { + return Object[].class; + } + + /** + * @see org.apache.tuscany.spi.databinding.extension.TransformerExtension#getTargetType() + */ + @Override + protected Class getTargetType() { + return Object[].class; + } + + /** + * @see org.apache.tuscany.spi.databinding.Transformer#getWeight() + */ + public int getWeight() { + return 10000; + } + + @SuppressWarnings("unchecked") + public Object[] transform(Object[] source, TransformationContext context) { + DataType<List<DataType<?>>> sourceType = context.getSourceDataType(); + Operation<?> sourceOp = (Operation<?>)sourceType.getMetadata(Operation.class.getName()); + boolean sourceWrapped = sourceOp != null && sourceOp.isWrapperStyle(); + + WrapperHandler sourceWrapperHandler = null; + if (sourceWrapped) { + sourceWrapperHandler = getWapperHandler(sourceType.getLogical().get(0).getDataBinding(), true); + } + + DataType<List<DataType<QName>>> targetType = context.getTargetDataType(); + Operation<?> targetOp = (Operation<?>)targetType.getMetadata(Operation.class.getName()); + boolean targetWrapped = targetOp != null && targetOp.isWrapperStyle(); + WrapperHandler targetWrapperHandler = null; + if (targetWrapped) { + targetWrapperHandler = getWapperHandler(targetType.getLogical().get(0).getDataBinding(), true); + } + + if ((!sourceWrapped) && targetWrapped) { + // Unwrapped --> Wrapped + WrapperInfo wrapper = targetOp.getWrapper(); + ElementInfo wrapperElement = wrapper.getInputWrapperElement(); + + // If the source can be wrapped, wrapped it first + if (sourceWrapperHandler != null) { + Object sourceWrapper = sourceWrapperHandler.create(wrapperElement, context); + for (int i = 0; i < source.length; i++) { + ElementInfo argElement = wrapper.getInputChildElements().get(i); + sourceWrapperHandler.setChild(sourceWrapper, i, argElement, source[0]); + } + } + Object targetWrapper = targetWrapperHandler.create(wrapperElement, context); + if (source == null) { + return new Object[] {targetWrapper}; + } + List<DataType<QName>> argTypes = wrapper.getUnwrappedInputType().getLogical(); + + for (int i = 0; i < source.length; i++) { + ElementInfo argElement = wrapper.getInputChildElements().get(i); + DataType<QName> argType = argTypes.get(i); + Object child = source[i]; + child = + mediator.mediate(source[i], sourceType.getLogical().get(i), argType, context + .getMetadata()); + targetWrapperHandler.setChild(targetWrapper, i, argElement, child); + } + return new Object[] {targetWrapper}; + } else if (sourceWrapped && (!targetWrapped)) { + // Wrapped to Unwrapped + Object sourceWrapper = source[0]; + List<ElementInfo> childElements = sourceOp.getWrapper().getInputChildElements(); + Object[] target = new Object[childElements.size()]; + + targetWrapperHandler = getWapperHandler(targetType.getLogical().get(0).getDataBinding(), false); + if (targetWrapperHandler != null) { + ElementInfo wrapperElement = sourceOp.getWrapper().getInputWrapperElement(); + // Object targetWrapper = + // targetWrapperHandler.create(wrapperElement, context); + DataType<QName> targetWrapperType = + new DataType<QName>(targetType.getLogical().get(0).getDataBinding(), Object.class, + wrapperElement.getQName()); + Object targetWrapper = + mediator.mediate(sourceWrapper, + sourceType.getLogical().get(0), + targetWrapperType, + context.getMetadata()); + for (int i = 0; i < childElements.size(); i++) { + ElementInfo childElement = childElements.get(i); + target[i] = targetWrapperHandler.getChild(targetWrapper, i, childElement); + } + } else { + for (int i = 0; i < childElements.size(); i++) { + ElementInfo childElement = childElements.get(i); + Object child = sourceWrapperHandler.getChild(sourceWrapper, i, childElement); + DataType<QName> childType = + sourceOp.getWrapper().getUnwrappedInputType().getLogical().get(i); + target[i] = + mediator.mediate(child, childType, targetType.getLogical().get(i), context + .getMetadata()); + } + } + return target; + } else { + // Assuming wrapper to wrapper conversion can be handled here as + // well + Object[] newArgs = new Object[source.length]; + for (int i = 0; i < source.length; i++) { + Object child = + mediator.mediate(source[i], sourceType.getLogical().get(i), targetType.getLogical() + .get(i), context.getMetadata()); + newArgs[i] = child; + } + return newArgs; + } + } + + private WrapperHandler getWapperHandler(String dataBindingId, boolean required) { + DataBinding dataBinding = dataBindingRegistry.getDataBinding(dataBindingId); + WrapperHandler wrapperHandler = dataBinding == null ? null : dataBinding.getWrapperHandler(); + if (wrapperHandler == null && required) { + throw new TransformationException( + "No wrapper handler is provided for databinding: " + dataBindingId); + } + return wrapperHandler; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/MediatorImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/MediatorImpl.java new file mode 100644 index 0000000000..f8b38de806 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/MediatorImpl.java @@ -0,0 +1,175 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.impl; + +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.databinding.DataBindingRegistry; +import org.apache.tuscany.spi.databinding.DataPipe; +import org.apache.tuscany.spi.databinding.Mediator; +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.TransformerRegistry; +import org.apache.tuscany.spi.model.DataType; +import org.osoa.sca.annotations.Scope; + +/** + * Default Mediator implementation + */ +@Scope("MODULE") +public class MediatorImpl implements Mediator { + + private DataBindingRegistry dataBindingRegistry; + + private TransformerRegistry transformerRegistry; + + @Autowire + public void setTransformerRegistry(TransformerRegistry transformerRegistry) { + this.transformerRegistry = transformerRegistry; + } + + /** + * @param dataBindingRegistry the dataBindingRegistry to set + */ + @Autowire + public void setDataBindingRegistry(DataBindingRegistry dataBindingRegistry) { + this.dataBindingRegistry = dataBindingRegistry; + } + + /** + * @see org.apache.tuscany.spi.databinding.Mediator#mediate(java.lang.Object, + * org.apache.tuscany.spi.model.DataType, + * org.apache.tuscany.spi.model.DataType, Map) + */ + @SuppressWarnings("unchecked") + public Object mediate(Object source, + DataType sourceDataType, + DataType targetDataType, + Map<Class<?>, Object> metadata) { + if (source == null) { + // Shortcut for null value + return null; + } + if (sourceDataType == null) { + sourceDataType = dataBindingRegistry.introspectType(source); + } + if (sourceDataType == null) { + return source; + } else if (sourceDataType.equals(targetDataType)) { + return source; + } + + List<Transformer> path = getTransformerChain(sourceDataType, targetDataType); + + Object result = source; + int size = path.size(); + int i = 0; + while (i < size) { + Transformer transformer = path.get(i); + TransformationContext context = + createTransformationContext(sourceDataType, targetDataType, size, i, transformer, metadata); + // the source and target type + if (transformer instanceof PullTransformer) { + // For intermediate node, set data type to null + result = ((PullTransformer)transformer).transform(result, context); + } else if (transformer instanceof PushTransformer) { + DataPipe dataPipe = (i < size - 1) ? (DataPipe)path.get(++i) : null; + ((PushTransformer)transformer).transform(result, dataPipe.getSink(), context); + result = dataPipe.getResult(); + } + i++; + } + + return result; + } + + private TransformationContext createTransformationContext(DataType sourceDataType, + DataType targetDataType, + int size, + int index, + Transformer transformer, + Map<Class<?>, Object> metadata) { + DataType sourceType = + (index == 0) ? sourceDataType : new DataType<Object>(transformer.getSourceDataBinding(), + Object.class, null); + DataType targetType = + (index == size - 1) ? targetDataType : new DataType<Object>(transformer.getTargetDataBinding(), + Object.class, null); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + TransformationContext context = + new TransformationContextImpl(sourceType, targetType, classLoader, metadata); + return context; + } + + @SuppressWarnings("unchecked") + public void mediate(Object source, + Object target, + DataType sourceDataType, + DataType targetDataType, + Map<Class<?>, Object> metadata) { + if (source == null) { + // Shortcut for null value + return; + } + if (sourceDataType == null) { + sourceDataType = dataBindingRegistry.introspectType(source); + } + if (sourceDataType == null) { + return; + } else if (sourceDataType.equals(targetDataType)) { + return; + } + + List<Transformer> path = getTransformerChain(sourceDataType, targetDataType); + Object result = source; + int size = path.size(); + for (int i = 0; i < size; i++) { + Transformer transformer = path.get(i); + TransformationContext context = + createTransformationContext(sourceDataType, targetDataType, size, i, transformer, metadata); + + if (transformer instanceof PullTransformer) { + result = ((PullTransformer)transformer).transform(result, context); + } else if (transformer instanceof PushTransformer) { + DataPipe dataPipe = (i < size - 1) ? (DataPipe)path.get(++i) : null; + Object sink = dataPipe != null ? dataPipe.getSink() : target; + ((PushTransformer)transformer).transform(result, sink, context); + result = (dataPipe != null) ? dataPipe.getResult() : null; + } + } + } + + private List<Transformer> getTransformerChain(DataType sourceDataType, DataType targetDataType) { + String sourceId = sourceDataType.getDataBinding(); + String targetId = targetDataType.getDataBinding(); + List<Transformer> path = transformerRegistry.getTransformerChain(sourceId, targetId); + if (path == null) { + TransformationException ex = new TransformationException("No path found for the transformation"); + ex.addContextName("Source: " + sourceId); + ex.addContextName("Target: " + targetId); + throw ex; + } + return path; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Output2OutputTransformer.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Output2OutputTransformer.java new file mode 100644 index 0000000000..f0405ca313 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/Output2OutputTransformer.java @@ -0,0 +1,195 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.databinding.DataBinding; +import org.apache.tuscany.spi.databinding.DataBindingRegistry; +import org.apache.tuscany.spi.databinding.Mediator; +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.WrapperHandler; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.apache.tuscany.spi.idl.ElementInfo; +import org.apache.tuscany.spi.idl.WrapperInfo; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.Operation; +import org.osoa.sca.annotations.Service; + +/** + * This is a special transformer to transform the output from one IDL to the + * other one + */ +@Service(Transformer.class) +public class Output2OutputTransformer extends TransformerExtension<Object, Object> implements + PullTransformer<Object, Object> { + private static final String IDL_OUTPUT = "idl:output"; + + protected DataBindingRegistry dataBindingRegistry; + + protected Mediator mediator; + + /** + * @param wrapperHandler + */ + public Output2OutputTransformer() { + super(); + } + + /** + * @param mediator the mediator to set + */ + @Autowire + public void setMediator(Mediator mediator) { + this.mediator = mediator; + } + + /** + * @param dataBindingRegistry the dataBindingRegistry to set + */ + @Autowire + public void setDataBindingRegistry(DataBindingRegistry dataBindingRegistry) { + this.dataBindingRegistry = dataBindingRegistry; + } + + @Override + public String getSourceDataBinding() { + return IDL_OUTPUT; + } + + @Override + public String getTargetDataBinding() { + return IDL_OUTPUT; + } + + /** + * @see org.apache.tuscany.spi.databinding.extension.TransformerExtension#getSourceType() + */ + @Override + protected Class getSourceType() { + return Object.class; + } + + /** + * @see org.apache.tuscany.spi.databinding.extension.TransformerExtension#getTargetType() + */ + @Override + protected Class getTargetType() { + return Object.class; + } + + /** + * @see org.apache.tuscany.spi.databinding.Transformer#getWeight() + */ + public int getWeight() { + return 10; + } + + private WrapperHandler getWapperHandler(Operation<?> operation) { + String dataBindingId; + dataBindingId = operation.getDataBinding(); + DataBinding dataBinding = dataBindingRegistry.getDataBinding(dataBindingId); + WrapperHandler wrapperHandler = dataBinding == null ? null : dataBinding.getWrapperHandler(); + if (wrapperHandler == null) { + throw new TransformationException( + "No wrapper handler is provided for databinding: " + dataBindingId); + } + return wrapperHandler; + } + + private WrapperHandler getWapperHandler(String dataBindingId) { + DataBinding dataBinding = dataBindingRegistry.getDataBinding(dataBindingId); + return dataBinding == null ? null : dataBinding.getWrapperHandler(); + } + + @SuppressWarnings("unchecked") + public Object transform(Object response, TransformationContext context) { + try { + DataType<DataType> sourceType = context.getSourceDataType(); + Operation<?> sourceOp = (Operation<?>)sourceType.getMetadata(Operation.class.getName()); + boolean sourceWrapped = sourceOp != null && sourceOp.isWrapperStyle(); + WrapperHandler sourceWrapperHandler = null; + if (sourceWrapped) { + sourceWrapperHandler = getWapperHandler(sourceOp); + } + + DataType<DataType> targetType = context.getTargetDataType(); + Operation<?> targetOp = (Operation<?>)targetType.getMetadata(Operation.class.getName()); + boolean targetWrapped = targetOp != null && targetOp.isWrapperStyle(); + WrapperHandler targetWrapperHandler = null; + if (targetWrapped) { + targetWrapperHandler = getWapperHandler(targetOp); + } + + if ((!sourceWrapped) && targetWrapped) { + // Unwrapped --> Wrapped + WrapperInfo wrapper = targetOp.getWrapper(); + Object targetWrapper = + targetWrapperHandler.create(wrapper.getOutputWrapperElement(), context); + if (response == null) { + return targetWrapper; + } + + ElementInfo argElement = wrapper.getOutputChildElements().get(0); + DataType<QName> argType = wrapper.getUnwrappedOutputType(); + Object child = response; + child = mediator.mediate(response, sourceType.getLogical(), argType, context.getMetadata()); + targetWrapperHandler.setChild(targetWrapper, 0, argElement, child); + return targetWrapper; + } else if (sourceWrapped && (!targetWrapped)) { + // Wrapped to Unwrapped + Object sourceWrapper = response; + List<ElementInfo> childElements = sourceOp.getWrapper().getOutputChildElements(); + ElementInfo childElement = childElements.get(0); + + targetWrapperHandler = getWapperHandler(targetType.getLogical().getDataBinding()); + if (targetWrapperHandler != null) { + ElementInfo wrapperElement = sourceOp.getWrapper().getInputWrapperElement(); + // Object targetWrapper = + // targetWrapperHandler.create(wrapperElement, context); + DataType<QName> targetWrapperType = + new DataType<QName>(targetType.getLogical().getDataBinding(), Object.class, + wrapperElement.getQName()); + Object targetWrapper = + mediator.mediate(sourceWrapper, sourceType.getLogical(), targetWrapperType, context + .getMetadata()); + return targetWrapperHandler.getChild(targetWrapper, 0, childElement); + } else { + Object child = sourceWrapperHandler.getChild(sourceWrapper, 0, childElement); + DataType<?> childType = sourceOp.getWrapper().getUnwrappedOutputType(); + return mediator.mediate(child, childType, targetType.getLogical(), context.getMetadata()); + } + } else { + // FIXME: Do we want to handle wrapped to wrapped? + return mediator.mediate(response, sourceType.getLogical(), targetType.getLogical(), context + .getMetadata()); + } + } catch (Exception e) { + throw new TransformationException(e); + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PipedTransformer.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PipedTransformer.java new file mode 100755 index 0000000000..388ea710a7 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/PipedTransformer.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.core.databinding.impl; + +import org.apache.tuscany.spi.databinding.DataPipe; +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; + +/** + * A utility class to connect PushTransformer and DataPipe to create a + * PullTransformer + * + * @param <S> Source type + * @param <I> Intermidate type + * @param <R> Result type + */ +public class PipedTransformer<S, I, R> implements PullTransformer<S, R> { + private PushTransformer<S, I> pusher; + + private DataPipe<I, R> pipe; + + /** + * @param pumper + * @param pipe + */ + public PipedTransformer(PushTransformer<S, I> pumper, DataPipe<I, R> pipe) { + super(); + this.pusher = pumper; + this.pipe = pipe; + } + + public R transform(S source, TransformationContext context) { + pusher.transform(source, pipe.getSink(), context); + return pipe.getResult(); + } + + public String getSourceDataBinding() { + return pusher.getSourceDataBinding(); + } + + public String getTargetDataBinding() { + return pipe.getTargetDataBinding(); + } + + public int getWeight() { + return pusher.getWeight() + pipe.getWeight(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/SimpleDataBinding.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/SimpleDataBinding.java new file mode 100644 index 0000000000..9d56ab5353 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/SimpleDataBinding.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import org.apache.tuscany.spi.databinding.extension.DataBindingExtension; +import org.apache.tuscany.spi.loader.MissingResourceException; +import org.osoa.sca.annotations.Property; + +/** + * Simple databinding represented by a base java type. A SCDL property className + * is used to customize this component. + * <p> + * The following illustrates how a simple data binding can be registered as a + * SCA component. + * <p> + * <component name="databinding.MyDataBinding"><br> + * <system:implementation.java + * class="org.apache.tuscany.databinding.impl.SimpleDataBinding"/><br> + * <property name="className">my.Type</property><br> + * </component> + */ +public class SimpleDataBinding extends DataBindingExtension { + + public SimpleDataBinding(@Property(name = "className") String className) throws MissingResourceException { + super(resolve(className)); + } + + private static Class<?> resolve(String className) throws MissingResourceException { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + try { + return Class.forName(className, false, classLoader); + } catch (ClassNotFoundException e) { + classLoader = SimpleDataBinding.class.getClassLoader(); + try { + return Class.forName(className, false, classLoader); + } catch (ClassNotFoundException e1) { + MissingResourceException mre = new MissingResourceException(className, e1); + throw mre; + } + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformationContextImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformationContextImpl.java new file mode 100755 index 0000000000..47f340097b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformationContextImpl.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.core.databinding.impl; + +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.model.DataType; + +public class TransformationContextImpl implements TransformationContext { + private DataType sourceDataType; + + private DataType targetDataType; + + private final Map<Class<?>, Object> metadata = new HashMap<Class<?>, Object>(); + + private WeakReference<ClassLoader> classLoaderRef; + + public TransformationContextImpl() { + super(); + setClassLoader(Thread.currentThread().getContextClassLoader()); + } + + public TransformationContextImpl(DataType sourceDataType, + DataType targetDataType, + ClassLoader classLoader, + Map<Class<?>, Object> metadata) { + super(); + this.sourceDataType = sourceDataType; + this.targetDataType = targetDataType; + setClassLoader(classLoader); + if (metadata != null) { + this.metadata.putAll(metadata); + } + } + + public DataType getSourceDataType() { + return sourceDataType; + } + + public DataType getTargetDataType() { + return targetDataType; + } + + public void setSourceDataType(DataType sourceDataType) { + this.sourceDataType = sourceDataType; + } + + public void setTargetDataType(DataType targetDataType) { + this.targetDataType = targetDataType; + } + + public final void setClassLoader(ClassLoader classLoader) { + this.classLoaderRef = new WeakReference<ClassLoader>(classLoader); + } + + public ClassLoader getClassLoader() { + return classLoaderRef.get(); + } + + public Map<Class<?>, Object> getMetadata() { + return metadata; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformerRegistryImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformerRegistryImpl.java new file mode 100755 index 0000000000..5cbd931cb0 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/impl/TransformerRegistryImpl.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.core.databinding.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.TransformerRegistry; +import org.osoa.sca.annotations.Init; + +public class TransformerRegistryImpl implements TransformerRegistry { + + private final DirectedGraph<Object, Transformer> graph = new DirectedGraph<Object, Transformer>(); + + @Init(eager = true) + public void init() { + } + + public void registerTransformer(String sourceType, String resultType, int weight, Transformer transformer) { + graph.addEdge(sourceType, resultType, transformer, weight); + } + + public void registerTransformer(Transformer transformer) { + graph.addEdge(transformer.getSourceDataBinding(), + transformer.getTargetDataBinding(), + transformer, + transformer.getWeight()); + } + + public boolean unregisterTransformer(String sourceType, String resultType) { + return graph.removeEdge(sourceType, resultType); + } + + public Transformer getTransformer(String sourceType, String resultType) { + DirectedGraph<Object, Transformer>.Edge edge = graph.getEdge(sourceType, resultType); + return (edge == null) ? null : edge.getValue(); + } + + public List<Transformer> getTransformerChain(String sourceType, String resultType) { + List<Transformer> transformers = new ArrayList<Transformer>(); + DirectedGraph<Object, Transformer>.Path path = graph.getShortestPath(sourceType, resultType); + if (path == null) { + return null; + } + for (DirectedGraph<Object, Transformer>.Edge edge : path.getEdges()) { + transformers.add(edge.getValue()); + } + return transformers; + } + + public String toString() { + return graph.toString(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMDataBinding.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMDataBinding.java new file mode 100644 index 0000000000..9fc1cc5152 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMDataBinding.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.xml; + + +import org.apache.tuscany.spi.databinding.WrapperHandler; +import org.apache.tuscany.spi.databinding.extension.DataBindingExtension; +import org.w3c.dom.Node; + +/** + * DOM DataBinding + */ +public class DOMDataBinding extends DataBindingExtension { + public static final String NAME = Node.class.getName(); + + public DOMDataBinding() { + super(Node.class); + } + + @Override + public WrapperHandler getWrapperHandler() { + return new DOMWrapperHandler(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMWrapperHandler.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMWrapperHandler.java new file mode 100644 index 0000000000..0373ebcdfe --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMWrapperHandler.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.core.databinding.xml; + +import javax.xml.namespace.QName; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.WrapperHandler; +import org.apache.tuscany.spi.databinding.extension.DOMHelper; +import org.apache.tuscany.spi.idl.ElementInfo; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class DOMWrapperHandler implements WrapperHandler<Node> { + + private Document document; + + public DOMWrapperHandler() { + super(); + try { + this.document = DOMHelper.newDocument(); + } catch (ParserConfigurationException e) { + throw new TransformationException(e); + } + } + + public Node create(ElementInfo element, TransformationContext context) { + QName name = element.getQName(); + return DOMHelper.createElement(document, name); + } + + public Object getChild(Node wrapper, int i, ElementInfo element) { + int index = 0; + NodeList nodes = wrapper.getChildNodes(); + for (int j = 0; j < nodes.getLength(); j++) { + Node node = nodes.item(j); + if (node.getNodeType() != Node.ELEMENT_NODE) { + continue; + } + if (index != i) { + index++; + } else { + QName name = DOMHelper.getQName(node); + if (name.equals(element.getQName())) { + return node; + } + } + } + return null; + } + + public void setChild(Node wrapper, int i, ElementInfo childElement, Object value) { + Node node = (Node) value; + if (node.getNodeType() == Node.DOCUMENT_NODE) { + node = ((Document) node).getDocumentElement(); + } + wrapper.appendChild(wrapper.getOwnerDocument().importNode(node, true)); + } +}
\ No newline at end of file diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMXMLStreamReader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMXMLStreamReader.java new file mode 100644 index 0000000000..5a12cc72cb --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/DOMXMLStreamReader.java @@ -0,0 +1,1410 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +import org.w3c.dom.Attr; +import org.w3c.dom.CharacterData; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.apache.tuscany.core.databinding.xml.StAXHelper.XMLFragmentStreamReader; + +public class DOMXMLStreamReader implements XMLFragmentStreamReader { + protected static class DelegatingNamespaceContext implements NamespaceContext { + private int counter; + + private NamespaceContext parent; + + private Map<String, String> prefixToNamespaceMapping = new HashMap<String, String>(); + + public DelegatingNamespaceContext(NamespaceContext parent) { + super(); + this.parent = parent; + + prefixToNamespaceMapping.put("xml", "http://www.w3.org/XML/1998/namespace"); + prefixToNamespaceMapping.put("xmlns", "http://www.w3.org/2000/xmlns/"); + prefixToNamespaceMapping.put("xsi", "http://www.w3.org/2001/XMLSchema-instance"); + } + + public synchronized QName createQName(String nsURI, String name) { + String prefix = nsURI != null ? (String) getPrefix(nsURI) : null; + if (prefix == null && nsURI != null && !nsURI.equals("")) { + prefix = "p" + (counter++); + } + if (prefix == null) { + prefix = ""; + } + if (nsURI != null) { + prefixToNamespaceMapping.put(prefix, nsURI); + } + return new QName(nsURI, name, prefix); + } + + public String getNamespaceURI(String prefix) { + if (prefix == null) { + throw new IllegalArgumentException("Prefix is null"); + } + + String ns = (String) prefixToNamespaceMapping.get(prefix); + if (ns != null) { + return ns; + } else if (parent != null) { + return parent.getNamespaceURI(prefix); + } else { + return null; + } + } + + public String getPrefix(String nsURI) { + if (nsURI == null) { + throw new IllegalArgumentException("Namespace is null"); + } + for (Map.Entry<String, String> entry1 : prefixToNamespaceMapping.entrySet()) { + Map.Entry entry = entry1; + if (entry.getValue().equals(nsURI)) { + return (String) entry.getKey(); + } + } + if (parent != null) { + return parent.getPrefix(nsURI); + } else { + return null; + } + } + + public Iterator getPrefixes(String nsURI) { + List<String> prefixList = new ArrayList<String>(); + for (Map.Entry<String, String> entry : prefixToNamespaceMapping.entrySet()) { + if (entry.getValue().equals(nsURI)) { + prefixList.add(entry.getKey()); + } + } + if (parent != null) { + for (Iterator i = parent.getPrefixes(nsURI); i.hasNext();) { + prefixList.add((String) i.next()); + } + } + return prefixList.iterator(); + } + + public void registerMapping(String prefix, String nsURI) { + prefixToNamespaceMapping.put(prefix, nsURI); + } + + public void removeMapping(String prefix) { + prefixToNamespaceMapping.remove(prefix); + } + + public void setParent(NamespaceContext parent) { + this.parent = parent; + } + } + + protected static class NameValuePair implements Map.Entry { + private Object key; + + private Object value; + + public NameValuePair(Object key, Object value) { + this.key = key; + this.value = value; + } + + public Object getKey() { + return key; + } + + public Object getValue() { + return value; + } + + public Object setValue(Object value) { + Object v = this.value; + this.value = value; + return v; + } + + } + + protected static class SimpleElementStreamReader implements XMLFragmentStreamReader { + + private static final int END_ELEMENT_STATE = 2; + + private static final int START_ELEMENT_STATE = 0; + + private static final int START_ELEMENT_STATE_WITH_NULL = 3; + + private static final int TEXT_STATE = 1; + + private static final QName XSI_NIL_QNAME = + new QName("http://www.w3.org/2001/XMLSchema-instance", "nil", "xsi"); + + private QName name; + + private DelegatingNamespaceContext namespaceContext = new DelegatingNamespaceContext(null); + + private int state = START_ELEMENT_STATE; + + private String value; + + public SimpleElementStreamReader(QName name, String value) { + this.name = name; + this.value = value; + if (value == null) { + state = START_ELEMENT_STATE_WITH_NULL; + } + } + + public void close() throws XMLStreamException { + // Do nothing - we've nothing to free here + } + + public int getAttributeCount() { + if (state == START_ELEMENT_STATE_WITH_NULL) { + return 1; + } + if (state == START_ELEMENT_STATE) { + return 0; + } else { + throw new IllegalStateException(); + } + + } + + public String getAttributeLocalName(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return XSI_NIL_QNAME.getLocalPart(); + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public QName getAttributeName(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return XSI_NIL_QNAME; + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeNamespace(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return XSI_NIL_QNAME.getNamespaceURI(); + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributePrefix(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return XSI_NIL_QNAME.getPrefix(); + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeType(int i) { + return null; // not implemented + } + + public String getAttributeValue(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return "true"; + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeValue(String string, String string1) { + if (state == TEXT_STATE) { + // todo something + return null; + } else { + return null; + } + + } + + public String getCharacterEncodingScheme() { + return null; + } + + public String getElementText() throws XMLStreamException { + if (state == START_ELEMENT) { + // move to the end state and return the value + state = END_ELEMENT_STATE; + return value; + } else { + throw new XMLStreamException(); + } + + } + + public String getEncoding() { + return "UTF-8"; + } + + public int getEventType() { + switch (state) { + case START_ELEMENT_STATE: + case START_ELEMENT_STATE_WITH_NULL: + return START_ELEMENT; + case END_ELEMENT_STATE: + return END_ELEMENT; + case TEXT_STATE: + return CHARACTERS; + default: + throw new UnsupportedOperationException(); + // we've no idea what this is!!!!! + } + + } + + public String getLocalName() { + if (state != TEXT_STATE) { + return name.getLocalPart(); + } else { + return null; + } + } + + public Location getLocation() { + return new Location() { + public int getCharacterOffset() { + return 0; + } + + public int getColumnNumber() { + return 0; + } + + public int getLineNumber() { + return 0; + } + + public String getPublicId() { + return null; + } + + public String getSystemId() { + return null; + } + }; + } + + public QName getName() { + if (state != TEXT_STATE) { + return name; + } else { + return null; + } + } + + public NamespaceContext getNamespaceContext() { + return this.namespaceContext; + } + + public int getNamespaceCount() { + if (state == START_ELEMENT_STATE_WITH_NULL && isXsiNamespacePresent()) { + return 1; + } else { + return 0; + } + + } + + public String getNamespacePrefix(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && isXsiNamespacePresent() && i == 0) { + return XSI_NIL_QNAME.getPrefix(); + } else { + return null; + } + } + + public String getNamespaceURI() { + if (state != TEXT_STATE) { + return name.getNamespaceURI(); + } else { + return null; + } + + } + + public String getNamespaceURI(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && isXsiNamespacePresent() && i == 0) { + return XSI_NIL_QNAME.getNamespaceURI(); + } else { + return null; + } + } + + public String getNamespaceURI(String prefix) { + return namespaceContext.getNamespaceURI(prefix); + } + + public String getPIData() { + return null; + } + + public String getPITarget() { + return null; + } + + public String getPrefix() { + if (state != TEXT_STATE) { + return name.getPrefix(); + } else { + return null; + } + } + + public Object getProperty(String key) throws IllegalArgumentException { + return null; + } + + public String getText() { + if (state == TEXT_STATE) { + return value; + } else { + throw new IllegalStateException(); + } + } + + public char[] getTextCharacters() { + if (state == TEXT_STATE) { + return value.toCharArray(); + } else { + throw new IllegalStateException(); + } + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + // not implemented + throw new UnsupportedOperationException(); + } + + public int getTextLength() { + if (state == TEXT_STATE) { + return value.length(); + } else { + throw new IllegalStateException(); + } + + } + + public int getTextStart() { + if (state == TEXT_STATE) { + return 0; + } else { + throw new IllegalStateException(); + } + } + + public String getVersion() { + return null; // todo 1.0 ? + } + + public boolean hasName() { + return state != TEXT_STATE; + + } + + public boolean hasNext() throws XMLStreamException { + return state != END_ELEMENT_STATE; + } + + public boolean hasText() { + return state == TEXT_STATE; + } + + public void init() { + // just add the current elements namespace and prefix to the this + // elements nscontext + registerNamespace(name.getPrefix(), name.getNamespaceURI()); + + } + + public boolean isAttributeSpecified(int i) { + return false; // no attribs here + } + + public boolean isCharacters() { + return state == TEXT_STATE; + } + + public boolean isEndElement() { + return state == END_ELEMENT_STATE; + } + + public boolean isEndOfFragment() { + return state == END_ELEMENT_STATE; + } + + public boolean isStandalone() { + return false; + } + + public boolean isStartElement() { + return state == START_ELEMENT_STATE || state == START_ELEMENT_STATE_WITH_NULL; + } + + public boolean isWhiteSpace() { + return false; // no whitespaces here + } + + /** + * Test whether the xsi namespace is present + * + * @return + */ + private boolean isXsiNamespacePresent() { + return namespaceContext.getNamespaceURI(XSI_NIL_QNAME.getPrefix()) != null; + } + + public int next() throws XMLStreamException { + switch (state) { + case START_ELEMENT_STATE: + state = TEXT_STATE; + return CHARACTERS; + case START_ELEMENT_STATE_WITH_NULL: + state = END_ELEMENT_STATE; + return END_ELEMENT; + case END_ELEMENT_STATE: + // oops, not supposed to happen! + throw new XMLStreamException("end already reached!"); + case TEXT_STATE: + state = END_ELEMENT_STATE; + return END_ELEMENT; + default: + throw new XMLStreamException("unknown event type!"); + } + } + + public int nextTag() throws XMLStreamException { + return 0; // todo + } + + /** + * @param prefix + * @param uri + */ + private void registerNamespace(String prefix, String uri) { + // todo - need to fix this up to cater for cases where + // namespaces are having no prefixes + if (!uri.equals(namespaceContext.getNamespaceURI(prefix))) { + // this namespace is not there. Need to declare it + namespaceContext.registerMapping(prefix, uri); + } + } + + public void require(int i, String string, String string1) throws XMLStreamException { + // not implemented + } + + public void setParentNamespaceContext(NamespaceContext nsContext) { + this.namespaceContext.setParent(nsContext); + } + + public boolean standaloneSet() { + return false; + } + + } + + private static final int DELEGATED_STATE = 2; + + private static final int END_ELEMENT_STATE = 1; + + // states for this pullparser - it can only have three states + private static final int START_ELEMENT_STATE = 0; + + private static final int TEXT_STATE = 3; + + private Map.Entry[] attributes; + + // reference to the child reader + private XMLFragmentStreamReader childReader; + + // current property index + private int currentPropertyIndex; + + private Map<String, String> declaredNamespaceMap = new HashMap<String, String>(); + + private QName elementQName; + + // we always create a new namespace context + private DelegatingNamespaceContext namespaceContext = new DelegatingNamespaceContext(null); + + private Map.Entry[] properties; + + private Element rootElement; + + private String rootElementName; + + private String rootElementURI; + + // integer field that keeps the state of this + // parser. + private int state = START_ELEMENT_STATE; + + public DOMXMLStreamReader(Node node) { + switch (node.getNodeType()) { + case Node.DOCUMENT_NODE: + this.rootElement = ((Document) node).getDocumentElement(); + break; + case Node.ELEMENT_NODE: + this.rootElement = (Element) node; + break; + default: + throw new IllegalArgumentException("Illegal Node"); + } + this.rootElementName = rootElement.getLocalName(); + this.rootElementURI = rootElement.getNamespaceURI(); + + declaredNamespaceMap.put("xml", "http://www.w3.org/XML/1998/namespace"); + declaredNamespaceMap.put("xmlns", "http://www.w3.org/2000/xmlns/"); + declaredNamespaceMap.put("xsi", "http://www.w3.org/2001/XMLSchema-instance"); + + populateProperties(); + } + + /* + * we need to pass in a namespace context since when delegated, we've no + * idea of the current namespace context. So it needs to be passed on here! + */ + protected DOMXMLStreamReader(QName elementQName, Map.Entry[] properties, Map.Entry[] attributes) { + // validate the lengths, since both the arrays are supposed + // to have + this.properties = properties; + this.elementQName = elementQName; + this.attributes = attributes; + + } + + public void close() throws XMLStreamException { + // do nothing here - we have no resources to free + } + + public int getAttributeCount() { + return (state == DELEGATED_STATE) ? childReader.getAttributeCount() + : ((attributes != null) && (state == START_ELEMENT_STATE) ? attributes.length : 0); + } + + public String getAttributeLocalName(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeLocalName(i); + } else if (state == START_ELEMENT_STATE) { + QName name = getAttributeName(i); + if (name == null) { + return null; + } else { + return name.getLocalPart(); + } + } else { + throw new IllegalStateException(); + } + } + + /** + * @param i + * @return + */ + public QName getAttributeName(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeName(i); + } else if (state == START_ELEMENT_STATE) { + if (attributes == null) { + return null; + } else { + if ((i >= (attributes.length)) || i < 0) { // out of range + return null; + } else { + // get the attribute pointer + Object attribPointer = attributes[i].getKey(); + // case one - attrib name is null + // this should be the pointer to the OMAttribute then + if (attribPointer instanceof String) { + return new QName((String) attribPointer); + } else if (attribPointer instanceof QName) { + return (QName) attribPointer; + } else { + return null; + } + } + } + } else { + throw new IllegalStateException(); // as per the api contract + } + + } + + public String getAttributeNamespace(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeNamespace(i); + } else if (state == START_ELEMENT_STATE) { + QName name = getAttributeName(i); + if (name == null) { + return null; + } else { + return name.getNamespaceURI(); + } + } else { + throw new IllegalStateException(); + } + } + + public String getAttributePrefix(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributePrefix(i); + } else if (state == START_ELEMENT_STATE) { + QName name = getAttributeName(i); + if (name == null) { + return null; + } else { + return name.getPrefix(); + } + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeType(int i) { + return null; // not supported + } + + public String getAttributeValue(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeValue(i); + } else if (state == START_ELEMENT_STATE) { + if (attributes == null) { + return null; + } else { + if ((i >= (attributes.length)) || i < 0) { // out of range + return null; + } else { + // get the attribute pointer + Object attribPointer = attributes[i].getKey(); + Object omAttribObj = attributes[i].getValue(); + // case one - attrib name is null + // this should be the pointer to the OMAttribute then + if (attribPointer instanceof String) { + return (String) omAttribObj; + } else if (attribPointer instanceof QName) { + return (String) omAttribObj; + } else { + return null; + } + } + } + } else { + throw new IllegalStateException(); + } + + } + + public String getAttributeValue(String nsUri, String localName) { + + int attribCount = getAttributeCount(); + String returnValue = null; + QName attribQualifiedName; + for (int i = 0; i < attribCount; i++) { + attribQualifiedName = getAttributeName(i); + if (nsUri == null) { + if (localName.equals(attribQualifiedName.getLocalPart())) { + returnValue = getAttributeValue(i); + break; + } + } else { + if (localName.equals(attribQualifiedName.getLocalPart()) && nsUri.equals(attribQualifiedName + .getNamespaceURI())) { + returnValue = getAttributeValue(i); + break; + } + } + + } + + return returnValue; + } + + public String getCharacterEncodingScheme() { + return null; // todo - should we return something for this ? + } + + /** + * todo implement the right contract for this + * + * @return + * @throws XMLStreamException + */ + public String getElementText() throws XMLStreamException { + if (state == DELEGATED_STATE) { + return childReader.getElementText(); + } else { + return null; + } + + } + + public String getEncoding() { + if (state == DELEGATED_STATE) { + return childReader.getEncoding(); + } else { + // we've no idea what the encoding is going to be in this case + // perhaps we ought to return some constant here, which the user + // might + // have access to change! + return null; + } + } + + // ///////////////////////////////////////////////////////////////////////// + // / attribute handling + // ///////////////////////////////////////////////////////////////////////// + + public int getEventType() { + if (state == START_ELEMENT_STATE) { + return START_ELEMENT; + } else if (state == END_ELEMENT_STATE) { + return END_ELEMENT; + } else { // this is the delegated state + return childReader.getEventType(); + } + + } + + public String getLocalName() { + if (state == DELEGATED_STATE) { + return childReader.getLocalName(); + } else if (state != TEXT_STATE) { + return elementQName.getLocalPart(); + } else { + throw new IllegalStateException(); + } + } + + /** + * @return + */ + public Location getLocation() { + // return a default location + return new Location() { + public int getCharacterOffset() { + return 0; + } + + public int getColumnNumber() { + return 0; + } + + public int getLineNumber() { + return 0; + } + + public String getPublicId() { + return null; + } + + public String getSystemId() { + return null; + } + }; + } + + public QName getName() { + if (state == DELEGATED_STATE) { + return childReader.getName(); + } else if (state != TEXT_STATE) { + return elementQName; + } else { + throw new IllegalStateException(); + } + + } + + public NamespaceContext getNamespaceContext() { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceContext(); + } else { + return namespaceContext; + } + + } + + public int getNamespaceCount() { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceCount(); + } else { + return declaredNamespaceMap.size(); + } + } + + /** + * @param i + * @return + */ + public String getNamespacePrefix(int i) { + if (state == DELEGATED_STATE) { + return childReader.getNamespacePrefix(i); + } else if (state != TEXT_STATE) { + // order the prefixes + String[] prefixes = makePrefixArray(); + if ((i >= prefixes.length) || (i < 0)) { + return null; + } else { + return prefixes[i]; + } + + } else { + throw new IllegalStateException(); + } + + } + + public String getNamespaceURI() { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceURI(); + } else if (state == TEXT_STATE) { + return null; + } else { + return elementQName.getNamespaceURI(); + } + } + + public String getNamespaceURI(int i) { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceURI(i); + } else if (state != TEXT_STATE) { + String namespacePrefix = getNamespacePrefix(i); + return namespacePrefix == null ? null : (String) declaredNamespaceMap.get(namespacePrefix); + } else { + throw new IllegalStateException(); + } + + } + + // ///////////////////////////////////////////////////////////////////////// + // //////////// end of attribute handling + // ///////////////////////////////////////////////////////////////////////// + + // ////////////////////////////////////////////////////////////////////////// + // //////////// namespace handling + // ////////////////////////////////////////////////////////////////////////// + + public String getNamespaceURI(String prefix) { + return namespaceContext.getNamespaceURI(prefix); + } + + public String getPIData() { + throw new UnsupportedOperationException("Yet to be implemented !!"); + } + + public String getPITarget() { + throw new UnsupportedOperationException("Yet to be implemented !!"); + } + + public String getPrefix() { + if (state == DELEGATED_STATE) { + return childReader.getPrefix(); + } else if (state == TEXT_STATE) { + return null; + } else { + return elementQName.getPrefix(); + } + } + + /** + * @param key + * @return + * @throws IllegalArgumentException + */ + public Object getProperty(String key) throws IllegalArgumentException { + if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) { + return null; + } else if (state == TEXT_STATE) { + return null; + } else if (state == DELEGATED_STATE) { + return childReader.getProperty(key); + } else { + return null; + } + + } + + // ///////////////////////////////////////////////////////////////////////// + // /////// end of namespace handling + // ///////////////////////////////////////////////////////////////////////// + + public String getText() { + if (state == DELEGATED_STATE) { + return childReader.getText(); + } else if (state == TEXT_STATE) { + return (String) properties[currentPropertyIndex - 1].getValue(); + } else { + throw new IllegalStateException(); + } + } + + public char[] getTextCharacters() { + if (state == DELEGATED_STATE) { + return childReader.getTextCharacters(); + } else if (state == TEXT_STATE) { + return properties[currentPropertyIndex - 1].getValue() == null ? new char[0] + : ((String) properties[currentPropertyIndex - 1].getValue()).toCharArray(); + } else { + throw new IllegalStateException(); + } + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + if (state == DELEGATED_STATE) { + return childReader.getTextCharacters(i, chars, i1, i2); + } else if (state == TEXT_STATE) { + // todo - implement this + return 0; + } else { + throw new IllegalStateException(); + } + } + + public int getTextLength() { + if (state == DELEGATED_STATE) { + return childReader.getTextLength(); + } else if (state == TEXT_STATE) { + return 0; // assume text always starts at 0 + } else { + throw new IllegalStateException(); + } + } + + public int getTextStart() { + if (state == DELEGATED_STATE) { + return childReader.getTextStart(); + } else if (state == TEXT_STATE) { + return 0; // assume text always starts at 0 + } else { + throw new IllegalStateException(); + } + } + + public String getVersion() { + return null; + } + + public boolean hasName() { + // since this parser always has a name, the hasname + // has to return true if we are still navigating this element + // if not we should ask the child reader for it. + if (state == DELEGATED_STATE) { + return childReader.hasName(); + } else { + return state != TEXT_STATE; + } + } + + /** + * @return + * @throws XMLStreamException + */ + public boolean hasNext() throws XMLStreamException { + if (state == DELEGATED_STATE) { + if (childReader.isEndOfFragment()) { + // the child reader is done. We shouldn't be getting the + // hasnext result from the child pullparser then + return true; + } else { + return childReader.hasNext(); + } + } else { + return state == START_ELEMENT_STATE || state == TEXT_STATE; + + } + } + + /** + * check the validity of this implementation + * + * @return + */ + public boolean hasText() { + if (state == DELEGATED_STATE) { + return childReader.hasText(); + } else { + return state == TEXT_STATE; + } + } + + /** + * we need to split out the calling to the populate namespaces seperately since this needs to be done *after* + * setting the parent namespace context. We cannot assume it will happen at construction! + */ + public void init() { + // here we have an extra issue to attend to. we need to look at the + // prefixes and uris (the combination) and populate a hashmap of + // namespaces. The hashmap of namespaces will be used to serve the + // namespace context + + populateNamespaceContext(); + } + + public boolean isAttributeSpecified(int i) { + return false; // not supported + } + + public boolean isCharacters() { + if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) { + return false; + } + return childReader.isCharacters(); + } + + public boolean isEndElement() { + if (state == START_ELEMENT_STATE) { + return false; + } else if (state == END_ELEMENT_STATE) { + return true; + } + return childReader.isEndElement(); + } + + /** + * are we done ? + * + * @return + */ + public boolean isEndOfFragment() { + return state == END_ELEMENT_STATE; + } + + public boolean isStandalone() { + return true; + } + + public boolean isStartElement() { + if (state == START_ELEMENT_STATE) { + return true; + } else if (state == END_ELEMENT_STATE) { + return false; + } + return childReader.isStartElement(); + } + + public boolean isWhiteSpace() { + if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) { + return false; + } + return childReader.isWhiteSpace(); + } + + /** + * Get the prefix list from the hastable and take that into an array + * + * @return + */ + private String[] makePrefixArray() { + String[] prefixes = + (String[]) declaredNamespaceMap.keySet().toArray(new String[declaredNamespaceMap.size()]); + Arrays.sort(prefixes); + return prefixes; + } + + public int next() throws XMLStreamException { + return updateStatus(); + } + + /** + * todo implement this + * + * @return + * @throws XMLStreamException + */ + public int nextTag() throws XMLStreamException { + return 0; + } + + // ///////////////////////////////////////////////////////////////////////// + // / Other utility methods + // //////////////////////////////////////////////////////////////////////// + + /** + * Populates a namespace context + */ + private void populateNamespaceContext() { + + // first add the current element namespace to the namespace context + // declare it if not found + registerNamespace(elementQName.getPrefix(), elementQName.getNamespaceURI()); + + // traverse through the attributes and populate the namespace context + // the attrib list can be of many combinations + // the valid combinations are + // String - String + // QName - QName + // null - OMAttribute + + if (attributes != null) { + for (int i = 0; i < attributes.length; i++) { // jump in two + Object attribName = attributes[i].getKey(); + if (attribName instanceof String) { + // ignore this case - Nothing to do + } else if (attribName instanceof QName) { + QName attribQName = (QName) attribName; + registerNamespace(attribQName.getPrefix(), attribQName.getNamespaceURI()); + + } + } + } + + } + + public final void populateProperties() { + if (properties != null) { + return; + } + if (elementQName == null) { + elementQName = namespaceContext.createQName(this.rootElementURI, this.rootElementName); + } else { + elementQName = + namespaceContext.createQName(elementQName.getNamespaceURI(), elementQName.getLocalPart()); + } + + List<Object> elementList = new ArrayList<Object>(); + List<Object> attributeList = new ArrayList<Object>(); + NamedNodeMap nodeMap = rootElement.getAttributes(); + for (int i = 0; i < nodeMap.getLength(); i++) { + Attr attr = (Attr) nodeMap.item(i); + if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(attr.getNamespaceURI())) { + // Skip xmlns:xxx + registerNamespace(attr.getLocalName(), attr.getValue()); + continue; + } + QName attrName = new QName(attr.getNamespaceURI(), attr.getLocalName()); + NameValuePair pair = new NameValuePair(attrName, attr.getValue()); + attributeList.add(pair); + } + NodeList nodeList = rootElement.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) { + Node node = nodeList.item(i); + switch (node.getNodeType()) { + case Node.TEXT_NODE: + case Node.CDATA_SECTION_NODE: + NameValuePair pair = new NameValuePair(ELEMENT_TEXT, ((CharacterData) node).getData()); + elementList.add(pair); + break; + + case Node.ELEMENT_NODE: + Element element = (Element) node; + QName elementName = new QName(element.getNamespaceURI(), element.getLocalName()); + pair = new NameValuePair(elementName, new DOMXMLStreamReader(element)); + elementList.add(pair); + break; + } + } + properties = elementList.toArray(new Map.Entry[elementList.size()]); + attributes = attributeList.toArray(new Map.Entry[attributeList.size()]); + } + + /** + * A convenient method to reuse the properties + * + * @return event to be thrown + * @throws XMLStreamException + */ + private int processProperties() throws XMLStreamException { + // move to the next property depending on the current property + // index + Object propPointer = properties[currentPropertyIndex].getKey(); + QName propertyQName = null; + boolean textFound = false; + if (propPointer == null) { + throw new XMLStreamException("property key cannot be null!"); + } else if (propPointer instanceof String) { + // propPointer being a String has a special case + // that is it can be a the special constant ELEMENT_TEXT that + // says this text event + if (ELEMENT_TEXT.equals(propPointer)) { + textFound = true; + } else { + propertyQName = new QName((String) propPointer); + } + } else if (propPointer instanceof QName) { + propertyQName = (QName) propPointer; + } else { + // oops - we've no idea what kind of key this is + throw new XMLStreamException("unidentified property key!!!" + propPointer); + } + + // ok! we got the key. Now look at the value + Object propertyValue = properties[currentPropertyIndex].getValue(); + // cater for the special case now + if (textFound) { + // no delegation here - make the parser null and immediately + // return with the event characters + childReader = null; + state = TEXT_STATE; + currentPropertyIndex++; + return CHARACTERS; + } else if (propertyValue == null || propertyValue instanceof String) { + // strings are handled by the NameValuePairStreamReader + childReader = new SimpleElementStreamReader(propertyQName, (String) propertyValue); + childReader.setParentNamespaceContext(this.namespaceContext); + childReader.init(); + } else if (propertyValue instanceof DOMXMLStreamReader) { + // ADBbean has it's own method to get a reader + XMLFragmentStreamReader reader = (DOMXMLStreamReader) propertyValue; + // we know for sure that this is an ADB XMLStreamreader. + // However we need to make sure that it is compatible + childReader = reader; + childReader.setParentNamespaceContext(this.namespaceContext); + childReader.init(); + } else { + // all special possiblilities has been tried! Let's treat + // the thing as a bean and try generating events from it + throw new UnsupportedOperationException("Not supported"); + // childReader = new + // WrappingXMLStreamReader(BeanUtil.getPullParser(propertyValue, + // propertyQName)); + // we cannot register the namespace context here + } + + // set the state here + state = DELEGATED_STATE; + // we are done with the delegation + // increment the property index + currentPropertyIndex++; + return childReader.getEventType(); + } + + /** + * @param prefix + * @param uri + */ + private void registerNamespace(String prefix, String uri) { + if (!uri.equals(namespaceContext.getNamespaceURI(prefix))) { + namespaceContext.registerMapping(prefix, uri); + declaredNamespaceMap.put(prefix, uri); + } + } + + public void require(int i, String string, String string1) throws XMLStreamException { + throw new UnsupportedOperationException(); + } + + /** + * add the namespace context + */ + + public void setParentNamespaceContext(NamespaceContext nsContext) { + // register the namespace context passed in to this + this.namespaceContext.setParent(nsContext); + + } + + public boolean standaloneSet() { + return true; + } + + /** + * By far this should be the most important method in this class this method changes the state of the parser + * according to the change in the + */ + private int updateStatus() throws XMLStreamException { + int returnEvent = -1; // invalid state is the default state + switch (state) { + case START_ELEMENT_STATE: + // current element is start element. We should be looking at the + // property list and making a pullparser for the property value + if (properties == null || properties.length == 0) { + // no properties - move to the end element state + // straightaway + state = END_ELEMENT_STATE; + returnEvent = END_ELEMENT; + } else { + // there are properties. now we should delegate this task to + // a + // child reader depending on the property type + returnEvent = processProperties(); + + } + break; + case END_ELEMENT_STATE: + // we've reached the end element already. If the user tries to + // push + // further ahead then it is an exception + throw new XMLStreamException("Trying to go beyond the end of the pullparser"); + + case DELEGATED_STATE: + if (childReader.isEndOfFragment()) { + // we've reached the end! + if (currentPropertyIndex > (properties.length - 1)) { + state = END_ELEMENT_STATE; + returnEvent = END_ELEMENT; + } else { + returnEvent = processProperties(); + } + } else { + returnEvent = childReader.next(); + } + break; + + case TEXT_STATE: + // if there are any more event we should be delegating to + // processProperties. if not we just return an end element + if (currentPropertyIndex > (properties.length - 1)) { + state = END_ELEMENT_STATE; + returnEvent = END_ELEMENT; + } else { + returnEvent = processProperties(); + } + break; + } + return returnEvent; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2Node.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2Node.java new file mode 100644 index 0000000000..e9757fa13c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2Node.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.stream.StreamSource; + +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +/** + * Push DOM InputSource to Node + */ +@Service(Transformer.class) +public class InputSource2Node extends TransformerExtension<InputSource, Node> implements + PullTransformer<InputSource, Node> { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public Node transform(InputSource source, TransformationContext context) { + try { + Source streamSource = new StreamSource(source.getCharacterStream()); + DOMResult result = new DOMResult(); + TRANSFORMER.transform(streamSource, result, context); + return result.getNode(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return InputSource.class; + } + + public Class getTargetType() { + return Node.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2SAX.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2SAX.java new file mode 100644 index 0000000000..be78a07ede --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputSource2SAX.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * Push InputSource to SAX + */ +@Service(Transformer.class) +public class InputSource2SAX extends TransformerExtension<InputSource, ContentHandler> implements + PushTransformer<InputSource, ContentHandler> { + + public void transform(InputSource source, ContentHandler target, TransformationContext context) { + try { + XMLReader reader = XMLReaderFactory.createXMLReader(); + reader.setFeature("http://xml.org/sax/features/namespaces", true); + reader.setFeature("http://xml.org/sax/features/namespace-prefixes", false); + reader.setContentHandler(target); + reader.parse(source); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return InputSource.class; + } + + public Class getTargetType() { + return ContentHandler.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2Node.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2Node.java new file mode 100644 index 0000000000..e103c82b33 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2Node.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.InputStream; + +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.sax.SAXSource; + +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +/** + * Push DOM InputSource to Node + */ +@Service(Transformer.class) +public class InputStream2Node extends TransformerExtension<InputStream, Node> implements + PullTransformer<InputStream, Node> { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public Node transform(InputStream source, TransformationContext context) { + try { + Source streamSource = new SAXSource(new InputSource(source)); + DOMResult result = new DOMResult(); + TRANSFORMER.transform(streamSource, result, context); + return result.getNode(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return InputStream.class; + } + + public Class getTargetType() { + return Node.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2SAX.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2SAX.java new file mode 100644 index 0000000000..d74863ea95 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/InputStream2SAX.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.InputStream; + +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * Push InputStream to SAX + */ +@Service(Transformer.class) +public class InputStream2SAX extends TransformerExtension<InputStream, ContentHandler> implements + PushTransformer<InputStream, ContentHandler> { + public void transform(InputStream source, ContentHandler target, TransformationContext context) { + try { + XMLReader reader = XMLReaderFactory.createXMLReader(); + reader.setContentHandler(target); + reader.parse(new InputSource(source)); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return InputStream.class; + } + + public Class getTargetType() { + return ContentHandler.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Object.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Object.java new file mode 100644 index 0000000000..ec0560e878 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Object.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.core.databinding.xml; + +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.SimpleType2JavaTransformer; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/** + * Transformer to convert data from an simple Node to Java Object + */ +@Service(Transformer.class) +public class Node2Object extends SimpleType2JavaTransformer<Node> { + + public Node2Object() { + super(null); + } + + @Override + protected String getText(Node source) { + if (source instanceof Document) { + source = ((Document)source).getDocumentElement(); + } + return source.getTextContent(); + } + + public Class getSourceType() { + return Node.class; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2OutputStream.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2OutputStream.java new file mode 100644 index 0000000000..34fbdf8c6f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2OutputStream.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.core.databinding.xml; + +import java.io.OutputStream; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; + +/** + * Push DOM Node to OutputStream + */ +@Service(Transformer.class) +public class Node2OutputStream extends TransformerExtension<Node, OutputStream> implements + PushTransformer<Node, OutputStream> { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public void transform(Node source, OutputStream writer, TransformationContext context) { + try { + Source domSource = new DOMSource(source); + Result result = new StreamResult(writer); + TRANSFORMER.transform(domSource, result, context); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return Node.class; + } + + public Class getTargetType() { + return OutputStream.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2String.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2String.java new file mode 100755 index 0000000000..92378e96a3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2String.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.StringWriter; + +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; + +/** + * Transform DOM Node to XML String + */ +@Service(org.apache.tuscany.spi.databinding.Transformer.class) +public class Node2String extends TransformerExtension<Node, String> implements PullTransformer<Node, String> { + private static final Node2Writer TRANSFORMER = new Node2Writer(); + + public String transform(Node source, TransformationContext context) { + try { + StringWriter writer = new StringWriter(); + TRANSFORMER.transform(source, writer, context); + return writer.toString(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return Node.class; + } + + public Class getTargetType() { + return String.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Writer.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Writer.java new file mode 100644 index 0000000000..96328fdd2f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2Writer.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.Writer; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; + +/** + * Push DOM Node to Writer + */ +@Service(Transformer.class) +public class Node2Writer extends TransformerExtension<Node, Writer> implements PushTransformer<Node, Writer> { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public void transform(Node source, Writer writer, TransformationContext context) { + try { + Source domSource = new DOMSource(source); + Result result = new StreamResult(writer); + TRANSFORMER.transform(domSource, result, context); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return Node.class; + } + + public Class getTargetType() { + return Writer.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2XMLStreamReader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2XMLStreamReader.java new file mode 100644 index 0000000000..bff9051e01 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Node2XMLStreamReader.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.core.databinding.xml.StAXHelper.XMLDocumentStreamReader; +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; + +/** + * Transform DOM Node to XML XMLStreamReader + */ +@Service(Transformer.class) +public class Node2XMLStreamReader extends TransformerExtension<Node, XMLStreamReader> implements + PullTransformer<Node, XMLStreamReader> { + + public XMLStreamReader transform(Node source, TransformationContext context) { + try { + DOMXMLStreamReader reader = new DOMXMLStreamReader(source); + return new XMLDocumentStreamReader(reader); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return Node.class; + } + + public Class getTargetType() { + return XMLStreamReader.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Object2Node.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Object2Node.java new file mode 100644 index 0000000000..7f472ba4ff --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Object2Node.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.namespace.QName; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.DOMHelper; +import org.apache.tuscany.spi.databinding.extension.Java2SimpleTypeTransformer; +import org.apache.tuscany.spi.idl.ElementInfo; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/** + * Transformer to convert data from a simple java object to Node + */ +@Service(Transformer.class) +public class Object2Node extends Java2SimpleTypeTransformer<Node> { + + private Document factory; + + public Object2Node() { + super(null); + try { + factory = DOMHelper.newDocument(); + } catch (ParserConfigurationException e) { + throw new TransformationException(e); + } + } + + protected Node createElement(ElementInfo element, String text, TransformationContext context) { + QName name = element.getQName(); + Node root = DOMHelper.createElement(factory, name); + root.appendChild(factory.createTextNode(text)); + return root; + } + + public Class getTargetType() { + return Node.class; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2Node.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2Node.java new file mode 100644 index 0000000000..02de055c35 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2Node.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.Reader; + +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.stream.StreamSource; + +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; + +/** + * Push DOM Reader to Node + */ +@Service(Transformer.class) +public class Reader2Node extends TransformerExtension<Reader, Node> implements PullTransformer<Reader, Node> { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public Node transform(Reader source, TransformationContext context) { + try { + Source streamSource = new StreamSource(source); + DOMResult result = new DOMResult(); + TRANSFORMER.transform(streamSource, result, context); + return result.getNode(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return Reader.class; + } + + public Class getTargetType() { + return Node.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2SAX.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2SAX.java new file mode 100644 index 0000000000..0a4504b3de --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Reader2SAX.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.Reader; + +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; + +/** + * Transform XML string to SAX + */ +@Service(Transformer.class) +public class Reader2SAX extends TransformerExtension<Reader, ContentHandler> implements + PushTransformer<Reader, ContentHandler> { + public void transform(Reader source, ContentHandler target, TransformationContext context) { + try { + new InputSource2SAX().transform(new InputSource(source), target, context); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return Reader.class; + } + + public Class getTargetType() { + return ContentHandler.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOM.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOM.java new file mode 100644 index 0000000000..8f8f0f952e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOM.java @@ -0,0 +1,244 @@ +/* + * Copyright 2001-2004 The Apache Software Foundation. + * + * 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. + */ + +package org.apache.tuscany.core.databinding.xml; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.tuscany.spi.databinding.extension.DOMHelper; +import org.w3c.dom.Comment; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.ProcessingInstruction; +import org.w3c.dom.Text; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.ext.LexicalHandler; + +/** + * SAX2DOM adapter + */ +public class SAX2DOM implements ContentHandler, LexicalHandler { + public static final String EMPTYSTRING = ""; + public static final String XML_PREFIX = "xml"; + public static final String XMLNS_PREFIX = "xmlns"; + public static final String XMLNS_STRING = "xmlns:"; + public static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/"; + + private Node root; + + private Document document; + + private Node nextSibling; + + private Stack<Node> nodeStk = new Stack<Node>(); + + private List<String> namespaceDecls; + + private Node lastSibling; + + public SAX2DOM() throws ParserConfigurationException { + this.document = DOMHelper.newDocument(); + this.root = document; + } + + public SAX2DOM(Node root, Node nextSibling) throws ParserConfigurationException { + this.root = root; + if (root instanceof Document) { + this.document = (Document)root; + } else if (root != null) { + this.document = root.getOwnerDocument(); + } else { + this.document = DOMHelper.newDocument(); + this.root = document; + } + + this.nextSibling = nextSibling; + } + + public SAX2DOM(Node root) throws ParserConfigurationException { + this(root, null); + } + + public Node getDOM() { + return root; + } + + public void characters(char[] ch, int start, int length) { + final Node last = (Node)nodeStk.peek(); + + // No text nodes can be children of root (DOM006 exception) + if (last != document) { + final String text = new String(ch, start, length); + if (lastSibling != null && lastSibling.getNodeType() == Node.TEXT_NODE) { + ((Text)lastSibling).appendData(text); + } else if (last == root && nextSibling != null) { + lastSibling = last.insertBefore(document.createTextNode(text), nextSibling); + } else { + lastSibling = last.appendChild(document.createTextNode(text)); + } + + } + } + + public void startDocument() { + nodeStk.push(root); + } + + public void endDocument() { + nodeStk.pop(); + } + + public void startElement(String namespace, String localName, String qName, Attributes attrs) { + final Element tmp = (Element)document.createElementNS(namespace, qName); + + // Add namespace declarations first + if (namespaceDecls != null) { + final int nDecls = namespaceDecls.size(); + for (int i = 0; i < nDecls; i++) { + final String prefix = (String)namespaceDecls.get(i++); + + if (prefix == null || prefix.equals(EMPTYSTRING)) { + tmp.setAttributeNS(XMLNS_URI, XMLNS_PREFIX, (String)namespaceDecls.get(i)); + } else { + tmp.setAttributeNS(XMLNS_URI, XMLNS_STRING + prefix, (String)namespaceDecls.get(i)); + } + } + namespaceDecls.clear(); + } + + // Add attributes to element + final int nattrs = attrs.getLength(); + for (int i = 0; i < nattrs; i++) { + if (attrs.getLocalName(i) == null) { + tmp.setAttribute(attrs.getQName(i), attrs.getValue(i)); + } else { + tmp.setAttributeNS(attrs.getURI(i), attrs.getQName(i), attrs.getValue(i)); + } + } + + // Append this new node onto current stack node + Node last = (Node)nodeStk.peek(); + + // If the SAX2DOM is created with a non-null next sibling node, + // insert the result nodes before the next sibling under the root. + if (last == root && nextSibling != null) { + last.insertBefore(tmp, nextSibling); + } else { + last.appendChild(tmp); + } + + // Push this node onto stack + nodeStk.push(tmp); + lastSibling = null; + } + + public void endElement(String namespace, String localName, String qName) { + nodeStk.pop(); + lastSibling = null; + } + + public void startPrefixMapping(String prefix, String uri) { + if (namespaceDecls == null) { + namespaceDecls = new ArrayList<String>(2); + } + namespaceDecls.add(prefix); + namespaceDecls.add(uri); + } + + public void endPrefixMapping(String prefix) { + // do nothing + } + + /** + * This class is only used internally so this method should never be called. + */ + public void ignorableWhitespace(char[] ch, int start, int length) { + } + + /** + * adds processing instruction node to DOM. + */ + public void processingInstruction(String target, String data) { + final Node last = (Node)nodeStk.peek(); + ProcessingInstruction pi = document.createProcessingInstruction(target, data); + if (pi != null) { + if (last == root && nextSibling != null) { + last.insertBefore(pi, nextSibling); + } else { + last.appendChild(pi); + } + + lastSibling = pi; + } + } + + /** + * This class is only used internally so this method should never be called. + */ + public void setDocumentLocator(Locator locator) { + } + + /** + * This class is only used internally so this method should never be called. + */ + public void skippedEntity(String name) { + } + + /** + * Lexical Handler method to create comment node in DOM tree. + */ + public void comment(char[] ch, int start, int length) { + final Node last = (Node)nodeStk.peek(); + Comment comment = document.createComment(new String(ch, start, length)); + if (comment != null) { + if (last == root && nextSibling != null) { + last.insertBefore(comment, nextSibling); + } else { + last.appendChild(comment); + } + + lastSibling = comment; + } + } + + // Lexical Handler methods- not implemented + public void startCDATA() { + } + + public void endCDATA() { + } + + public void startEntity(java.lang.String name) { + } + + public void endDTD() { + } + + public void endEntity(String name) { + } + + public void startDTD(String name, String publicId, String systemId) throws SAXException { + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOMPipe.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOMPipe.java new file mode 100644 index 0000000000..79118b4a2c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/SAX2DOMPipe.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.tuscany.spi.databinding.DataPipe; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; +import org.xml.sax.ContentHandler; + +@Service(Transformer.class) +public class SAX2DOMPipe extends TransformerExtension<ContentHandler, Node> implements + DataPipe<ContentHandler, Node> { + private SAX2DOM pipe; + + /** + * + */ + public SAX2DOMPipe() { + super(); + try { + this.pipe = new SAX2DOM(); + } catch (ParserConfigurationException e) { + throw new IllegalArgumentException(e); + } + } + + public Node getResult() { + return pipe.getDOM(); + } + + public Class getTargetType() { + return Node.class; + } + + public ContentHandler getSink() { + return pipe; + } + + public Class getSourceType() { + return ContentHandler.class; + } + + public int getWeight() { + return 30; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Source2ResultTransformer.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Source2ResultTransformer.java new file mode 100755 index 0000000000..7db14efb39 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Source2ResultTransformer.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.TransformerFactory; + +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; + +/** + * Transform TrAX Source to Result + */ +@Service(org.apache.tuscany.spi.databinding.Transformer.class) +public class Source2ResultTransformer extends TransformerExtension<Source, Result> implements + PushTransformer<Source, Result> { + private static final TransformerFactory FACTORY = TransformerFactory.newInstance(); + + public void transform(Source source, Result result, TransformationContext context) { + try { + javax.xml.transform.Transformer transformer = FACTORY.newTransformer(); + transformer.transform(source, result); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return Source.class; + } + + public Class getTargetType() { + return Result.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAX2SAXAdapter.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAX2SAXAdapter.java new file mode 100644 index 0000000000..63fa53edb4 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAX2SAXAdapter.java @@ -0,0 +1,256 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +/** + * Adapter that converts from StAX to SAX event streams. Currently the following + * SAX events are not generated: + * <ul> + * <li>ignorableWhitespace</li> + * <li>skippedEntity</li> + * <ul> + * Also the following StAX events are not mapped: + * <ul> + * <li>CDATA</li> + * <li>COMMENT</li> + * <li>DTD</li> + * <li>ENTITY_DECLARATION</li> + * <li>ENTITY_REFERENCE</li> + * <li>NOTATION_DECLARATION</li> + * <li>SPACE</li> + * </ul> + * StAX ATTRIBUTE events are ignored but the equivalent attributes (derived from + * the START_ELEMENT event) are supplied in the SAX startElement event's + * Attributes parameter. If the adaptor is configured to pass namespace prefixes + * then namespace information will also be included in the Attributes; StAX + * NAMESPACE events are ignored. <p/> Another issue is namespace processing. If + * the reader is positioned at a sub-node, we cannot capture all the in-scope + * namespace bindings. Therefore we cannot re-create a proper SAX event stream + * from a StAX parser. <p/> For example <p/> <a:root xmlns:a="foo" + * xmlns:b="bar"><b:sub>a:foo</b:sub></a:root> <p/> And if + * you are handed a parser at <b:sub>, then your SAX events should look + * like: <p/> <b:sub xmlns:a="foo" xmlns:b="bar">a:foo</b:sub> <p/> + * not: <p/> <b:sub>a:foo</b:sub> <p/> <p/> Proposal: we change the + * receiver of SAX events (SDOXMLResourceImpl) so that it uses NamespaceContext + * to resolve prefix (as opposed to record start/endPrefixMappings and use it + * for resolution.) + * + * @version $Rev$ $Date$ + */ +public class StAX2SAXAdapter { + private final boolean namespacePrefixes; + + /** + * Construct a new StAX to SAX adapter that will convert a StAX event stream + * into a SAX event stream. + * + * @param namespacePrefixes whether xmlns attributes should be included in + * startElement events; + */ + public StAX2SAXAdapter(boolean namespacePrefixes) { + this.namespacePrefixes = namespacePrefixes; + } + + /** + * Pull events from the StAX stream and dispatch to the SAX ContentHandler. + * The StAX stream would typically be located on a START_DOCUMENT or + * START_ELEMENT event and when this method returns it will be located on + * the associated END_DOCUMENT or END_ELEMENT event. Behaviour with other + * start events is undefined. + * + * @param reader StAX event source to read + * @param handler SAX ContentHandler for processing events + * @throws XMLStreamException if there was a problem reading the stream + * @throws SAXException passed through from the ContentHandler + */ + public void parse(XMLStreamReader reader, ContentHandler handler) throws XMLStreamException, SAXException { + handler.setDocumentLocator(new LocatorAdaptor(reader.getLocation())); + + // remembers the nest level of elements to know when we are done + int level = 0; + int event = reader.getEventType(); + while (true) { + switch (event) { + case XMLStreamConstants.START_DOCUMENT: + level++; + handler.startDocument(); + break; + case XMLStreamConstants.START_ELEMENT: + level++; + handleStartElement(reader, handler); + break; + case XMLStreamConstants.PROCESSING_INSTRUCTION: + handler.processingInstruction(reader.getPITarget(), reader.getPIData()); + break; + case XMLStreamConstants.CHARACTERS: + handler.characters(reader.getTextCharacters(), reader.getTextStart(), reader + .getTextLength()); + break; + case XMLStreamConstants.END_ELEMENT: + handleEndElement(reader, handler); + level--; + if (level == 0) { + return; + } + break; + case XMLStreamConstants.END_DOCUMENT: + handler.endDocument(); + return; + /* + * uncomment to handle all events rather than just mapped + * ones // StAX events that are not mapped to SAX case + * XMLStreamConstants.COMMENT: case + * XMLStreamConstants.SPACE: case + * XMLStreamConstants.ENTITY_REFERENCE: case + * XMLStreamConstants.DTD: case XMLStreamConstants.CDATA: + * case XMLStreamConstants.NOTATION_DECLARATION: case + * XMLStreamConstants.ENTITY_DECLARATION: break; // StAX + * events handled in START_ELEMENT case + * XMLStreamConstants.ATTRIBUTE: case + * XMLStreamConstants.NAMESPACE: break; default: throw new + * AssertionError("Unknown StAX event: " + event); + */ + } + event = reader.next(); + } + } + + private void handleStartElement(XMLStreamReader reader, ContentHandler handler) throws SAXException { + // send startPrefixMapping events immediately before startElement event + int nsCount = reader.getNamespaceCount(); + for (int i = 0; i < nsCount; i++) { + String prefix = reader.getNamespacePrefix(i); + if (prefix == null) { // true for default namespace + prefix = ""; + } + handler.startPrefixMapping(prefix, reader.getNamespaceURI(i)); + } + + // fire startElement + QName qname = reader.getName(); + String prefix = qname.getPrefix(); + String rawname; + if (prefix == null || prefix.length() == 0) { + rawname = qname.getLocalPart(); + } else { + rawname = prefix + ':' + qname.getLocalPart(); + } + Attributes attrs = getAttributes(reader); + handler.startElement(qname.getNamespaceURI(), qname.getLocalPart(), rawname, attrs); + } + + private static void handleEndElement(XMLStreamReader reader, ContentHandler handler) throws SAXException { + // fire endElement + QName qname = reader.getName(); + handler.endElement(qname.getNamespaceURI(), qname.getLocalPart(), qname.toString()); + + // send endPrefixMapping events immediately after endElement event + // we send them in the opposite order to that returned but this is not + // actually required by SAX + int nsCount = reader.getNamespaceCount(); + for (int i = nsCount - 1; i >= 0; i--) { + String prefix = reader.getNamespacePrefix(i); + if (prefix == null) { // true for default namespace + prefix = ""; + } + handler.endPrefixMapping(prefix); + } + } + + /** + * Get the attributes associated with the current START_ELEMENT event. + * + * @return the StAX attributes converted to org.xml.sax.Attributes + */ + private Attributes getAttributes(XMLStreamReader reader) { + assert reader.getEventType() == XMLStreamConstants.START_ELEMENT; + + AttributesImpl attrs = new AttributesImpl(); + + // add namespace declarations if required + if (namespacePrefixes) { + for (int i = 0; i < reader.getNamespaceCount(); i++) { + String prefix = reader.getNamespacePrefix(i); + String uri = reader.getNamespaceURI(i); + attrs.addAttribute(null, prefix, "xmlns:" + prefix, "CDATA", uri); + } + } + + // Regular attributes + for (int i = 0; i < reader.getAttributeCount(); i++) { + String uri = reader.getAttributeNamespace(i); + if (uri == null) { + uri = ""; + } + String localName = reader.getAttributeLocalName(i); + String prefix = reader.getAttributePrefix(i); + String qname; + if (prefix == null || prefix.length() == 0) { + qname = localName; + } else { + qname = prefix + ':' + localName; + } + String type = reader.getAttributeType(i); + String value = reader.getAttributeValue(i); + + attrs.addAttribute(uri, localName, qname, type, value); + } + + return attrs; + } + + /** + * Adaptor for mapping Locator information. + */ + private static final class LocatorAdaptor implements Locator { + private final Location location; + + private LocatorAdaptor(Location location) { + this.location = location; + } + + public int getColumnNumber() { + return location == null ? 0 : location.getColumnNumber(); + } + + public int getLineNumber() { + return location == null ? 0 : location.getLineNumber(); + } + + public String getPublicId() { + return location == null ? "" : location.getPublicId(); + } + + public String getSystemId() { + return location == null ? "" : location.getSystemId(); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAXHelper.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAXHelper.java new file mode 100755 index 0000000000..db0eae165f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StAXHelper.java @@ -0,0 +1,820 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import java.util.NoSuchElementException; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.transform.Source; + +public final class StAXHelper { + + private static final XMLInputFactory INPUT_FACTORY = XMLInputFactory.newInstance(); + + private static final XMLOutputFactory OUTPUT_FACTORY = XMLOutputFactory.newInstance(); + + private StAXHelper() { + } + + /** + * This class is derived from Apache Axis2 class + * org.apache.axis2.util.StreamWrapper</a>. It's used wrap a + * XMLStreamReader to create a XMLStreamReader representing a document and + * it will produce START_DOCUMENT, END_DOCUMENT events. + */ + public static class XMLDocumentStreamReader implements XMLStreamReader { + private static final int STATE_COMPLETE_AT_NEXT = 2; // The wrapper + // will produce + // END_DOCUMENT + + private static final int STATE_COMPLETED = 3; // Done + + private static final int STATE_INIT = 0; // The wrapper will produce + // START_DOCUMENT + + private static final int STATE_SWITCHED = 1; // The real reader will + // produce events + + private XMLStreamReader realReader; + + private int state = STATE_INIT; + + public XMLDocumentStreamReader(XMLStreamReader realReader) { + if (realReader == null) { + throw new UnsupportedOperationException("Reader cannot be null"); + } + + this.realReader = realReader; + + // If the real reader is positioned at START_DOCUMENT, always use + // the real reader + if (realReader.getEventType() == START_DOCUMENT) { + state = STATE_SWITCHED; + } + } + + public void close() throws XMLStreamException { + realReader.close(); + } + + public int getAttributeCount() { + if (isDelegating()) { + return realReader.getAttributeCount(); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeLocalName(int i) { + if (isDelegating()) { + return realReader.getAttributeLocalName(i); + } else { + throw new IllegalStateException(); + } + } + + public QName getAttributeName(int i) { + if (isDelegating()) { + return realReader.getAttributeName(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeNamespace(int i) { + if (isDelegating()) { + return realReader.getAttributeNamespace(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributePrefix(int i) { + if (isDelegating()) { + return realReader.getAttributePrefix(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeType(int i) { + if (isDelegating()) { + return realReader.getAttributeType(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeValue(int i) { + if (isDelegating()) { + return realReader.getAttributeValue(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeValue(String s, String s1) { + if (isDelegating()) { + return realReader.getAttributeValue(s, s1); + } else { + throw new IllegalStateException(); + } + } + + public String getCharacterEncodingScheme() { + return realReader.getCharacterEncodingScheme(); + } + + public String getElementText() throws XMLStreamException { + if (isDelegating()) { + return realReader.getElementText(); + } else { + throw new XMLStreamException(); + } + } + + public String getEncoding() { + return realReader.getEncoding(); + } + + public int getEventType() { + int event = -1; + switch (state) { + case STATE_SWITCHED: + case STATE_COMPLETE_AT_NEXT: + event = realReader.getEventType(); + break; + case STATE_INIT: + event = START_DOCUMENT; + break; + case STATE_COMPLETED: + event = END_DOCUMENT; + break; + } + return event; + } + + public String getLocalName() { + if (isDelegating()) { + return realReader.getLocalName(); + } else { + throw new IllegalStateException(); + } + } + + public Location getLocation() { + if (isDelegating()) { + return realReader.getLocation(); + } else { + return null; + } + } + + public QName getName() { + if (isDelegating()) { + return realReader.getName(); + } else { + throw new IllegalStateException(); + } + } + + public NamespaceContext getNamespaceContext() { + return realReader.getNamespaceContext(); + } + + public int getNamespaceCount() { + if (isDelegating()) { + return realReader.getNamespaceCount(); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespacePrefix(int i) { + if (isDelegating()) { + return realReader.getNamespacePrefix(i); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespaceURI() { + if (isDelegating()) { + return realReader.getNamespaceURI(); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespaceURI(int i) { + if (isDelegating()) { + return realReader.getNamespaceURI(i); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespaceURI(String s) { + if (isDelegating()) { + return realReader.getNamespaceURI(s); + } else { + throw new IllegalStateException(); + } + } + + public String getPIData() { + if (isDelegating()) { + return realReader.getPIData(); + } else { + throw new IllegalStateException(); + } + } + + public String getPITarget() { + if (isDelegating()) { + return realReader.getPITarget(); + } else { + throw new IllegalStateException(); + } + } + + public String getPrefix() { + if (isDelegating()) { + return realReader.getPrefix(); + } else { + throw new IllegalStateException(); + } + } + + public Object getProperty(String s) throws IllegalArgumentException { + if (isDelegating()) { + return realReader.getProperty(s); + } else { + throw new IllegalArgumentException(); + } + } + + public String getText() { + if (isDelegating()) { + return realReader.getText(); + } else { + throw new IllegalStateException(); + } + } + + public char[] getTextCharacters() { + if (isDelegating()) { + return realReader.getTextCharacters(); + } else { + throw new IllegalStateException(); + } + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + if (isDelegating()) { + return realReader.getTextCharacters(i, chars, i1, i2); + } else { + throw new IllegalStateException(); + } + } + + public int getTextLength() { + if (isDelegating()) { + return realReader.getTextLength(); + } else { + throw new IllegalStateException(); + } + } + + public int getTextStart() { + if (isDelegating()) { + return realReader.getTextStart(); + } else { + throw new IllegalStateException(); + } + } + + public String getVersion() { + if (isDelegating()) { + return realReader.getVersion(); + } else { + return null; + } + } + + public boolean hasName() { + if (isDelegating()) { + return realReader.hasName(); + } else { + return false; + } + } + + public boolean hasNext() throws XMLStreamException { + if (state == STATE_COMPLETE_AT_NEXT) { + return true; + } else if (state == STATE_COMPLETED) { + return false; + } else if (state == STATE_SWITCHED) { + return realReader.hasNext(); + } else { + return true; + } + } + + public boolean hasText() { + if (isDelegating()) { + return realReader.hasText(); + } else { + return false; + } + } + + public boolean isAttributeSpecified(int i) { + if (isDelegating()) { + return realReader.isAttributeSpecified(i); + } else { + return false; + } + } + + public boolean isCharacters() { + if (isDelegating()) { + return realReader.isCharacters(); + } else { + return false; + } + } + + private boolean isDelegating() { + return state == STATE_SWITCHED || state == STATE_COMPLETE_AT_NEXT; + } + + public boolean isEndElement() { + if (isDelegating()) { + return realReader.isEndElement(); + } else { + return false; + } + } + + public boolean isStandalone() { + if (isDelegating()) { + return realReader.isStandalone(); + } else { + return false; + } + } + + public boolean isStartElement() { + if (isDelegating()) { + return realReader.isStartElement(); + } else { + return false; + } + } + + public boolean isWhiteSpace() { + if (isDelegating()) { + return realReader.isWhiteSpace(); + } else { + return false; + } + } + + public int next() throws XMLStreamException { + int returnEvent = -1; + + switch (state) { + case STATE_SWITCHED: + returnEvent = realReader.next(); + if (returnEvent == END_DOCUMENT) { + state = STATE_COMPLETED; + } else if (!realReader.hasNext()) { + state = STATE_COMPLETE_AT_NEXT; + } + break; + case STATE_INIT: + state = STATE_SWITCHED; + returnEvent = realReader.getEventType(); + break; + case STATE_COMPLETE_AT_NEXT: + state = STATE_COMPLETED; + returnEvent = END_DOCUMENT; + break; + case STATE_COMPLETED: + // oops - no way we can go beyond this + throw new NoSuchElementException("End of stream has reached."); + default: + throw new UnsupportedOperationException(); + } + + return returnEvent; + } + + public int nextTag() throws XMLStreamException { + if (isDelegating()) { + return realReader.nextTag(); + } else { + throw new XMLStreamException(); + } + } + + public void require(int i, String s, String s1) throws XMLStreamException { + if (isDelegating()) { + realReader.require(i, s, s1); + } + } + + public boolean standaloneSet() { + if (isDelegating()) { + return realReader.standaloneSet(); + } else { + return false; + } + } + } + + public static interface XMLFragmentStreamReader extends XMLStreamReader { + + // this will help to handle Text within the current element. + // user should pass the element text to the property list as this + // ELEMENT_TEXT as the key. This key deliberately has a space in it + // so that it is not a valid XML name + String ELEMENT_TEXT = "Element Text"; + + /** + * Initiate the parser - this will do whatever the needed tasks to + * initiate the parser and must be called before attempting any specific + * parsing using this parser + */ + void init(); + + /** + * Extra method to query the state of the pullparser + * + * @return + */ + boolean isEndOfFragment(); + + /** + * add the parent namespace context to this parser + */ + void setParentNamespaceContext(NamespaceContext nsContext); + } + + /** + * The XMLStreamSerializer pulls events from the XMLStreamReader and dumps + * into the XMLStreamWriter + */ + public static class XMLStreamSerializer implements XMLStreamConstants { + + public static final String NAMESPACE_PREFIX = "ns"; + + private static int namespaceSuffix = 0; + + /* + * The behavior of the serializer is such that it returns when it + * encounters the starting element for the second time. The depth + * variable tracks the depth of the serilizer and tells it when to + * return. Note that it is assumed that this serialization starts on an + * Element. + */ + + /** + * Field depth + */ + private int depth = 0; + + /** + * Generates a unique namespace prefix that is not in the scope of the + * NamespaceContext + * + * @param nsCtxt + * @return string + */ + private String generateUniquePrefix(NamespaceContext nsCtxt) { + String prefix = NAMESPACE_PREFIX + namespaceSuffix++; + // null should be returned if the prefix is not bound! + while (nsCtxt.getNamespaceURI(prefix) != null) { + prefix = NAMESPACE_PREFIX + namespaceSuffix++; + } + + return prefix; + } + + /** + * Method serialize. + * + * @param node + * @param writer + * @throws XMLStreamException + */ + public void serialize(XMLStreamReader node, XMLStreamWriter writer) throws XMLStreamException { + serializeNode(node, writer); + } + + /** + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeAttributes(XMLStreamReader reader, XMLStreamWriter writer) + throws XMLStreamException { + int count = reader.getAttributeCount(); + String prefix = null; + String namespaceName = null; + String writerPrefix = null; + for (int i = 0; i < count; i++) { + prefix = reader.getAttributePrefix(i); + namespaceName = reader.getAttributeNamespace(i); + /* + * Due to parser implementations returning null as the namespace + * URI (for the empty namespace) we need to make sure that we + * deal with a namespace name that is not null. The best way to + * work around this issue is to set the namespace uri to "" if + * it is null + */ + if (namespaceName == null) { + namespaceName = ""; + } + + writerPrefix = writer.getNamespaceContext().getPrefix(namespaceName); + + if (!"".equals(namespaceName)) { + // prefix has already being declared but this particular + // attrib has a + // no prefix attached. So use the prefix provided by the + // writer + if (writerPrefix != null && (prefix == null || prefix.equals(""))) { + writer.writeAttribute(writerPrefix, + namespaceName, + reader.getAttributeLocalName(i), + reader.getAttributeValue(i)); + + // writer prefix is available but different from the + // current + // prefix of the attrib. We should be decalring the new + // prefix + // as a namespace declaration + } else if (prefix != null && !"".equals(prefix) && !prefix.equals(writerPrefix)) { + writer.writeNamespace(prefix, namespaceName); + writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader + .getAttributeValue(i)); + + // prefix is null (or empty), but the namespace name is + // valid! it has not + // being written previously also. So we need to generate + // a prefix + // here + } else if (prefix == null || prefix.equals("")) { + prefix = generateUniquePrefix(writer.getNamespaceContext()); + writer.writeNamespace(prefix, namespaceName); + writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader + .getAttributeValue(i)); + } else { + writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader + .getAttributeValue(i)); + } + } else { + // empty namespace is equal to no namespace! + writer.writeAttribute(reader.getAttributeLocalName(i), reader.getAttributeValue(i)); + } + + } + } + + /** + * Method serializeCData. + * + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeCData(XMLStreamReader reader, XMLStreamWriter writer) + throws XMLStreamException { + writer.writeCData(reader.getText()); + } + + /** + * Method serializeComment. + * + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeComment(XMLStreamReader reader, XMLStreamWriter writer) + throws XMLStreamException { + writer.writeComment(reader.getText()); + } + + /** + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeElement(XMLStreamReader reader, XMLStreamWriter writer) + throws XMLStreamException { + String prefix = reader.getPrefix(); + String nameSpaceName = reader.getNamespaceURI(); + if (nameSpaceName != null) { + String writerPrefix = writer.getPrefix(nameSpaceName); + if (writerPrefix != null) { + writer.writeStartElement(nameSpaceName, reader.getLocalName()); + } else { + if (prefix != null) { + writer.writeStartElement(prefix, reader.getLocalName(), nameSpaceName); + writer.writeNamespace(prefix, nameSpaceName); + writer.setPrefix(prefix, nameSpaceName); + } else { + writer.writeStartElement(nameSpaceName, reader.getLocalName()); + writer.writeDefaultNamespace(nameSpaceName); + writer.setDefaultNamespace(nameSpaceName); + } + } + } else { + writer.writeStartElement(reader.getLocalName()); + } + + // add the namespaces + int count = reader.getNamespaceCount(); + String namespacePrefix; + for (int i = 0; i < count; i++) { + namespacePrefix = reader.getNamespacePrefix(i); + if (namespacePrefix != null && namespacePrefix.length() == 0) { + continue; + } + + serializeNamespace(namespacePrefix, reader.getNamespaceURI(i), writer); + } + + // add attributes + serializeAttributes(reader, writer); + + } + + /** + * Method serializeEndElement. + * + * @param writer + * @throws XMLStreamException + */ + protected void serializeEndElement(XMLStreamWriter writer) throws XMLStreamException { + writer.writeEndElement(); + } + + /** + * Method serializeNamespace. + * + * @param prefix + * @param uri + * @param writer + * @throws XMLStreamException + */ + private void serializeNamespace(String prefix, String uri, XMLStreamWriter writer) + throws XMLStreamException { + String prefix1 = writer.getPrefix(uri); + if (prefix1 == null) { + writer.writeNamespace(prefix, uri); + writer.setPrefix(prefix, uri); + } + } + + /** + * Method serializeNode. + * + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeNode(XMLStreamReader reader, XMLStreamWriter writer) + throws XMLStreamException { + // TODO We get the StAXWriter at this point and uses it hereafter + // assuming that this is the only entry point + // to this class. + // If there can be other classes calling methodes of this we might + // need to change methode signatures to + // OMOutputer + while (reader.hasNext()) { + int event = reader.next(); + if (event == START_ELEMENT) { + serializeElement(reader, writer); + depth++; + } else if (event == ATTRIBUTE) { + serializeAttributes(reader, writer); + } else if (event == CHARACTERS) { + serializeText(reader, writer); + } else if (event == COMMENT) { + serializeComment(reader, writer); + } else if (event == CDATA) { + serializeCData(reader, writer); + } else if (event == END_ELEMENT) { + serializeEndElement(writer); + depth--; + } else if (event == START_DOCUMENT) { + depth++; // if a start document is found then increment + // the depth + } else if (event == END_DOCUMENT) { + if (depth != 0) { + depth--; // for the end document - reduce the depth + } + try { + serializeEndElement(writer); + } catch (Exception e) { + // TODO: log exceptions + } + } + if (depth == 0) { + break; + } + } + } + + /** + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeText(XMLStreamReader reader, XMLStreamWriter writer) + throws XMLStreamException { + writer.writeCharacters(reader.getText()); + } + } + + public static XMLStreamReader createXMLStreamReader(InputStream inputStream) throws XMLStreamException { + XMLStreamReader streamReader = INPUT_FACTORY.createXMLStreamReader(inputStream); + return streamReader; + } + + public static XMLStreamReader createXMLStreamReader(Reader reader) throws XMLStreamException { + XMLStreamReader streamReader = INPUT_FACTORY.createXMLStreamReader(reader); + return streamReader; + } + + public static XMLStreamReader createXMLStreamReader(Source source) throws XMLStreamException { + XMLStreamReader reader = INPUT_FACTORY.createXMLStreamReader(source); + return reader; + } + + public static XMLStreamReader createXMLStreamReader(String string) throws XMLStreamException { + StringReader reader = new StringReader(string); + return createXMLStreamReader(reader); + } + + public static String save(XMLStreamReader reader) throws XMLStreamException { + StringWriter writer = new StringWriter(); + save(reader, writer); + return writer.toString(); + } + + public static void save(XMLStreamReader reader, OutputStream outputStream) throws XMLStreamException { + XMLStreamSerializer serializer = new XMLStreamSerializer(); + XMLStreamWriter streamWriter = OUTPUT_FACTORY.createXMLStreamWriter(outputStream); + serializer.serialize(reader, streamWriter); + streamWriter.flush(); + } + + public static void save(XMLStreamReader reader, Writer writer) throws XMLStreamException { + XMLStreamSerializer serializer = new XMLStreamSerializer(); + XMLStreamWriter streamWriter = OUTPUT_FACTORY.createXMLStreamWriter(writer); + serializer.serialize(reader, streamWriter); + streamWriter.flush(); + } + + public static void save(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + XMLStreamSerializer serializer = new XMLStreamSerializer(); + serializer.serialize(reader, writer); + writer.flush(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StreamDataPipe.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StreamDataPipe.java new file mode 100755 index 0000000000..d0b6ce07f2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/StreamDataPipe.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.tuscany.spi.databinding.DataPipe; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; + +@Service(Transformer.class) +public class StreamDataPipe extends TransformerExtension<OutputStream, InputStream> implements + DataPipe<OutputStream, InputStream> { + + private ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + public InputStream getResult() { + return new ByteArrayInputStream(outputStream.toByteArray()); + } + + public Class getTargetType() { + return InputStream.class; + } + + public int getWeight() { + return 50; + } + + public OutputStream getSink() { + return outputStream; + } + + public Class getSourceType() { + return OutputStream.class; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2Node.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2Node.java new file mode 100755 index 0000000000..3f878a07b9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2Node.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.StringReader; + +import javax.xml.parsers.DocumentBuilder; + +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.DOMHelper; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +@Service(Transformer.class) +public class String2Node extends TransformerExtension<String, Node> implements PullTransformer<String, Node> { + + public Node transform(String source, TransformationContext context) { + try { + DocumentBuilder builder = DOMHelper.newDocumentBuilder(); + InputSource inputSource = new InputSource(new StringReader(source)); + return builder.parse(inputSource); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return String.class; + } + + public Class getTargetType() { + return Node.class; + } + + public int getWeight() { + return 50; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2SAX.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2SAX.java new file mode 100644 index 0000000000..50ea110b17 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2SAX.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import java.io.StringReader; + +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; + +/** + * Transform XML string to SAX + */ +@Service(Transformer.class) +public class String2SAX extends TransformerExtension<String, ContentHandler> implements + PushTransformer<String, ContentHandler> { + + public void transform(String source, ContentHandler target, TransformationContext context) { + try { + new InputSource2SAX().transform(new InputSource(new StringReader(source)), target, context); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return String.class; + } + + public Class getTargetType() { + return ContentHandler.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2XMLStreamReader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2XMLStreamReader.java new file mode 100755 index 0000000000..9793cc3f7e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/String2XMLStreamReader.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; + +@Service(Transformer.class) +public class String2XMLStreamReader extends TransformerExtension<String, XMLStreamReader> implements + PullTransformer<String, XMLStreamReader> { + + public XMLStreamReader transform(String source, TransformationContext context) { + try { + return StAXHelper.createXMLStreamReader(source); + } catch (XMLStreamException e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return String.class; + } + + public Class getTargetType() { + return XMLStreamReader.class; + } + + public int getWeight() { + return 50; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Writer2ReaderDataPipe.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Writer2ReaderDataPipe.java new file mode 100755 index 0000000000..c66d0fd934 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/Writer2ReaderDataPipe.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.core.databinding.xml; + +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; + +import org.apache.tuscany.spi.databinding.DataPipe; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; + +@Service(Transformer.class) +public class Writer2ReaderDataPipe extends TransformerExtension<Writer, Reader> implements DataPipe<Writer, Reader> { + + private StringWriter writer = new StringWriter(); + + public Reader getResult() { + return new StringReader(writer.toString()); + } + + public Class getTargetType() { + return Reader.class; + } + + public int getWeight() { + return 50; + } + + public Writer getSink() { + return writer; + } + + public Class getSourceType() { + return Writer.class; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2Node.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2Node.java new file mode 100644 index 0000000000..6ecaa85be4 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2Node.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; + +/** + * Transform DOM Node to XML XMLStreamReader + */ +@Service(Transformer.class) +public class XMLStreamReader2Node extends TransformerExtension<XMLStreamReader, Node> implements + PullTransformer<XMLStreamReader, Node> { + private SAX2DOMPipe pipe = new SAX2DOMPipe(); + + private XMLStreamReader2SAX stax2sax = new XMLStreamReader2SAX(); + + public Node transform(XMLStreamReader source, TransformationContext context) { + try { + stax2sax.transform(source, pipe.getSink(), context); + return pipe.getResult(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return XMLStreamReader.class; + } + + public Class getTargetType() { + return Node.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2SAX.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2SAX.java new file mode 100644 index 0000000000..0c6f0b8df7 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2SAX.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.databinding.PushTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; +import org.xml.sax.ContentHandler; + +/** + * XMLStreamReader to SAX events + */ +@Service(Transformer.class) +public class XMLStreamReader2SAX extends TransformerExtension<XMLStreamReader, ContentHandler> implements + PushTransformer<XMLStreamReader, ContentHandler> { + + /** + * @see org.apache.tuscany.spi.databinding.PushTransformer#getSourceType() + */ + public Class getTargetType() { + return ContentHandler.class; + } + + /** + * @see org.apache.tuscany.spi.databinding.PushTransformer#getSourceType() + */ + public Class getSourceType() { + return XMLStreamReader.class; + } + + /** + * @see org.apache.tuscany.spi.databinding.PushTransformer#getWeight() + */ + public int getWeight() { + return 20; + } + + /** + * @see org.apache.tuscany.spi.databinding.PushTransformer#transform(java.lang.Object, + * java.lang.Object, + * org.apache.tuscany.spi.databinding.TransformationContext) + */ + public void transform(XMLStreamReader source, ContentHandler sink, TransformationContext context) { + StAX2SAXAdapter adapter = new StAX2SAXAdapter(false); + try { + adapter.parse(source, sink); + } catch (Exception e) { + throw new TransformationException(e); + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2String.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2String.java new file mode 100755 index 0000000000..85ac7b5af6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamReader2String.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.databinding.PullTransformer; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformationException; +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.extension.TransformerExtension; +import org.osoa.sca.annotations.Service; + +@Service(Transformer.class) +public class XMLStreamReader2String extends TransformerExtension<XMLStreamReader, String> implements + PullTransformer<XMLStreamReader, String> { + + public String transform(XMLStreamReader source, TransformationContext context) { + try { + return StAXHelper.save(source); + } catch (XMLStreamException e) { + throw new TransformationException(e); + } + } + + public Class getSourceType() { + return XMLStreamReader.class; + } + + public Class getTargetType() { + return String.class; + } + + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStringDataBinding.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStringDataBinding.java new file mode 100644 index 0000000000..39e9362524 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStringDataBinding.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.core.databinding.xml; + +import org.apache.tuscany.spi.databinding.extension.DataBindingExtension; + +/** + * A DataBinding for the XML string + */ +public class XMLStringDataBinding extends DataBindingExtension { + public static final String NAME = String.class.getName(); + + public XMLStringDataBinding() { + super(NAME, String.class); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/AbstractDeploymentContext.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/AbstractDeploymentContext.java new file mode 100644 index 0000000000..c931cccde9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/AbstractDeploymentContext.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.deployer; + +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.deployer.DeploymentContext; + +/** + * Base class for DeploymentContext implementations. + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractDeploymentContext implements DeploymentContext { + private final ClassLoader classLoader; + private final URL scdlLocation; + private final Map<String, Object> properties = new HashMap<String, Object>(); + + protected AbstractDeploymentContext(ClassLoader classLoader, URL scdlLocation) { + this.classLoader = classLoader; + this.scdlLocation = scdlLocation; + } + + public ClassLoader getClassLoader() { + return classLoader; + } + + public URL getScdlLocation() { + return scdlLocation; + } + + public Object getExtension(String name) { + return properties.get(name); + } + + public void putExtension(String name, Object value) { + if (value == null) { + properties.remove(name); + } else { + properties.put(name, value); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/ChildDeploymentContext.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/ChildDeploymentContext.java new file mode 100644 index 0000000000..10bb5a4609 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/ChildDeploymentContext.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.deployer; + +import java.net.URL; +import javax.xml.stream.XMLInputFactory; + +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.deployer.DeploymentContext; + +/** + * An holder that can be used during the load process to store information that is not part of the logical assembly + * model. This should be regarded as transient and references to this context should not be stored inside the model. + * + * @version $Rev$ $Date$ + */ +public class ChildDeploymentContext extends AbstractDeploymentContext { + private final DeploymentContext parent; + + /** + * Constructor specifying the loader for application resources. + * + * @param parent the parent of this context + * @param classLoader the loader for application resources + * @param scdlLocation the location of the SCDL being deployed + */ + public ChildDeploymentContext(DeploymentContext parent, ClassLoader classLoader, URL scdlLocation) { + super(classLoader, scdlLocation); + assert parent != null; + this.parent = parent; + } + + public DeploymentContext getParent() { + return parent; + } + + public XMLInputFactory getXmlFactory() { + return parent.getXmlFactory(); + } + + public ScopeContainer getModuleScope() { + return parent.getModuleScope(); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/DeployerImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/DeployerImpl.java new file mode 100644 index 0000000000..e5556292da --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/DeployerImpl.java @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.deployer; + +import javax.xml.stream.XMLInputFactory; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.builder.Builder; +import org.apache.tuscany.spi.builder.BuilderRegistry; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.deployer.Deployer; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.loader.Loader; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.Implementation; + +import org.apache.tuscany.core.component.scope.ModuleScopeContainer; + +/** + * Default implementation of Deployer. + * + * @version $Rev$ $Date$ + */ +public class DeployerImpl implements Deployer { + private XMLInputFactory xmlFactory; + private Loader loader; + private Builder builder; + + public DeployerImpl(XMLInputFactory xmlFactory, Loader loader, Builder builder) { + this.xmlFactory = xmlFactory; + this.loader = loader; + this.builder = builder; + } + + public DeployerImpl() { + xmlFactory = XMLInputFactory.newInstance("javax.xml.stream.XMLInputFactory", getClass().getClassLoader()); + } + + @Autowire + public void setLoader(LoaderRegistry loader) { + this.loader = loader; + } + + @Autowire + public void setBuilder(BuilderRegistry builder) { + this.builder = builder; + } + + public <I extends Implementation<?>> Component deploy(CompositeComponent parent, + ComponentDefinition<I> componentDefinition) + throws LoaderException { + ScopeContainer moduleScope = new ModuleScopeContainer(); + DeploymentContext deploymentContext = new RootDeploymentContext(null, xmlFactory, moduleScope, null); + try { + load(parent, componentDefinition, deploymentContext); + } catch (LoaderException e) { + e.addContextName(componentDefinition.getName()); + throw e; + } + Component component = (Component) build(parent, componentDefinition, deploymentContext); + if (component instanceof CompositeComponent) { + CompositeComponent composite = (CompositeComponent) component; + composite.setScopeContainer(moduleScope); + } + component.prepare(); + parent.register(component); + return component; + } + + /** + * Load the componentDefinition type information for the componentDefinition being deployed. For a typical + * deployment this will result in the SCDL definition being loaded. + * + * @param componentDefinition the componentDefinition being deployed + * @param deploymentContext the current deployment context + */ + protected <I extends Implementation<?>> void load(CompositeComponent parent, + ComponentDefinition<I> componentDefinition, + DeploymentContext deploymentContext) throws LoaderException { + loader.loadComponentType(parent, componentDefinition.getImplementation(), deploymentContext); + } + + /** + * Build the runtime context for a loaded componentDefinition. + * + * @param parent the context that will be the parent of the new sub-context + * @param componentDefinition the componentDefinition being deployed + * @param deploymentContext the current deployment context + * @return the new runtime context + */ + protected <I extends Implementation<?>> SCAObject build(CompositeComponent parent, + ComponentDefinition<I> componentDefinition, + DeploymentContext deploymentContext) { + return builder.build(parent, componentDefinition, deploymentContext); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/RootDeploymentContext.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/RootDeploymentContext.java new file mode 100644 index 0000000000..cc3ae86cc8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/deployer/RootDeploymentContext.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.deployer; + +import java.net.URL; +import javax.xml.stream.XMLInputFactory; + +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.deployer.DeploymentContext; + +/** + * A holder that can be used during the load process to store information that is not part of the logical assembly + * model. This should be regarded as transient and references to this context should not be stored inside the model. + * + * @version $Rev$ $Date$ + */ +public class RootDeploymentContext extends AbstractDeploymentContext { + private final XMLInputFactory xmlFactory; + private final ScopeContainer moduleScope; + + /** + * Constructor specifying the loader for application resources. + * + * @param classLoader the loader for application resources + * @param xmlFactory a factory that can be used to obtain an StAX XMLStreamReader + * @param moduleScope the scope context representing this deployment's MODULE scope + * @param scdlLocation the location of the SCDL being deployed + */ + public RootDeploymentContext(ClassLoader classLoader, + XMLInputFactory xmlFactory, + ScopeContainer moduleScope, + URL scdlLocation) { + super(classLoader, scdlLocation); + this.xmlFactory = xmlFactory; + this.moduleScope = moduleScope; + } + + public DeploymentContext getParent() { + return null; + } + + public XMLInputFactory getXmlFactory() { + return xmlFactory; + } + + public ScopeContainer getModuleScope() { + return moduleScope; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/IllegalCallbackException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/IllegalCallbackException.java new file mode 100644 index 0000000000..45741e828b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/IllegalCallbackException.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.core.idl.java; + +import org.apache.tuscany.spi.idl.InvalidServiceContractException; + +/** + * Denotes an illegal callback interface + * + * @version $Rev$ $Date$ + */ + +public class IllegalCallbackException extends InvalidServiceContractException { + public IllegalCallbackException() { + } + + public IllegalCallbackException(String message) { + super(message); + } + + public IllegalCallbackException(String message, Throwable cause) { + super(message, cause); + } + + public IllegalCallbackException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/InterfaceJavaLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/InterfaceJavaLoader.java new file mode 100644 index 0000000000..057928ed31 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/InterfaceJavaLoader.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.core.idl.java; + +import java.util.HashMap; +import java.util.Map; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import static org.osoa.sca.Version.XML_NAMESPACE_1_0; +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.loader.InvalidValueException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.LoaderUtil; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.InteractionScope; +import org.apache.tuscany.spi.model.ModelObject; + +import org.apache.tuscany.core.loader.StAXUtil; + +/** + * Loads a Java interface definition from an XML-based assembly file + * + * @version $Rev$ $Date$ + */ +public class InterfaceJavaLoader extends LoaderExtension<JavaServiceContract> { + public static final QName INTERFACE_JAVA = new QName(XML_NAMESPACE_1_0, "interface.java"); + + private final JavaInterfaceProcessorRegistry interfaceRegsitry; + + @Constructor({"registry", "interfaceRegsitry"}) + public InterfaceJavaLoader(@Autowire LoaderRegistry registry, + @Autowire JavaInterfaceProcessorRegistry interfaceRegistry) { + super(registry); + this.interfaceRegsitry = interfaceRegistry; + } + + public QName getXMLType() { + return INTERFACE_JAVA; + } + + public JavaServiceContract load(CompositeComponent parent, + XMLStreamReader reader, + DeploymentContext deploymentContext) + throws XMLStreamException, LoaderException { + + assert INTERFACE_JAVA.equals(reader.getName()); + InteractionScope interactionScope = StAXUtil.interactionScope(reader.getAttributeValue(null, "scope")); + String name = reader.getAttributeValue(null, "interface"); + if (name == null) { + // allow "class" as well as seems to be a common mistake + name = reader.getAttributeValue(null, "class"); + } + if (name == null) { + throw new InvalidValueException("interface name not supplied"); + } + Class<?> interfaceClass = LoaderUtil.loadClass(name, deploymentContext.getClassLoader()); + + name = reader.getAttributeValue(null, "callbackInterface"); + Class<?> callbackClass = (name != null) ? LoaderUtil.loadClass(name, deploymentContext.getClassLoader()) : null; + + Map<Class<?>, ModelObject> extensions = new HashMap<Class<?>, ModelObject>(); + while (true) { + int event = reader.next(); + if (event == XMLStreamConstants.START_ELEMENT) { + ModelObject mo = registry.load(parent, reader, deploymentContext); + if (mo != null) { + extensions.put(mo.getClass(), mo); + } + } else if (event == XMLStreamConstants.END_ELEMENT && reader.getName().equals(INTERFACE_JAVA)) { + break; + } + } + JavaServiceContract serviceContract; + try { + serviceContract = interfaceRegsitry.introspect(interfaceClass, callbackClass); + } catch (InvalidServiceContractException e) { + LoaderException le = new LoaderException(e); + le.setIdentifier(interfaceClass.getName()); + throw le; + } + + // Set databinding from the SCDL extension <databinding> + DataType<?> dataType = (DataType<?>) extensions.get(DataType.class); + if (dataType != null) { + serviceContract.setDataBinding(dataType.getDataBinding()); + } + serviceContract.getExtensions().putAll(extensions); + + serviceContract.setInteractionScope(interactionScope); + return serviceContract; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/JavaInterfaceProcessorRegistryImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/JavaInterfaceProcessorRegistryImpl.java new file mode 100644 index 0000000000..b0df6d0844 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/idl/java/JavaInterfaceProcessorRegistryImpl.java @@ -0,0 +1,145 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.idl.java; + +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.osoa.sca.annotations.Callback; +import org.osoa.sca.annotations.OneWay; +import org.osoa.sca.annotations.Remotable; +import org.osoa.sca.annotations.Scope; + +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.OverloadedOperationException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessor; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.InteractionScope; +import org.apache.tuscany.spi.model.Operation; + +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getBaseName; + +/** + * Default implementation of an InterfaceJavaIntrospector. + * + * @version $Rev$ $Date$ + */ +public class JavaInterfaceProcessorRegistryImpl implements JavaInterfaceProcessorRegistry { + + public static final String IDL_INPUT = "idl:input"; + private static final String UNKNOWN_DATABINDING = null; + + private List<JavaInterfaceProcessor> processors = new ArrayList<JavaInterfaceProcessor>(); + + public JavaInterfaceProcessorRegistryImpl() { + } + + public void registerProcessor(JavaInterfaceProcessor processor) { + processors.add(processor); + } + + public void unregisterProcessor(JavaInterfaceProcessor processor) { + processors.remove(processor); + } + + public <T> JavaServiceContract introspect(Class<T> type) throws InvalidServiceContractException { + Class<?> callbackClass = null; + Callback callback = type.getAnnotation(Callback.class); + if (callback != null && !Void.class.equals(callback.value())) { + callbackClass = callback.value(); + } else if (callback != null && Void.class.equals(callback.value())) { + IllegalCallbackException e = new IllegalCallbackException("No callback interface specified on annotation"); + e.setIdentifier(type.getName()); + throw e; + } + return introspect(type, callbackClass); + } + + public <I, C> JavaServiceContract introspect(Class<I> type, Class<C> callback) + throws InvalidServiceContractException { + JavaServiceContract contract = new JavaServiceContract(); + contract.setInterfaceName(getBaseName(type)); + contract.setInterfaceClass(type); + boolean remotable = type.isAnnotationPresent(Remotable.class); + contract.setRemotable(remotable); + contract.setOperations(getOperations(type, remotable)); + + if (callback != null) { + contract.setCallbackName(getBaseName(callback)); + contract.setCallbackClass(callback); + contract.setCallbackOperations(getOperations(callback, remotable)); + } + + Scope interactionScope = type.getAnnotation(Scope.class); + if (interactionScope == null) { + contract.setInteractionScope(InteractionScope.NONCONVERSATIONAL); + } else { + if ("CONVERSATIONAL".equalsIgnoreCase(interactionScope.value())) { + contract.setInteractionScope(InteractionScope.CONVERSATIONAL); + } else { + contract.setInteractionScope(InteractionScope.NONCONVERSATIONAL); + } + } + for (JavaInterfaceProcessor processor : processors) { + processor.visitInterface(type, callback, contract); + } + return contract; + } + + private <T> Map<String, Operation<Type>> getOperations(Class<T> type, boolean remotable) + throws OverloadedOperationException { + Method[] methods = type.getMethods(); + Map<String, Operation<Type>> operations = new HashMap<String, Operation<Type>>(methods.length); + for (Method method : methods) { + String name = method.getName(); + if (remotable && operations.containsKey(name)) { + throw new OverloadedOperationException(method.toString()); + } + + Type returnType = method.getGenericReturnType(); + Type[] paramTypes = method.getGenericParameterTypes(); + Type[] faultTypes = method.getGenericExceptionTypes(); + boolean nonBlocking = method.isAnnotationPresent(OneWay.class); + + DataType<Type> returnDataType = new DataType<Type>(UNKNOWN_DATABINDING, returnType, returnType); + List<DataType<Type>> paramDataTypes = new ArrayList<DataType<Type>>(paramTypes.length); + for (Type paramType : paramTypes) { + paramDataTypes.add(new DataType<Type>(UNKNOWN_DATABINDING, paramType, paramType)); + } + List<DataType<Type>> faultDataTypes = new ArrayList<DataType<Type>>(faultTypes.length); + for (Type faultType : faultTypes) { + faultDataTypes.add(new DataType<Type>(UNKNOWN_DATABINDING, faultType, faultType)); + } + + DataType<List<DataType<Type>>> inputType = + new DataType<List<DataType<Type>>>(IDL_INPUT, Object[].class, paramDataTypes); + Operation<Type> operation = + new Operation<Type>(name, inputType, returnDataType, faultDataTypes, nonBlocking, UNKNOWN_DATABINDING); + operations.put(name, operation); + } + return operations; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/IntrospectionRegistryImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/IntrospectionRegistryImpl.java new file mode 100644 index 0000000000..3dd1328b6a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/IntrospectionRegistryImpl.java @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessor; +import org.apache.tuscany.spi.implementation.java.IntrospectionRegistry; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +import org.apache.tuscany.core.util.JavaIntrospectionHelper; + +/** + * Default implementation of the <code>IntrospectionRegistry</code> + * + * @version $Rev$ $Date$ + */ +public class IntrospectionRegistryImpl implements IntrospectionRegistry { + + private Monitor monitor; + private List<ImplementationProcessor> cache = new ArrayList<ImplementationProcessor>(); + + public IntrospectionRegistryImpl() { + } + + public IntrospectionRegistryImpl(Monitor monitor) { + this.monitor = monitor; + } + + @org.apache.tuscany.api.annotation.Monitor + public void setMonitor(Monitor monitor) { + this.monitor = monitor; + } + + public void registerProcessor(ImplementationProcessor processor) { + monitor.register(processor); + cache.add(processor); + } + + public void unregisterProcessor(ImplementationProcessor processor) { + monitor.unregister(processor); + cache.remove(processor); + } + + public PojoComponentType introspect(CompositeComponent parent, Class<?> clazz, + PojoComponentType<JavaMappedService, JavaMappedReference, + JavaMappedProperty<?>> type, + DeploymentContext context) + throws ProcessingException { + for (ImplementationProcessor processor : cache) { + processor.visitClass(parent, clazz, type, context); + } + + for (Constructor<?> constructor : clazz.getConstructors()) { + for (ImplementationProcessor processor : cache) { + processor.visitConstructor(parent, constructor, type, context); + } + } + + Set<Method> methods = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(clazz); + for (Method method : methods) { + for (ImplementationProcessor processor : cache) { + processor.visitMethod(parent, method, type, context); + } + } + + Set<Field> fields = JavaIntrospectionHelper.getAllPublicAndProtectedFields(clazz); + for (Field field : fields) { + for (ImplementationProcessor processor : cache) { + processor.visitField(parent, field, type, context); + } + } + + Class superClass = clazz.getSuperclass(); + if (superClass != null) { + visitSuperClass(parent, superClass, type, context); + } + + for (ImplementationProcessor processor : cache) { + processor.visitEnd(parent, clazz, type, context); + } + return type; + } + + private void visitSuperClass(CompositeComponent parent, + Class<?> clazz, + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + DeploymentContext context) + throws ProcessingException { + if (!Object.class.equals(clazz)) { + for (ImplementationProcessor processor : cache) { + processor.visitSuperClass(parent, clazz, type, context); + } + clazz = clazz.getSuperclass(); + if (clazz != null) { + visitSuperClass(parent, clazz, type, context); + } + } + } + + public static interface Monitor { + void register(ImplementationProcessor processor); + + void unregister(ImplementationProcessor processor); + + void processing(ImplementationProcessor processor); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoAtomicComponent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoAtomicComponent.java new file mode 100644 index 0000000000..cfa5284efe --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoAtomicComponent.java @@ -0,0 +1,222 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation; + +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.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.extension.AtomicComponentExtension; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.RuntimeWire; + +import org.apache.tuscany.core.injection.ArrayMultiplicityObjectFactory; +import org.apache.tuscany.core.injection.EventInvoker; +import org.apache.tuscany.core.injection.FieldInjector; +import org.apache.tuscany.core.injection.Injector; +import org.apache.tuscany.core.injection.InvalidAccessorException; +import org.apache.tuscany.core.injection.ListMultiplicityObjectFactory; +import org.apache.tuscany.core.injection.MethodInjector; +import org.apache.tuscany.core.injection.NoAccessorException; +import org.apache.tuscany.core.injection.ObjectCallbackException; +import org.apache.tuscany.core.injection.PojoObjectFactory; + +/** + * Base implementation of an {@link org.apache.tuscany.spi.component.AtomicComponent} whose type is a Java class + * + * @version $$Rev$$ $$Date$$ + */ +public abstract class PojoAtomicComponent extends AtomicComponentExtension { + + protected EventInvoker<Object> initInvoker; + protected EventInvoker<Object> destroyInvoker; + protected PojoObjectFactory<?> instanceFactory; + protected List<String> constructorParamNames; + protected List<Class<?>> serviceInterfaces; + protected Map<String, Member> referenceSites; + protected Map<String, Member> propertySites; + protected Map<String, Member> callbackSites; + protected List<Injector<Object>> injectors; + + public PojoAtomicComponent(String name, PojoConfiguration configuration) { + super(name, + configuration.getParent(), + configuration.getScopeContainer(), + configuration.getWireService(), + configuration.getWorkContext(), + configuration.getScheduler(), + configuration.getInitLevel()); + assert configuration.getInstanceFactory() != null : "Object factory was null"; + initInvoker = configuration.getInitInvoker(); + destroyInvoker = configuration.getDestroyInvoker(); + instanceFactory = configuration.getInstanceFactory(); + constructorParamNames = configuration.getConstructorParamNames(); + serviceInterfaces = configuration.getServiceInterfaces(); + injectors = new ArrayList<Injector<Object>>(); + referenceSites = configuration.getReferenceSite() != null ? configuration.getReferenceSite() + : new HashMap<String, Member>(); + propertySites = configuration.getPropertySites() != null ? configuration.getPropertySites() + : new HashMap<String, Member>(); + callbackSites = configuration.getCallbackSite() != null ? configuration.getCallbackSite() + : new HashMap<String, Member>(); + } + + public List<Class<?>> getServiceInterfaces() { + return serviceInterfaces; + } + + public void init(Object instance) throws TargetException { + if (initInvoker != null) { + try { + initInvoker.invokeEvent(instance); + } catch (ObjectCallbackException e) { + TargetException t = new TargetException("Error initializing component instance", e); + t.setIdentifier(getName()); + throw t; + } + } + } + + public void destroy(Object instance) throws TargetException { + if (destroyInvoker != null) { + try { + destroyInvoker.invokeEvent(instance); + } catch (ObjectCallbackException e) { + TargetException t = new TargetException("Error destroying component instance", e); + t.setIdentifier(getName()); + throw t; + } + } + } + + public Object getTargetInstance() throws TargetException { + return scopeContainer.getInstance(this); + } + + public Object createInstance() throws ObjectCreationException { + Object instance = instanceFactory.getInstance(); + // inject the instance with properties and references + for (Injector<Object> injector : injectors) { + injector.inject(instance); + } + return instance; + } + + public void addPropertyFactory(String name, ObjectFactory<?> factory) { + Member member = propertySites.get(name); + if (member instanceof Field) { + injectors.add(new FieldInjector<Object>((Field) member, factory)); + } else if (member instanceof Method) { + injectors.add(new MethodInjector<Object>((Method) member, factory)); + } + // cycle through constructor param names as well + for (int i = 0; i < constructorParamNames.size(); i++) { + if (name.equals(constructorParamNames.get(i))) { + ObjectFactory[] initializerFactories = instanceFactory.getInitializerFactories(); + initializerFactories[i] = factory; + break; + } + } + //FIXME throw an error if no injection site found + } + + protected void onReferenceWire(OutboundWire wire) { + String name = wire.getReferenceName(); + Member member = referenceSites.get(name); + if (member != null) { + injectors.add(createInjector(member, wire)); + } + // cycle through constructor param names as well + for (int i = 0; i < constructorParamNames.size(); i++) { + if (name.equals(constructorParamNames.get(i))) { + ObjectFactory[] initializerFactories = instanceFactory.getInitializerFactories(); + initializerFactories[i] = createWireFactory(wire); + break; + } + } + //TODO error if ref not set on constructor or ref site + } + + public void onReferenceWires(Class<?> multiplicityClass, List<OutboundWire> wires) { + assert wires.size() > 0 : "Wires were empty"; + String referenceName = wires.get(0).getReferenceName(); + Member member = referenceSites.get(referenceName); + if (member == null) { + if (constructorParamNames.contains(referenceName)) { + // injected on the constructor + + } else { + throw new NoAccessorException(referenceName); + } + } + injectors.add(createMultiplicityInjector(member, multiplicityClass, wires)); + //TODO multiplicity for constructor injection + } + + protected Injector<Object> createInjector(Member member, RuntimeWire wire) { + ObjectFactory<?> factory = createWireFactory(wire); + if (member instanceof Field) { + return new FieldInjector<Object>((Field) member, factory); + } else if (member instanceof Method) { + return new MethodInjector<Object>((Method) member, factory); + } else { + InvalidAccessorException e = new InvalidAccessorException("Member must be a field or method"); + e.setIdentifier(member.getName()); + throw e; + } + } + + protected Injector<Object> createMultiplicityInjector(Member member, + Class<?> interfaceType, + List<OutboundWire> wireFactories) { + List<ObjectFactory<?>> factories = new ArrayList<ObjectFactory<?>>(); + for (OutboundWire wire : wireFactories) { + factories.add(createWireFactory(wire)); + } + if (member instanceof Field) { + Field field = (Field) member; + if (field.getType().isArray()) { + return new FieldInjector<Object>(field, new ArrayMultiplicityObjectFactory(interfaceType, factories)); + } else { + return new FieldInjector<Object>(field, new ListMultiplicityObjectFactory(factories)); + } + } else if (member instanceof Method) { + Method method = (Method) member; + if (method.getParameterTypes()[0].isArray()) { + return new MethodInjector<Object>(method, new ArrayMultiplicityObjectFactory(interfaceType, factories)); + } else { + return new MethodInjector<Object>(method, new ListMultiplicityObjectFactory(factories)); + } + } else { + InvalidAccessorException e = new InvalidAccessorException("Member must be a field or method"); + e.setIdentifier(member.getName()); + throw e; + } + } + + protected abstract ObjectFactory<?> createWireFactory(RuntimeWire wire); + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoConfiguration.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoConfiguration.java new file mode 100644 index 0000000000..6a8c80fb05 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/PojoConfiguration.java @@ -0,0 +1,184 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation; + +import java.lang.reflect.Member; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.services.work.WorkScheduler; +import org.apache.tuscany.spi.wire.WireService; + +import org.apache.tuscany.core.injection.EventInvoker; +import org.apache.tuscany.core.injection.Injector; +import org.apache.tuscany.core.injection.PojoObjectFactory; + +/** + * Encapsulates confuration for a Java-based atomic component + * + * @version $Rev$ $Date$ + */ +public class PojoConfiguration { + + private CompositeComponent parent; + private ScopeContainer scopeContainer; + private PojoObjectFactory<?> instanceFactory; + private List<String> constructorParamNames = new ArrayList<String>(); + private int initLevel; + private EventInvoker<Object> initInvoker; + private EventInvoker<Object> destroyInvoker; + private List<Injector> propertyInjectors = new ArrayList<Injector>(); + private Map<String, Member> referenceSites = new HashMap<String, Member>(); + private Map<String, Member> propertySites = new HashMap<String, Member>(); + private Map<String, Member> callbackSites = new HashMap<String, Member>(); + private List<Class<?>> serviceInterfaces = new ArrayList<Class<?>>(); + private WireService wireService; + private WorkContext workContext; + private WorkScheduler scheduler; + + public CompositeComponent getParent() { + return parent; + } + + public void setParent(CompositeComponent parent) { + this.parent = parent; + } + + public ScopeContainer getScopeContainer() { + return scopeContainer; + } + + public void setScopeContainer(ScopeContainer scopeContainer) { + this.scopeContainer = scopeContainer; + } + + public List<Class<?>> getServiceInterfaces() { + return serviceInterfaces; + } + + public void addServiceInterface(Class<?> serviceInterface) { + serviceInterfaces.add(serviceInterface); + } + + public PojoObjectFactory<?> getInstanceFactory() { + return instanceFactory; + } + + public void setInstanceFactory(PojoObjectFactory<?> objectFactory) { + this.instanceFactory = objectFactory; + } + + public List<String> getConstructorParamNames() { + return constructorParamNames; + } + + public void setConstructorParamNames(List<String> names) { + constructorParamNames = names; + } + + public void addConstructorParamName(String name) { + constructorParamNames.add(name); + } + + public int getInitLevel() { + return initLevel; + } + + public void setInitLevel(int initLevel) { + this.initLevel = initLevel; + } + + public EventInvoker<Object> getInitInvoker() { + return initInvoker; + } + + public void setInitInvoker(EventInvoker<Object> initInvoker) { + this.initInvoker = initInvoker; + } + + public EventInvoker<Object> getDestroyInvoker() { + return destroyInvoker; + } + + public void setDestroyInvoker(EventInvoker<Object> destroyInvoker) { + this.destroyInvoker = destroyInvoker; + } + + public List<Injector> getPropertyInjectors() { + return propertyInjectors; + } + + public void addPropertyInjector(Injector injector) { + propertyInjectors.add(injector); + } + + public Map<String, Member> getReferenceSite() { + return referenceSites; + } + + public void addReferenceSite(String name, Member member) { + referenceSites.put(name, member); + } + + public Map<String, Member> getCallbackSite() { + return callbackSites; + } + + public void addCallbackSite(String name, Member member) { + callbackSites.put(name, member); + } + + public Map<String, Member> getPropertySites() { + return propertySites; + } + + public void addPropertySite(String name, Member member) { + propertySites.put(name, member); + } + + public WireService getWireService() { + return wireService; + } + + public void setWireService(WireService wireService) { + this.wireService = wireService; + } + + public WorkContext getWorkContext() { + return workContext; + } + + public void setWorkContext(WorkContext workContext) { + this.workContext = workContext; + } + + public WorkScheduler getScheduler() { + return scheduler; + } + + public void setScheduler(WorkScheduler scheduler) { + this.scheduler = scheduler; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeComponent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeComponent.java new file mode 100644 index 0000000000..7949bf4a71 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeComponent.java @@ -0,0 +1,170 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.w3c.dom.Document; + +import org.apache.tuscany.spi.builder.Connector; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.ObjectRegistrationException; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.event.Event; +import org.apache.tuscany.spi.extension.CompositeComponentExtension; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.TargetInvoker; + +import org.apache.tuscany.core.component.ComponentInitException; +import org.apache.tuscany.core.component.event.CompositeStart; +import org.apache.tuscany.core.component.event.CompositeStop; +import org.apache.tuscany.core.implementation.system.component.SystemSingletonAtomicComponent; + +/** + * The base implementation of a composite context + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractCompositeComponent extends CompositeComponentExtension { + + public static final int DEFAULT_WAIT = 1000 * 60; + + // Blocking latch to ensure the module is initialized exactly once prior to servicing requests + protected CountDownLatch initializeLatch = new CountDownLatch(1); + + protected final Object lock = new Object(); + + // Indicates whether the module context has been initialized + protected boolean initialized; + + protected ScopeContainer scopeContainer; + + + /** + * @param name the name of the SCA composite + * @param parent the SCA composite parent + * @param connector + * @param propertyValues the values of this composite's Properties + */ + public AbstractCompositeComponent(String name, + CompositeComponent parent, + Connector connector, + Map<String, Document> propertyValues) { + super(name, parent, connector, propertyValues); + } + + public void setScopeContainer(ScopeContainer scopeContainer) { + assert this.scopeContainer == null; + this.scopeContainer = scopeContainer; + addListener(scopeContainer); + } + + public <S, I extends S> void registerJavaObject(String name, Class<S> service, I instance) + throws ObjectRegistrationException { + register(new SystemSingletonAtomicComponent<S, I>(name, this, service, instance)); + } + + public void start() { + synchronized (lock) { + if (lifecycleState != UNINITIALIZED && lifecycleState != STOPPED) { + throw new IllegalStateException("Composite not in UNINITIALIZED state"); + } + + if (scopeContainer != null) { + scopeContainer.start(); + } + for (SCAObject child : systemChildren.values()) { + child.start(); + } + for (SCAObject child : children.values()) { + child.start(); + } + initializeLatch.countDown(); + initialized = true; + lifecycleState = INITIALIZED; + } + publish(new CompositeStart(this, this)); + } + + public void stop() { + if (lifecycleState == STOPPED) { + return; + } + + publish(new CompositeStop(this, this)); + for (SCAObject child : children.values()) { + child.stop(); + } + for (SCAObject child : systemChildren.values()) { + child.stop(); + } + if (scopeContainer != null) { + scopeContainer.stop(); + } + + // need to block a start until reset is complete + initializeLatch = new CountDownLatch(2); + lifecycleState = STOPPING; + initialized = false; + // allow initialized to be called + initializeLatch.countDown(); + lifecycleState = STOPPED; + } + + public void publish(Event event) { + if (lifecycleState == STOPPED) { + return; + } + checkInit(); + super.publish(event); + } + + public TargetInvoker createTargetInvoker(String targetName, Operation operation) { + return null; + } + + public TargetInvoker createAsyncTargetInvoker(InboundWire wire, Operation operation) { + return null; + } + + + /** + * Blocks until the module context has been initialized + */ + protected void checkInit() { + if (!initialized) { + try { + /* block until the module has initialized */ + boolean success = initializeLatch.await(AbstractCompositeComponent.DEFAULT_WAIT, + TimeUnit.MILLISECONDS); + if (!success) { + throw new ComponentInitException("Timeout waiting for context to initialize"); + } + } catch (InterruptedException e) { // should not happen + } + } + + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeReferenceTargetInvoker.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeReferenceTargetInvoker.java new file mode 100644 index 0000000000..5ef666be76 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractCompositeReferenceTargetInvoker.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.lang.reflect.InvocationTargetException; + +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.TargetInvoker; + +/** + * Base class for dispatching to a Composite Reference. + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractCompositeReferenceTargetInvoker implements TargetInvoker { + + protected Operation operation; + protected boolean cacheable; + + public AbstractCompositeReferenceTargetInvoker(Operation operation) { + assert operation != null : "Operation method cannot be null"; + this.operation = operation; + } + + public boolean isCacheable() { + return cacheable; + } + + public void setCacheable(boolean cacheable) { + this.cacheable = cacheable; + } + + public boolean isOptimizable() { + return isCacheable(); // we only need to check if the scopes are correct + } + + public Object invokeTarget(final Object payload) throws InvocationTargetException { + Object[] args; + if (payload != null && !payload.getClass().isArray()) { + args = new Object[]{payload}; + } else { + args = (Object[]) payload; + } + try { + AbstractOperationOutboundInvocationHandler invocationHandler = getInvocationHandler(); + return invocationHandler.invoke(operation, args); + } catch (Throwable t) { + throw new InvocationTargetException(t); + } + } + + @Override + public AbstractCompositeReferenceTargetInvoker clone() throws CloneNotSupportedException { + return (AbstractCompositeReferenceTargetInvoker) super.clone(); + } + + protected abstract AbstractOperationOutboundInvocationHandler getInvocationHandler(); +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractOperationOutboundInvocationHandler.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractOperationOutboundInvocationHandler.java new file mode 100644 index 0000000000..2ccc3ec729 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/AbstractOperationOutboundInvocationHandler.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.core.implementation.composite; + +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.AbstractOutboundInvocationHandler; + +/** + * + * @version $Rev$ $Date$ + */ +public abstract class AbstractOperationOutboundInvocationHandler + extends AbstractOutboundInvocationHandler { + + public abstract Object invoke(Operation operation, Object[] args) throws Throwable; +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeBindlessBuilder.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeBindlessBuilder.java new file mode 100644 index 0000000000..c0466465cf --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeBindlessBuilder.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.core.implementation.composite; + +import org.osoa.sca.annotations.Init; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.builder.BindlessBuilder; +import org.apache.tuscany.spi.builder.BuilderRegistry; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.Reference; +import org.apache.tuscany.spi.component.Service; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.model.BindlessServiceDefinition; +import org.apache.tuscany.spi.model.ReferenceDefinition; +import org.apache.tuscany.spi.wire.WireService; + +/** + * The default implementation f a {@link BindlessBuilder} for a composite + */ +public class CompositeBindlessBuilder implements BindlessBuilder { + + protected BuilderRegistry builderRegistry; + protected WireService wireService; + protected WorkContext workContext; + + @Autowire + public void setBuilderRegistry(BuilderRegistry registry) { + this.builderRegistry = registry; + } + + @Autowire + public void setWireService(WireService wireService) { + this.wireService = wireService; + } + + @Autowire + public void setWorkContext(WorkContext workContext) { + this.workContext = workContext; + } + + @Init(eager = true) + public void init() { + builderRegistry.register(this); + } + + public Service build(CompositeComponent parent, + BindlessServiceDefinition definition, + DeploymentContext deploymentContext) { + return new CompositeService(definition.getName(), + definition.getServiceContract().getInterfaceClass(), + parent, + wireService, + workContext); + } + + public Reference build(CompositeComponent parent, + ReferenceDefinition definition, + DeploymentContext deploymentContext) { + return new CompositeReference(definition.getName(), + parent, + wireService, + definition.getServiceContract(), + workContext); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeBuilder.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeBuilder.java new file mode 100644 index 0000000000..dccfc636c4 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeBuilder.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.spi.builder.BuilderConfigException; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.ComponentBuilderExtension; +import org.apache.tuscany.spi.model.Binding; +import org.apache.tuscany.spi.model.BindlessServiceDefinition; +import org.apache.tuscany.spi.model.BoundReferenceDefinition; +import org.apache.tuscany.spi.model.BoundServiceDefinition; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.CompositeImplementation; +import org.apache.tuscany.spi.model.Implementation; +import org.apache.tuscany.spi.model.ReferenceDefinition; +import org.apache.tuscany.spi.model.ServiceDefinition; + +/** + * Instantiates a composite component from an assembly definition + * + * @version $Rev$ $Date$ + */ +public class CompositeBuilder extends ComponentBuilderExtension<CompositeImplementation> { + + public Component build(CompositeComponent parent, + ComponentDefinition<CompositeImplementation> componentDefinition, + DeploymentContext deploymentContext) throws BuilderConfigException { + CompositeImplementation implementation = componentDefinition.getImplementation(); + CompositeComponentType<?, ?, ?> componentType = implementation.getComponentType(); + + // create lists of all components, services and references in this composite + List<ComponentDefinition<? extends Implementation<?>>> allComponents = + new ArrayList<ComponentDefinition<? extends Implementation<?>>>(); + allComponents.addAll(componentType.getComponents().values()); + + List<BoundServiceDefinition<? extends Binding>> allBoundServices = + new ArrayList<BoundServiceDefinition<? extends Binding>>(); + List<BindlessServiceDefinition> allBindlessServices = new ArrayList<BindlessServiceDefinition>(); + for (ServiceDefinition serviceDefinition : componentType.getServices().values()) { + if (serviceDefinition instanceof BoundServiceDefinition) { + BoundServiceDefinition<? extends Binding> boundService = + (BoundServiceDefinition<? extends Binding>) serviceDefinition; + allBoundServices.add(boundService); + } else if (serviceDefinition instanceof BindlessServiceDefinition) { + allBindlessServices.add((BindlessServiceDefinition) serviceDefinition); + } + } + + // FIXME is this right? + List<BoundReferenceDefinition<? extends Binding>> allBoundReferences = + new ArrayList<BoundReferenceDefinition<? extends Binding>>(); + List<ReferenceDefinition> allTargetlessReferences = new ArrayList<ReferenceDefinition>(); + + for (Object referenceTarget : componentType.getReferences().values()) { + if (referenceTarget instanceof BoundReferenceDefinition<?>) { + allBoundReferences.add((BoundReferenceDefinition<? extends Binding>) referenceTarget); + } else if (referenceTarget instanceof ReferenceDefinition) { + allTargetlessReferences.add((ReferenceDefinition) referenceTarget); + } + } + + String name = componentDefinition.getName(); + CompositeComponentImpl component = new CompositeComponentImpl(name, parent, connector, null); + for (BoundReferenceDefinition<? extends Binding> referenceDefinition : allBoundReferences) { + component.register(builderRegistry.build(component, referenceDefinition, deploymentContext)); + } + for (BindlessServiceDefinition bindlessServiceDef : allBindlessServices) { + component.register(builderRegistry.build(component, bindlessServiceDef, deploymentContext)); + } + for (ComponentDefinition<? extends Implementation<?>> child : allComponents) { + component.register(builderRegistry.build(component, child, deploymentContext)); + } + for (BoundServiceDefinition<? extends Binding> serviceDefinition : allBoundServices) { + component.register(builderRegistry.build(component, serviceDefinition, deploymentContext)); + } + for (ReferenceDefinition targetlessReferenceDef : allTargetlessReferences) { + component.register(builderRegistry.build(component, targetlessReferenceDef, deploymentContext)); + } + + // HACK: [rfeng] We need a better way to propagate model extensions to SCAObject. + component.getExtensions().putAll(componentType.getExtensions()); + + return component; + } + + protected Class<CompositeImplementation> getImplementationType() { + return CompositeImplementation.class; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImpl.java new file mode 100644 index 0000000000..d7833c8707 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImpl.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.util.Map; + +import org.w3c.dom.Document; + +import org.apache.tuscany.spi.builder.Connector; +import org.apache.tuscany.spi.component.CompositeComponent; + +/** + * The standard implementation of a composite component. Autowiring is performed by delegating to the parent composite. + * + * @version $Rev$ $Date$ + */ +public class CompositeComponentImpl extends AbstractCompositeComponent { + private String uri; + + public CompositeComponentImpl(String name, + CompositeComponent parent, + Connector connector, + Map<String, Document> propertyValues) { + this(name, null, parent, connector, propertyValues); + } + + /** + * Constructor specifying name and URI. + * + * @param name the name of this Component + * @param uri the unique identifier for this component + * @param parent this component's parent + * @param connector + * @param propertyValues this composite's Property values + */ + public CompositeComponentImpl(String name, + String uri, + CompositeComponent parent, + Connector connector, + Map<String, Document> propertyValues) { + super(name, parent, connector, propertyValues); + this.uri = uri; + } + + public String getURI() { + return uri; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentTypeLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentTypeLoader.java new file mode 100644 index 0000000000..cac1b231c6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeComponentTypeLoader.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.net.URL; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.CompositeClassLoader; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.ComponentTypeLoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.CompositeImplementation; + +import org.apache.tuscany.core.deployer.ChildDeploymentContext; + +/** + * Loads a composite component type + * + * @version $Rev$ $Date$ + */ +public class CompositeComponentTypeLoader extends ComponentTypeLoaderExtension<CompositeImplementation> { + public CompositeComponentTypeLoader() { + } + + public CompositeComponentTypeLoader(LoaderRegistry loaderRegistry) { + super(loaderRegistry); + } + + protected Class<CompositeImplementation> getImplementationClass() { + return CompositeImplementation.class; + } + + public void load(CompositeComponent parent, CompositeImplementation implementation, + DeploymentContext deploymentContext) + throws LoaderException { + URL scdlLocation = implementation.getScdlLocation(); + ClassLoader cl = new CompositeClassLoader(implementation.getClassLoader()); + deploymentContext = new ChildDeploymentContext(deploymentContext, cl, scdlLocation); + CompositeComponentType componentType = loadFromSidefile(parent, scdlLocation, deploymentContext); + implementation.setComponentType(componentType); + } + + protected CompositeComponentType loadFromSidefile(CompositeComponent parent, + URL url, + DeploymentContext deploymentContext) + throws LoaderException { + return loaderRegistry.load(parent, url, CompositeComponentType.class, deploymentContext); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeLoader.java new file mode 100644 index 0000000000..312d06cbd2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeLoader.java @@ -0,0 +1,130 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; +import static org.osoa.sca.Version.XML_NAMESPACE_1_0; + +import java.net.URL; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.core.property.PropertyHelper; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.CompositeClassLoader; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.Implementation; +import org.apache.tuscany.spi.model.Include; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.model.ReferenceDefinition; +import org.apache.tuscany.spi.model.ServiceDefinition; +import org.apache.tuscany.spi.services.artifact.Artifact; +import org.apache.tuscany.spi.services.artifact.ArtifactRepository; + +/** + * Loads a composite component definition from an XML-based assembly file + * + * @version $Rev$ $Date$ + */ +public class CompositeLoader extends LoaderExtension<CompositeComponentType> { + public static final QName COMPOSITE = new QName(XML_NAMESPACE_1_0, "composite"); + + private final ArtifactRepository artifactRepository; + + public CompositeLoader(@Autowire LoaderRegistry registry, + @Autowire ArtifactRepository artifactRepository) { + super(registry); + this.artifactRepository = artifactRepository; + } + + public QName getXMLType() { + return COMPOSITE; + } + + public CompositeComponentType load(CompositeComponent parent, + XMLStreamReader reader, + DeploymentContext deploymentContext) + throws XMLStreamException, LoaderException { + CompositeComponentType<ServiceDefinition, ReferenceDefinition, Property<?>> composite = + new CompositeComponentType<ServiceDefinition, ReferenceDefinition, Property<?>>(); + composite.setName(reader.getAttributeValue(null, "name")); + boolean done = false; + while (!done) { + switch (reader.next()) { + case START_ELEMENT: + ModelObject o = registry.load(parent, reader, deploymentContext); + if (o instanceof ServiceDefinition) { + composite.add((ServiceDefinition) o); + } else if (o instanceof ReferenceDefinition) { + composite.add((ReferenceDefinition) o); + } else if (o instanceof Property<?>) { + composite.add((Property<?>) o); + } else if (o instanceof ComponentDefinition<?>) { + composite.add((ComponentDefinition<? extends Implementation<?>>) o); + } else if (o instanceof Include) { + composite.add((Include) o); + } else if (o instanceof Dependency) { + Artifact artifact = ((Dependency) o).getArtifact(); + if (artifactRepository != null) { + // default to jar type if not specified + if (artifact.getType() == null) { + artifact.setType("jar"); + } + artifactRepository.resolve(artifact); + } + if (artifact.getUrl() != null) { + ClassLoader classLoader = deploymentContext.getClassLoader(); + if (classLoader instanceof CompositeClassLoader) { + CompositeClassLoader ccl = (CompositeClassLoader)classLoader; + for (URL dep : artifact.getUrls()) { + ccl.addURL(dep); + } + } + } + } else { + // HACK: [rfeng] Add as an unknown model extension + if (o != null) { + composite.getExtensions().put(o.getClass(), o); + } + } + reader.next(); + break; + case END_ELEMENT: + if (COMPOSITE.equals(reader.getName())) { + done = true; + break; + } + } + } + for (ComponentDefinition<? extends Implementation<?>> c : composite.getComponents().values()) { + PropertyHelper.processProperties(composite, c, deploymentContext); + } + return composite; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeReference.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeReference.java new file mode 100644 index 0000000000..60f91ec073 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeReference.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.core.implementation.composite; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.extension.ReferenceExtension; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.TargetInvoker; +import org.apache.tuscany.spi.wire.WireService; + +/** + * A bindless reference to a target service in the parent composite + */ +public class CompositeReference extends ReferenceExtension { + + private WorkContext workContext; + + public CompositeReference(String name, + CompositeComponent parent, + WireService wireService, + ServiceContract contract, + WorkContext workContext) { + super(name, contract.getInterfaceClass(), parent, wireService); + this.workContext = workContext; + } + + public TargetInvoker createTargetInvoker(ServiceContract contract, Operation operation) { + return new CompositeReferenceTargetInvoker(operation, inboundWire, outboundWire, workContext); + } + + public TargetInvoker createCallbackTargetInvoker(ServiceContract contract, Operation operation) { + return new CompositeReferenceCallbackTargetInvoker(operation, inboundWire, workContext); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeReferenceCallbackTargetInvoker.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeReferenceCallbackTargetInvoker.java new file mode 100644 index 0000000000..5301e024dc --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeReferenceCallbackTargetInvoker.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.lang.reflect.InvocationTargetException; + +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.InvocationRuntimeException; +import org.apache.tuscany.spi.wire.Message; + +/** + * + */ +public class CompositeReferenceCallbackTargetInvoker extends AbstractCompositeReferenceTargetInvoker { + + private InboundWire inboundWire; + private WorkContext workContext; + + public CompositeReferenceCallbackTargetInvoker(Operation operation, InboundWire inboundWire, WorkContext context) { + super(operation); + this.inboundWire = inboundWire; + this.workContext = context; + } + + public Message invoke(Message msg) throws InvocationRuntimeException { + try { + workContext.setCurrentMessageId(msg.getMessageId()); + workContext.setCurrentCorrelationId(msg.getCorrelationId()); + Object resp = invokeTarget(msg.getBody()); + msg.setBody(resp); + } catch (InvocationTargetException e) { + msg.setBodyWithFault(e.getCause()); + } catch (Throwable e) { + msg.setBodyWithFault(e); + } + return msg; + } + + public CompositeReferenceCallbackTargetInvoker clone() throws CloneNotSupportedException { + return (CompositeReferenceCallbackTargetInvoker) super.clone(); + } + + protected AbstractOperationOutboundInvocationHandler getInvocationHandler() { + return new OperationCallbackInvocationHandler(workContext, inboundWire); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeReferenceTargetInvoker.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeReferenceTargetInvoker.java new file mode 100644 index 0000000000..42c9c7ed82 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeReferenceTargetInvoker.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.core.implementation.composite; + +import java.lang.reflect.InvocationTargetException; + +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.InvocationRuntimeException; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.OutboundWire; + +/** + * + */ +public class CompositeReferenceTargetInvoker extends AbstractCompositeReferenceTargetInvoker { + + private InboundWire inboundWire; + private OutboundWire outboundWire; + private WorkContext workContext; + + + public CompositeReferenceTargetInvoker(Operation operation, + InboundWire inboundWire, + OutboundWire outboundWire, + WorkContext workContext) { + super(operation); + this.inboundWire = inboundWire; + this.outboundWire = outboundWire; + this.workContext = workContext; + } + + public Message invoke(Message msg) throws InvocationRuntimeException { + try { + inboundWire.addMapping(msg.getMessageId(), msg.getFromAddress()); + workContext.setCurrentMessageId(msg.getMessageId()); + workContext.setCurrentCorrelationId(msg.getCorrelationId()); + Object resp = invokeTarget(msg.getBody()); + msg.setBody(resp); + } catch (InvocationTargetException e) { + msg.setBodyWithFault(e.getCause()); + } catch (Throwable e) { + msg.setBodyWithFault(e); + } + return msg; + } + + public CompositeReferenceTargetInvoker clone() throws CloneNotSupportedException { + return (CompositeReferenceTargetInvoker) super.clone(); + } + + protected AbstractOperationOutboundInvocationHandler getInvocationHandler() { + return new OperationOutboundInvocationHandler(outboundWire, workContext); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeService.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeService.java new file mode 100644 index 0000000000..45b1e41d13 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/CompositeService.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import org.apache.tuscany.spi.CoreRuntimeException; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.extension.ServiceExtension; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.TargetInvoker; +import org.apache.tuscany.spi.wire.WireService; + +public class CompositeService extends ServiceExtension { + + private WorkContext workContext; + + public CompositeService(String name, + Class<?> interfaze, + CompositeComponent parent, + WireService wireService, + WorkContext workContext) throws CoreRuntimeException { + super(name, interfaze, parent, wireService); + this.workContext = workContext; + } + + /** + * A service for a remote binding does not need a target invoker, but a bindless service does because it gets wired + * localy from a reference (or from a parent service?!) We just reuse CompositeReferenceTargetInvoker for now since + * it seems the target invoker we need does the same thing, if this is confirmed we should give it a common name + * FIXME !!! Notice that this method is not defined in the SPI !!! + */ + public TargetInvoker createTargetInvoker(ServiceContract contract, Operation operation) { + return new CompositeReferenceTargetInvoker(operation, inboundWire, outboundWire, workContext); + } + + /** + */ + public TargetInvoker createCallbackTargetInvoker(ServiceContract contract, Operation operation) { + return new CompositeReferenceCallbackTargetInvoker(operation, inboundWire, workContext); + } + + public Object getServiceInstance() throws TargetException { + return interfaze.cast(wireService.createProxy(outboundWire)); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/Dependency.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/Dependency.java new file mode 100644 index 0000000000..808f36072f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/Dependency.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.core.implementation.composite; + +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.services.artifact.Artifact; + +/** + * A model object that represents a dependency on an external artifact. + * + * @version $Rev$ $Date$ + */ +public class Dependency extends ModelObject { + private Artifact artifact; + + public Artifact getArtifact() { + return artifact; + } + + public void setArtifact(Artifact artifact) { + this.artifact = artifact; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/DependencyLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/DependencyLoader.java new file mode 100644 index 0000000000..643c59bad2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/DependencyLoader.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.services.artifact.Artifact; + +/** + * Loader for handling <dependency> elements. + * + * @version $Rev$ $Date$ + */ +public class DependencyLoader extends LoaderExtension<Dependency> { + private static final String NS = "http://incubator.apache.org/tuscany/xmlns/1.0-incubator-M2"; + private static final QName DEPENDENCY = new QName(NS, "dependency"); + private static final QName GROUP = new QName(NS, "group"); + private static final QName NAME = new QName(NS, "name"); + private static final QName VERSION = new QName(NS, "version"); + private static final QName CLASSIFIER = new QName(NS, "classifier"); + private static final QName TYPE = new QName(NS, "type"); + + public DependencyLoader(@Autowire LoaderRegistry registry) { + super(registry); + } + + public QName getXMLType() { + return DEPENDENCY; + } + + public Dependency load(CompositeComponent parent, + XMLStreamReader reader, + DeploymentContext deploymentContext) + throws XMLStreamException, LoaderException { + + Artifact artifact = new Artifact(); + while (reader.nextTag() == XMLStreamConstants.START_ELEMENT) { + QName name = reader.getName(); + String text = reader.getElementText(); + if (GROUP.equals(name)) { + artifact.setGroup(text); + } else if (NAME.equals(name)) { + artifact.setName(text); + } else if (VERSION.equals(name)) { + artifact.setVersion(text); + } else if (CLASSIFIER.equals(name)) { + artifact.setClassifier(text); + } else if (TYPE.equals(name)) { + artifact.setType(text); + } + } + Dependency dependency = new Dependency(); + dependency.setArtifact(artifact); + return dependency; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ImplementationCompositeLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ImplementationCompositeLoader.java new file mode 100644 index 0000000000..40051d30ba --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/ImplementationCompositeLoader.java @@ -0,0 +1,133 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collections; +import java.util.Set; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.osoa.sca.Version; +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.CompositeClassLoader; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.InvalidValueException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.LoaderUtil; +import org.apache.tuscany.spi.loader.MissingResourceException; +import org.apache.tuscany.spi.model.CompositeImplementation; +import org.apache.tuscany.spi.services.artifact.Artifact; +import org.apache.tuscany.spi.services.artifact.ArtifactRepository; + +/** + * Loader that handles an <implementation.composite> element. + * + * @version $Rev$ $Date$ + */ +public class ImplementationCompositeLoader extends LoaderExtension<CompositeImplementation> { + private static final QName IMPLEMENTATION_COMPOSITE = + new QName(Version.XML_NAMESPACE_1_0, "implementation.composite"); + + private final ArtifactRepository artifactRepository; + + public ImplementationCompositeLoader(@Autowire LoaderRegistry registry, + @Autowire ArtifactRepository artifactRepository) { + super(registry); + this.artifactRepository = artifactRepository; + } + + public QName getXMLType() { + return IMPLEMENTATION_COMPOSITE; + } + + public CompositeImplementation load(CompositeComponent parent, + XMLStreamReader reader, + DeploymentContext deploymentContext) + throws XMLStreamException, LoaderException { + + assert IMPLEMENTATION_COMPOSITE.equals(reader.getName()); + String name = reader.getAttributeValue(null, "name"); + String group = reader.getAttributeValue(null, "group"); + String version = reader.getAttributeValue(null, "version"); + String scdlLocation = reader.getAttributeValue(null, "scdlLocation"); + String jarLocation = reader.getAttributeValue(null, "jarLocation"); + LoaderUtil.skipToEndElement(reader); + + CompositeImplementation impl = new CompositeImplementation(); + impl.setName(name); + if (scdlLocation != null) { + try { + impl.setScdlLocation(new URL(deploymentContext.getScdlLocation(), scdlLocation)); + } catch (MalformedURLException e) { + InvalidValueException ive = new InvalidValueException(scdlLocation, e); + ive.setIdentifier(name); + throw ive; + } + impl.setClassLoader(deploymentContext.getClassLoader()); + } else if (jarLocation != null) { + URL jarUrl; + try { + jarUrl = new URL(deploymentContext.getScdlLocation(), jarLocation); + } catch (MalformedURLException e) { + InvalidValueException ive = new InvalidValueException(jarLocation, e); + ive.setIdentifier(name); + throw ive; + } + try { + impl.setScdlLocation(new URL("jar:" + jarUrl.toExternalForm() + "!/META-INF/sca/default.scdl")); + } catch (MalformedURLException e) { + throw new AssertionError("Could not convert URL to a jar: url"); + } + impl.setClassLoader(new CompositeClassLoader(new URL[]{jarUrl}, deploymentContext.getClassLoader())); + } else if (artifactRepository != null && group != null && version != null) { + Artifact artifact = new Artifact(); + artifact.setGroup(group); + artifact.setName(name); + artifact.setVersion(version); + artifact.setType("jar"); + artifactRepository.resolve(artifact); + if (artifact.getUrl() == null) { + MissingResourceException mre = new MissingResourceException(artifact.toString()); + mre.setIdentifier(name); + throw mre; + } + try { + impl.setScdlLocation(new URL("jar:" + artifact.getUrl() + "!/META-INF/sca/default.scdl")); + } catch (MalformedURLException e) { + throw new AssertionError(e); + } + Set<URL> artifactURLs = artifact.getUrls(); + URL[] urls = new URL[artifactURLs.size()]; + int i = 0; + for (URL artifactURL : artifactURLs) { + urls[i++] = artifactURL; + } + impl.setClassLoader(new CompositeClassLoader(urls, deploymentContext.getClassLoader())); + } + return impl; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/OperationCallbackInvocationHandler.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/OperationCallbackInvocationHandler.java new file mode 100644 index 0000000000..df8e13a58e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/OperationCallbackInvocationHandler.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.util.Map; + +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.TargetInvoker; + +/** + * + */ +public class OperationCallbackInvocationHandler extends AbstractOperationOutboundInvocationHandler { + + private WorkContext context; + private InboundWire inboundWire; + private Object messageId; + private Object correlationId; + + public OperationCallbackInvocationHandler(WorkContext context, InboundWire inboundWire) { + this.context = context; + this.inboundWire = inboundWire; + } + + public Object invoke(Object proxy, Operation operation, Object[] args) throws Throwable { + messageId = context.getCurrentMessageId(); + context.setCurrentMessageId(null); + correlationId = context.getCurrentCorrelationId(); + context.setCurrentCorrelationId(null); + Object targetAddress = inboundWire.retrieveMapping(correlationId); + if (targetAddress == null) { + throw new AssertionError("No from address associated with message id [" + correlationId + "]"); + } + //TODO optimize as this is slow in local invocations + Map<Operation<?>, OutboundInvocationChain> sourceCallbackInvocationChains = + inboundWire.getSourceCallbackInvocationChains(targetAddress); + OutboundInvocationChain chain = sourceCallbackInvocationChains.get(operation); + TargetInvoker invoker = chain.getTargetInvoker(); + return invoke(chain, invoker, args); + } + + + public Object invoke(Operation operation, Object[] args) throws Throwable { + return invoke(null, operation, args); + } + + protected Object getFromAddress() { + return (inboundWire.getContainer() == null) ? null : inboundWire.getContainer().getName(); + } + + protected Object getMessageId() { + return messageId; + } + + protected Object getCorrelationId() { + return correlationId; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/OperationOutboundInvocationHandler.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/OperationOutboundInvocationHandler.java new file mode 100644 index 0000000000..ba49cee547 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/composite/OperationOutboundInvocationHandler.java @@ -0,0 +1,127 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.TargetInvoker; + +/** + * + */ +public class OperationOutboundInvocationHandler extends AbstractOperationOutboundInvocationHandler { + + /* + * an association of an operation to chain holder. The holder contains an invocation chain + * and a local clone of the master TargetInvoker. TargetInvokers will be cloned by the handler and placed in the + * holder if they are cacheable. This allows optimizations such as avoiding target resolution when a source refers + * to a target of greater scope since the target reference can be maintained by the invoker. When a target invoker + * is not cacheable, the master associated with the wire chains will be used. + */ + private Map<Operation, ChainHolder> chains; + private WorkContext context; + private Object fromAddress; + private Object messageId; + private Object correlationId; + + public OperationOutboundInvocationHandler(OutboundWire wire, WorkContext context) { + Map<Operation<?>, OutboundInvocationChain> invocationChains = wire.getInvocationChains(); + this.chains = new HashMap<Operation, ChainHolder>(invocationChains.size()); + this.fromAddress = (wire.getContainer() == null) ? null : wire.getContainer().getName(); + // TODO optimize this + for (Map.Entry<Operation<?>, OutboundInvocationChain> entry : invocationChains.entrySet()) { + Operation operation = entry.getKey(); + this.chains.put(operation, new ChainHolder(entry.getValue())); + } + + this.context = context; + } + + public Object invoke(Object proxy, Operation operation, Object[] args) throws Throwable { + ChainHolder holder = chains.get(operation); + if (holder == null) { + TargetException e = new TargetException("Operation not configured"); + e.setIdentifier(operation.getName()); + throw e; + } + OutboundInvocationChain chain = holder.chain; + TargetInvoker invoker; + + if (holder.cachedInvoker == null) { + assert chain != null; + if (chain.getTargetInvoker() == null) { + TargetException e = new TargetException("No target invoker configured for operation"); + e.setIdentifier(chain.getOperation().getName()); + throw e; + } + if (chain.getTargetInvoker().isCacheable()) { + // clone and store the invoker locally + holder.cachedInvoker = (TargetInvoker) chain.getTargetInvoker().clone(); + invoker = holder.cachedInvoker; + } else { + invoker = chain.getTargetInvoker(); + } + } else { + assert chain != null; + invoker = chain.getTargetInvoker(); + } + messageId = context.getCurrentMessageId(); + context.setCurrentMessageId(null); + correlationId = context.getCurrentCorrelationId(); + context.setCurrentCorrelationId(null); + return invoke(chain, invoker, args); + } + + public Object invoke(Operation operation, Object[] args) throws Throwable { + return invoke(null, operation, args); + } + + protected Object getFromAddress() { + return fromAddress; + } + + protected Object getMessageId() { + return messageId; + } + + protected Object getCorrelationId() { + return correlationId; + } + + /** + * A holder used to associate an wire chain with a local copy of a target invoker that was previously cloned from + * the chain master + */ + private class ChainHolder { + + OutboundInvocationChain chain; + TargetInvoker cachedInvoker; + + public ChainHolder(OutboundInvocationChain config) { + this.chain = config; + } + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/AsyncJavaTargetInvoker.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/AsyncJavaTargetInvoker.java new file mode 100644 index 0000000000..d6e2a35a87 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/AsyncJavaTargetInvoker.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import java.lang.reflect.Method; + +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.InvocationRuntimeException; +import org.apache.tuscany.spi.wire.Message; + +import org.apache.tuscany.core.wire.PojoTargetInvoker; + +/** + * Responsible for performing a non-blocking dispatch on a Java component implementation instance + * + * @version $Rev$ $Date$ + */ +public class AsyncJavaTargetInvoker extends PojoTargetInvoker { + + private JavaAtomicComponent component; + private InboundWire wire; + private AsyncMonitor monitor; + private WorkContext workContext; + private Object target; + + /** + * Creates a new invoker + * + * @param operation the operation the invoker is associated with + * @param wire + * @param component the target component + * @param monitor the monitor to pass events to + * @param workContext + */ + public AsyncJavaTargetInvoker(Method operation, + InboundWire wire, + JavaAtomicComponent component, + AsyncMonitor monitor, + WorkContext workContext) { + super(operation); + this.wire = wire; + this.component = component; + this.monitor = monitor; + this.workContext = workContext; + } + + public Message invoke(Message msg) throws InvocationRuntimeException { + try { + Object messageId = msg.getMessageId(); + wire.addMapping(messageId, msg.getFromAddress()); + workContext.setCurrentMessageId(null); + workContext.setCurrentCorrelationId(messageId); + invokeTarget(msg.getBody()); + // async so no return value + return null; + } catch (Throwable e) { + // FIXME need to log exceptions + monitor.executionError(e); + return null; + } + } + + public AsyncJavaTargetInvoker clone() throws CloneNotSupportedException { + return (AsyncJavaTargetInvoker) super.clone(); + } + + /** + * Resolves the target service instance or returns a cached one + */ + protected Object getInstance() throws TargetException { + if (!cacheable) { + return component.getTargetInstance(); + } else { + if (target == null) { + target = component.getTargetInstance(); + } + return target; + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/AsyncMonitor.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/AsyncMonitor.java new file mode 100644 index 0000000000..6d35b32841 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/AsyncMonitor.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +/** + * A monitor used to log events during non-blocking invocations + * <p/> + * REVIEW JFM we should probably generalize async monitor and make it an invocation monitor + * + * @version $$Rev$$ $$Date$$ + */ +public interface AsyncMonitor { + + /** + * Logs an exception thrown during an invocation + */ + void executionError(Throwable e); + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponent.java new file mode 100644 index 0000000000..96b61dab1c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponent.java @@ -0,0 +1,136 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; + +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.component.TargetNotFoundException; +import static org.apache.tuscany.spi.idl.java.JavaIDLUtils.findMethod; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.RuntimeWire; +import org.apache.tuscany.spi.wire.TargetInvoker; + +import org.apache.tuscany.core.implementation.PojoAtomicComponent; +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.core.injection.CallbackWireObjectFactory; +import org.apache.tuscany.core.injection.FieldInjector; +import org.apache.tuscany.core.injection.Injector; +import org.apache.tuscany.core.injection.InvalidAccessorException; +import org.apache.tuscany.core.injection.MethodInjector; +import org.apache.tuscany.core.injection.WireObjectFactory; + +/** + * The runtime instantiation of Java component implementations + * + * @version $Rev$ $Date$ + */ +public class JavaAtomicComponent extends PojoAtomicComponent { + + private AsyncMonitor monitor; + + public JavaAtomicComponent(String name, + PojoConfiguration configuration, + AsyncMonitor monitor) { + super(name, configuration); + this.scope = configuration.getScopeContainer().getScope(); + this.monitor = monitor; + } + + public Object getServiceInstance(String name) throws TargetException { + InboundWire wire = serviceWires.get(name); + if (wire == null) { + TargetNotFoundException e = new TargetNotFoundException(name); + e.addContextName(getName()); + throw e; + } + return wireService.createProxy(wire); + } + + public Object getServiceInstance() throws TargetException { + if (serviceInterfaces.size() == 0) { + return getTargetInstance(); + } else if (serviceInterfaces.size() == 1) { + return getTargetInstance(); + } else { + throw new TargetException("Component must have exactly one service"); + } + } + + public TargetInvoker createTargetInvoker(String targetName, Operation operation) { + Method[] methods; + if (operation.isCallback()) { + methods = operation.getServiceContract().getCallbackClass().getMethods(); + + } else { + methods = operation.getServiceContract().getInterfaceClass().getMethods(); + } + Method method = findMethod(operation, methods); + return new JavaTargetInvoker(method, this); + } + + public TargetInvoker createAsyncTargetInvoker(InboundWire wire, Operation operation) { + Method method; + if (operation.isCallback()) { + method = findMethod(operation, operation.getServiceContract().getCallbackClass().getMethods()); + + } else { + method = findMethod(operation, operation.getServiceContract().getInterfaceClass().getMethods()); + } + return new AsyncJavaTargetInvoker(method, wire, this, monitor, workContext); + } + + protected void onServiceWire(InboundWire wire) { + String name = wire.getCallbackReferenceName(); + if (name == null) { + // It's ok not to have one, we just do nothing + return; + } + Member member = callbackSites.get(name); + if (member != null) { + injectors.add(createCallbackInjector(member, wire.getServiceContract(), wire)); + } + } + + protected Injector<Object> createCallbackInjector(Member member, ServiceContract<?> contract, + InboundWire inboundWire) { + if (member instanceof Field) { + Field field = (Field) member; + ObjectFactory<?> factory = new CallbackWireObjectFactory(contract, wireService, inboundWire); + return new FieldInjector<Object>(field, factory); + } else if (member instanceof Method) { + Method method = (Method) member; + ObjectFactory<?> factory = new CallbackWireObjectFactory(contract, wireService, inboundWire); + return new MethodInjector<Object>(method, factory); + } else { + InvalidAccessorException e = new InvalidAccessorException("Member must be a field or method"); + e.setIdentifier(member.getName()); + throw e; + } + } + + protected ObjectFactory<?> createWireFactory(RuntimeWire wire) { + return new WireObjectFactory(wire, wireService); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentBuilder.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentBuilder.java new file mode 100644 index 0000000000..2666423b12 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentBuilder.java @@ -0,0 +1,140 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Member; +import java.lang.reflect.Method; + +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; + +import org.apache.tuscany.api.annotation.Monitor; +import org.apache.tuscany.spi.builder.BuilderConfigException; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.ComponentBuilderExtension; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.PropertyValue; +import org.apache.tuscany.spi.model.Scope; + +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; + +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.core.injection.MethodEventInvoker; +import org.apache.tuscany.core.injection.PojoObjectFactory; + +/** + * Builds a Java-based atomic context from a component definition + * + * @version $$Rev$$ $$Date$$ + */ +public class JavaComponentBuilder extends ComponentBuilderExtension<JavaImplementation> { + + private AsyncMonitor monitor; + + @Monitor + public void setMonitor(AsyncMonitor monitor) { + this.monitor = monitor; + } + + @SuppressWarnings("unchecked") + public AtomicComponent build(CompositeComponent parent, + ComponentDefinition<JavaImplementation> definition, + DeploymentContext deployment) + throws BuilderConfigException { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> componentType = + definition.getImplementation().getComponentType(); + + PojoConfiguration configuration = new PojoConfiguration(); + configuration.setParent(parent); + Scope scope = componentType.getImplementationScope(); + if (Scope.MODULE == scope) { + configuration.setScopeContainer(deployment.getModuleScope()); + } else { + configuration.setScopeContainer(scopeRegistry.getScopeContainer(scope)); + } + if (definition.getInitLevel() != null) { + configuration.setInitLevel(definition.getInitLevel()); + } else { + configuration.setInitLevel(componentType.getInitLevel()); + } + Method initMethod = componentType.getInitMethod(); + if (initMethod != null) { + configuration.setInitInvoker(new MethodEventInvoker(initMethod)); + } + Method destroyMethod = componentType.getDestroyMethod(); + if (destroyMethod != null) { + configuration.setDestroyInvoker(new MethodEventInvoker(destroyMethod)); + } + + configuration.setWireService(wireService); + configuration.setWorkContext(workContext); + configuration.setScheduler(workScheduler); + + // setup property injection sites + for (JavaMappedProperty<?> property : componentType.getProperties().values()) { + configuration.addPropertySite(property.getName(), property.getMember()); + } + + // setup reference injection sites + for (JavaMappedReference reference : componentType.getReferences().values()) { + Member member = reference.getMember(); + if (member != null) { + // could be null if the reference is mapped to a constructor + configuration.addReferenceSite(reference.getName(), member); + } + } + // setup constructor injection + ConstructorDefinition<?> ctorDef = componentType.getConstructorDefinition(); + Constructor<?> constr = ctorDef.getConstructor(); + PojoObjectFactory<?> instanceFactory = new PojoObjectFactory(constr); + configuration.setInstanceFactory(instanceFactory); + configuration.getConstructorParamNames().addAll(ctorDef.getInjectionNames()); + + JavaAtomicComponent component = + new JavaAtomicComponent(definition.getName(), configuration, monitor); + + // handle properties + for (PropertyValue<?> property : definition.getPropertyValues().values()) { + ObjectFactory<?> factory = property.getValueFactory(); + if (factory != null) { + component.addPropertyFactory(property.getName(), factory); + } + } + + for (JavaMappedService service : componentType.getServices().values()) { + // setup callback injection sites + if (service.getCallbackReferenceName() != null) { + // Only if there is a callback reference in the service + configuration.addCallbackSite(service.getCallbackReferenceName(), service.getCallbackMember()); + } + } + return component; + } + + protected Class<JavaImplementation> getImplementationType() { + return JavaImplementation.class; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentTypeLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentTypeLoader.java new file mode 100644 index 0000000000..0c4f5537ab --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaComponentTypeLoader.java @@ -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.core.implementation.java; + +import java.net.URL; + +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.ComponentTypeLoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; + +import org.apache.tuscany.spi.implementation.java.IntrospectionRegistry; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; + +import org.apache.tuscany.spi.implementation.java.Introspector; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +import org.apache.tuscany.spi.implementation.java.PojoComponentType; + +import org.apache.tuscany.core.util.JavaIntrospectionHelper; + +/** + * @version $Rev$ $Date$ + */ +public class JavaComponentTypeLoader extends ComponentTypeLoaderExtension<JavaImplementation> { + private Introspector introspector; + + @Constructor({"registry", "introspector"}) + public JavaComponentTypeLoader(@Autowire LoaderRegistry loaderRegistry, + @Autowire IntrospectionRegistry introspector) { + super(loaderRegistry); + this.introspector = introspector; + } + + @Override + protected Class<JavaImplementation> getImplementationClass() { + return JavaImplementation.class; + } + + public void load(CompositeComponent parent, + JavaImplementation implementation, + DeploymentContext deploymentContext) throws LoaderException { + Class<?> implClass = implementation.getImplementationClass(); + URL resource = implClass.getResource(JavaIntrospectionHelper.getBaseName(implClass) + ".componentType"); + PojoComponentType componentType; + if (resource == null) { + componentType = loadByIntrospection(parent, implementation, deploymentContext); + } else { + componentType = loadFromSidefile(resource, deploymentContext); + } + implementation.setComponentType(componentType); + } + + protected PojoComponentType loadByIntrospection(CompositeComponent parent, + JavaImplementation implementation, + DeploymentContext deploymentContext) throws ProcessingException { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> componentType = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Class<?> implClass = implementation.getImplementationClass(); + introspector.introspect(parent, implClass, componentType, deploymentContext); + return componentType; + } + + protected PojoComponentType loadFromSidefile(URL url, DeploymentContext deploymentContext) throws LoaderException { + return loaderRegistry.load(null, url, PojoComponentType.class, deploymentContext); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementation.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementation.java new file mode 100644 index 0000000000..807db532fe --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementation.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import org.apache.tuscany.spi.model.AtomicImplementation; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; + +/** + * @version $$Rev$$ $$Date$$ + */ +public class JavaImplementation extends AtomicImplementation<PojoComponentType> { + private Class<?> implementationClass; + + public Class<?> getImplementationClass() { + return implementationClass; + } + + public void setImplementationClass(Class<?> implementationClass) { + this.implementationClass = implementationClass; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementationLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementationLoader.java new file mode 100644 index 0000000000..2ac8056d74 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaImplementationLoader.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import static org.osoa.sca.Version.XML_NAMESPACE_1_0; +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderUtil; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.annotation.Autowire; + +public class JavaImplementationLoader extends LoaderExtension { + public static final QName IMPLEMENTATION_JAVA = new QName(XML_NAMESPACE_1_0, "implementation.java"); + + @Constructor({"registry"}) + public JavaImplementationLoader(@Autowire LoaderRegistry registry) { + super(registry); + } + + @Override + public QName getXMLType() { + return IMPLEMENTATION_JAVA; + } + + public ModelObject load(CompositeComponent parent, XMLStreamReader reader, DeploymentContext deploymentContext) + throws XMLStreamException, LoaderException { + assert IMPLEMENTATION_JAVA.equals(reader.getName()); + JavaImplementation implementation = new JavaImplementation(); + String implClass = reader.getAttributeValue(null, "class"); + Class<?> implementationClass = LoaderUtil.loadClass(implClass, deploymentContext.getClassLoader()); + implementation.setImplementationClass(implementationClass); + registry.loadComponentType(parent, implementation, deploymentContext); + LoaderUtil.skipToEndElement(reader); + return implementation; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaTargetInvoker.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaTargetInvoker.java new file mode 100644 index 0000000000..004929fd93 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/java/JavaTargetInvoker.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import java.lang.reflect.Method; + +import org.apache.tuscany.spi.component.TargetException; + +import org.apache.tuscany.core.wire.PojoTargetInvoker; + +/** + * Uses a component to resolve an implementation instance based on the current thread component + * + * @version $Rev$ $Date$ + */ +public class JavaTargetInvoker extends PojoTargetInvoker { + + private JavaAtomicComponent component; + private Object target; + + /** + * Creates a new invoker + * + * @param operation the operation the invoker is associated with + * @param component the target component + */ + public JavaTargetInvoker(Method operation, JavaAtomicComponent component) { + super(operation); + assert component != null : "No atomic component specified"; + this.component = component; + } + + /** + * Resolves the target service instance or returns a cached one + */ + protected Object getInstance() throws TargetException { + if (!cacheable) { + return component.getTargetInstance(); + } else { + if (target == null) { + target = component.getTargetInstance(); + } + return target; + } + } + + public JavaTargetInvoker clone() throws CloneNotSupportedException { + JavaTargetInvoker invoker = (JavaTargetInvoker) super.clone(); + invoker.target = null; + invoker.cacheable = this.cacheable; + invoker.component = this.component; + return invoker; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/AmbiguousConstructorException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/AmbiguousConstructorException.java new file mode 100644 index 0000000000..6a91bbefe4 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/AmbiguousConstructorException.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.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Thrown when constructor parameters cannot be unambiguously resolved to a property or reference + * + * @version $Rev$ $Date$ + */ +public class AmbiguousConstructorException extends ProcessingException { + public AmbiguousConstructorException() { + } + + public AmbiguousConstructorException(String message) { + super(message); + } + + public AmbiguousConstructorException(String message, Throwable cause) { + super(message, cause); + } + + public AmbiguousConstructorException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessor.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessor.java new file mode 100644 index 0000000000..b363d46337 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessor.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.util.List; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; + + +/** + * Handles processing of a constructor decorated with {@link org.osoa.sca.annotations.Constructor} + * + * @version $Rev$ $Date$ + */ +@SuppressWarnings("unchecked") +public class ConstructorProcessor extends ImplementationProcessorExtension { + + private ImplementationProcessorService service; + + public ConstructorProcessor(@Autowire ImplementationProcessorService service) { + this.service = service; + } + + public <T> void visitClass(CompositeComponent parent, Class<T> clazz, + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + DeploymentContext context) throws ProcessingException { + Constructor[] ctors = clazz.getConstructors(); + boolean found = false; + for (Constructor constructor : ctors) { + if (constructor.getAnnotation(org.osoa.sca.annotations.Constructor.class) != null) { + if (found) { + DuplicateConstructorException e = + new DuplicateConstructorException("Multiple constructors marked with @Constructor"); + e.setIdentifier(constructor.getDeclaringClass().getName()); + throw e; + } + found = true; + } + } + } + + public <T> void visitConstructor(CompositeComponent parent, Constructor<T> constructor, + PojoComponentType<JavaMappedService, JavaMappedReference, + JavaMappedProperty<?>> type, + DeploymentContext context) throws ProcessingException { + org.osoa.sca.annotations.Constructor annotation = + constructor.getAnnotation(org.osoa.sca.annotations.Constructor.class); + if (annotation == null) { + return; + } + ConstructorDefinition<?> definition = type.getConstructorDefinition(); + if (definition != null && !definition.getConstructor().equals(constructor)) { + DuplicateConstructorException e = + new DuplicateConstructorException("Multiple constructor definitions found"); + e.setIdentifier(constructor.getDeclaringClass().getName()); + throw e; + } else if (definition == null) { + definition = new ConstructorDefinition(constructor); + } + Class<?>[] params = constructor.getParameterTypes(); + String[] names = annotation.value(); + Annotation[][] annotations = constructor.getParameterAnnotations(); + List<String> injectionNames = definition.getInjectionNames(); + for (int i = 0; i < params.length; i++) { + Class<?> param = params[i]; + Annotation[] paramAnnotations = annotations[i]; + try { + if (!service.processParam(param, paramAnnotations, names, i, type, injectionNames)) { + String name = (i < names.length) ? names[i] : ""; + service.addName(injectionNames, i, name); + } + } catch (ProcessingException + e) { + e.setIdentifier(constructor.toString()); + throw e; + } + } + if (names.length != 0 && names[0].length() != 0 && names.length != params.length) { + throw new InvalidConstructorException("Names in @Constructor do not match number of parameters"); + } + type.setConstructorDefinition(definition); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ContextProcessor.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ContextProcessor.java new file mode 100644 index 0000000000..326bfb05f4 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ContextProcessor.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import org.osoa.sca.CompositeContext; +import org.osoa.sca.RequestContext; +import org.osoa.sca.annotations.Context; + +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.core.util.JavaIntrospectionHelper; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; + +/** + * Processes {@link @Context} annotations on a component implementation and adds a {@link JavaMappedProperty} to the + * component type which will be used to inject the appropriate context + * + * @version $Rev$ $Date$ + */ +public class ContextProcessor extends ImplementationProcessorExtension { + + public void visitMethod(CompositeComponent parent, Method method, + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + DeploymentContext context) + throws ProcessingException { + if (method.getAnnotation(Context.class) == null) { + return; + } + if (method.getParameterTypes().length != 1) { + IllegalContextException e = new IllegalContextException("Context setter must have one parameter"); + e.setIdentifier(method.toString()); + throw e; + } + Class<?> paramType = method.getParameterTypes()[0]; + if (CompositeContext.class.equals(paramType)) { + String name = method.getName(); + if (name.startsWith("set")) { + name = JavaIntrospectionHelper.toPropertyName(name); + } + JavaMappedProperty property = new JavaMappedProperty(); + property.setName(name); + property.setMember(method); + throw new UnsupportedOperationException(); + // TODO pass in composite context + //SingletonObjectFactory factory = new SingletonObjectFactory(compositeContext); + //property.setDefaultValueFactory(factory); + //type.getProperties().put(name,property); + } else if (RequestContext.class.equals(paramType)) { + String name = method.getName(); + if (name.startsWith("set")) { + name = JavaIntrospectionHelper.toPropertyName(name); + } + JavaMappedProperty property = new JavaMappedProperty(); + property.setName(name); + property.setMember(method); + throw new UnsupportedOperationException(); + // TODO pass in request context + //property.setDefaultValueFactory(factory); + //type.getProperties().put(name,property); + } else { + throw new UnknownContextTypeException(paramType.getName()); + } + + } + + public void visitField(CompositeComponent parent, Field field, + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + DeploymentContext context) throws ProcessingException { + super.visitField(parent, field, type, context); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DestroyProcessor.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DestroyProcessor.java new file mode 100644 index 0000000000..a25902566f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DestroyProcessor.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.osoa.sca.annotations.Destroy; + +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; + +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; + +/** + * Processes the {@link @Destroy} annotation on a component implementation and updates the component type with the + * decorated destructor method + * + * @version $Rev$ $Date$ + */ +public class DestroyProcessor extends ImplementationProcessorExtension { + + public void visitMethod(CompositeComponent parent, Method method, + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + DeploymentContext context) + throws ProcessingException { + Destroy annotation = method.getAnnotation(Destroy.class); + if (annotation == null) { + return; + } + if (method.getParameterTypes().length != 0) { + IllegalDestructorException e = new IllegalDestructorException("Destructor must not have argments"); + e.setIdentifier(method.toString()); + throw e; + } + if (type.getDestroyMethod() != null) { + throw new DuplicateDestructorException("More than one destructor found on implementation"); + } + if (Modifier.isProtected(method.getModifiers())) { + method.setAccessible(true); + } + type.setDestroyMethod(method); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateConstructorException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateConstructorException.java new file mode 100644 index 0000000000..909d0ef124 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateConstructorException.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.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Thrown when more than one component implementation constructor is annotated with {@link + * org.osoa.sca.annotations.Constructor} + * + * @version $Rev$ $Date$ + */ +public class DuplicateConstructorException extends ProcessingException { + + public DuplicateConstructorException() { + } + + public DuplicateConstructorException(String message) { + super(message); + } + + public DuplicateConstructorException(String message, Throwable cause) { + super(message, cause); + } + + public DuplicateConstructorException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateDestructorException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateDestructorException.java new file mode 100644 index 0000000000..732dd926c3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateDestructorException.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.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Thrown when an implementation is annotated multiple times with {@link org.osoa.sca.annotations.Destroy} + * + * @version $Rev$ $Date$ + */ +public class DuplicateDestructorException extends ProcessingException { + public DuplicateDestructorException() { + } + + public DuplicateDestructorException(String message) { + super(message); + } + + public DuplicateDestructorException(String message, Throwable cause) { + super(message, cause); + } + + public DuplicateDestructorException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateInitException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateInitException.java new file mode 100644 index 0000000000..6795a7bfce --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateInitException.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.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Thrown when an implementation is annotated multiple times with {@link @org.osoa.sca.annotations.Init} + * + * @version $Rev$ $Date$ + */ +public class DuplicateInitException extends ProcessingException { + public DuplicateInitException() { + } + + public DuplicateInitException(String message) { + super(message); + } + + public DuplicateInitException(String message, Throwable cause) { + super(message, cause); + } + + public DuplicateInitException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateReferenceException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateReferenceException.java new file mode 100644 index 0000000000..da6ceaa472 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/DuplicateReferenceException.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.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Thrown when an implementation has more than one reference injection site with the same name + * + * @version $Rev$ $Date$ + */ +public class DuplicateReferenceException extends ProcessingException { + public DuplicateReferenceException() { + } + + public DuplicateReferenceException(String message) { + super(message); + } + + public DuplicateReferenceException(String message, Throwable cause) { + super(message, cause); + } + + public DuplicateReferenceException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/HeuristicPojoProcessor.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/HeuristicPojoProcessor.java new file mode 100644 index 0000000000..27ecccafb3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/HeuristicPojoProcessor.java @@ -0,0 +1,521 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getAllInterfaces; +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getAllPublicAndProtectedFields; +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getAllUniquePublicProtectedMethods; +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getBaseName; +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.toPropertyName; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.model.OverrideOptions; +import org.osoa.sca.annotations.Remotable; +import org.osoa.sca.annotations.Service; + +/** + * Heuristically evaluates an un-annotated Java implementation type to determine services, references, and properties + * according to the algorithm described in the SCA Java Client and Implementation Model Specification <p/> TODO + * Implement: + * <p/> + * When no service inteface is annotated, need to calculate a single service comprising all public methods that are not + * reference or property injection sites. If that service can be exactly mapped to an interface implemented by the class + * then the service interface will be defined in terms of that interface. + * + * @version $Rev$ $Date$ + */ +public class HeuristicPojoProcessor extends ImplementationProcessorExtension { + + private ImplementationProcessorService implService; + + public HeuristicPojoProcessor(@Autowire ImplementationProcessorService service) { + this.implService = service; + } + + public <T> void visitEnd( + CompositeComponent parent, + Class<T> clazz, + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + DeploymentContext context) throws ProcessingException { + Map<String, JavaMappedService> services = type.getServices(); + if (services.isEmpty()) { + // heuristically determine the service + // TODO finish algorithm + Set<Class> interfaces = getAllInterfaces(clazz); + if (interfaces.size() == 0) { + // class is the interface + JavaMappedService service; + try { + service = implService.createService(clazz); + } catch (InvalidServiceContractException e) { + throw new ProcessingException(e); + } + type.getServices().put(service.getName(), service); + } else if (interfaces.size() == 1) { + JavaMappedService service; + try { + service = implService.createService(interfaces.iterator().next()); + } catch (InvalidServiceContractException e) { + throw new ProcessingException(e); + } + type.getServices().put(service.getName(), service); + } + } + Set<Method> methods = getAllUniquePublicProtectedMethods(clazz); + if (!type.getReferences().isEmpty() || !type.getProperties().isEmpty()) { + // references and properties have been explicitly defined + if (type.getServices().isEmpty()) { + calculateServiceInterface(clazz, type, methods); + if (type.getServices().isEmpty()) { + throw new ServiceTypeNotFoundException(clazz.getName()); + } + } + evaluateConstructor(type, clazz); + return; + } + + // heuristically determine the properties references + // make a first pass through all public methods with one param + for (Method method : methods) { + if (method.getParameterTypes().length != 1 || !Modifier.isPublic(method.getModifiers()) + || !method.getName().startsWith("set") + || method.getReturnType() != void.class) { + continue; + } + if (!isInServiceInterface(method, services)) { + String name = toPropertyName(method.getName()); + // avoid duplicate property or ref names + if (!type.getProperties().containsKey(name) && !type.getReferences().containsKey(name)) { + Class<?> param = method.getParameterTypes()[0]; + Type genericType = method.getGenericParameterTypes()[0]; + if (isReferenceType(genericType)) { + type.add(createReference(name, method, param)); + } else { + type.add(createProperty(name, method, param)); + } + } + } + } + // second pass for protected methods with one param + for (Method method : methods) { + if (method.getParameterTypes().length != 1 || !Modifier.isProtected(method.getModifiers()) + || !method.getName().startsWith("set") + || method.getReturnType() != void.class) { + continue; + } + Class<?> param = method.getParameterTypes()[0]; + String name = toPropertyName(method.getName()); + // avoid duplicate property or ref names + if (!type.getProperties().containsKey(name) && !type.getReferences().containsKey(name)) { + if (isReferenceType(param)) { + type.add(createReference(name, method, param)); + } else { + type.add(createProperty(name, method, param)); + } + } + } + Set<Field> fields = getAllPublicAndProtectedFields(clazz); + for (Field field : fields) { + Class<?> paramType = field.getType(); + if (isReferenceType(paramType)) { + type.add(createReference(field.getName(), field, paramType)); + } else { + type.add(createProperty(field.getName(), field, paramType)); + } + } + evaluateConstructor(type, clazz); + } + + /** + * Determines the constructor to use based on the component type's references and properties + * + * @param type the component type + * @param clazz the implementation class corresponding to the component type + * @throws NoConstructorException if no suitable constructor is found + * @throws AmbiguousConstructorException if the parameters of a constructor cannot be unambiguously mapped to + * references and properties + */ + @SuppressWarnings("unchecked") + private <T> void evaluateConstructor( + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + Class<T> clazz) throws ProcessingException { + // determine constructor if one is not annotated + ConstructorDefinition<?> definition = type.getConstructorDefinition(); + Constructor constructor; + boolean explict = false; + if (definition != null + && definition.getConstructor().getAnnotation(org.osoa.sca.annotations.Constructor.class) != null) { + // the constructor was already defined explicitly + return; + } else if (definition != null) { + explict = true; + constructor = definition.getConstructor(); + } else { + // no definition, heuristically determine constructor + Constructor[] constructors = clazz.getConstructors(); + if (constructors.length == 0) { + NoConstructorException e = new NoConstructorException("No public constructor for class"); + e.setIdentifier(clazz.getName()); + throw e; + } else if (constructors.length == 1) { + constructor = constructors[0]; + } else { + // FIXME multiple constructors, none yet done + Constructor<T> selected = null; + int sites = type.getProperties().size() + type.getReferences().size(); + for (Constructor<T> ctor : constructors) { + if (ctor.getParameterTypes().length == 0) { + selected = ctor; + } + if (ctor.getParameterTypes().length == sites) { + // TODO finish + // selected = constructor; + // select constructor + // break; + } + } + if (selected == null) { + throw new NoConstructorException(); + } + constructor = selected; + definition = new ConstructorDefinition<T>(selected); + type.setConstructorDefinition(definition); + // return; + } + definition = new ConstructorDefinition<T>(constructor); + type.setConstructorDefinition(definition); + } + Class[] params = constructor.getParameterTypes(); + if (params.length == 0) { + return; + } + List<String> paramNames = definition.getInjectionNames(); + Map<String, JavaMappedProperty<?>> props = type.getProperties(); + Map<String, JavaMappedReference> refs = type.getReferences(); + Annotation[][] annotations = constructor.getParameterAnnotations(); + if (!explict) { + // the constructor wasn't defined by an annotation, so check to see if any of the params have an annotation + // which we can impute as explicitly defining the constructor, e.g. @Property, @Reference, or @Autowire + explict = implService.injectionAnnotationsPresent(annotations); + } + if (explict) { + for (int i = 0; i < params.length; i++) { + Class param = params[i]; + implService.processParam(param, annotations[i], new String[0], i, type, paramNames); + } + } else { + if (!implService.areUnique(params)) { + throw new AmbiguousConstructorException("Cannot resolve non-unique parameter types, use @Constructor"); + } + if (!calcPropRefUniqueness(props.values(), refs.values())) { + throw new AmbiguousConstructorException("Cannot resolve non-unique parameter types, use @Constructor"); + } + boolean empty = props.size() + refs.size() == 0; + if (!empty) { + // the constructor param types must unambiguously match defined reference or property types + for (Class param : params) { + String name = findReferenceOrProperty(param, props, refs); + if (name == null) { + throw new AmbiguousConstructorException(param.getName()); + } + paramNames.add(name); + } + } else { + // heuristically determine refs and props from the parameter types + for (Class<?> param : params) { + String name = getBaseName(param).toLowerCase(); + if (isReferenceType(param)) { + refs.put(name, createReference(name, null, param)); + } else { + props.put(name, createProperty(name, null, param)); + } + paramNames.add(name); + } + } + } + } + + /** + * Returns true if the union of the given collections of properties and references have unique Java types + */ + private boolean calcPropRefUniqueness( + Collection<JavaMappedProperty<?>> props, + Collection<JavaMappedReference> refs) { + + Class[] classes = new Class[props.size() + refs.size()]; + int i = 0; + for (JavaMappedProperty<?> property : props) { + classes[i] = property.getJavaType(); + i++; + } + for (JavaMappedReference reference : refs) { + classes[i] = reference.getServiceContract().getInterfaceClass(); + i++; + } + return implService.areUnique(classes); + } + + /** + * Unambiguously finds the reference or property associated with the given type + * + * @return the name of the reference or property if found, null if not + * @throws AmbiguousConstructorException if the constructor parameter cannot be resolved to a property or reference + */ + private String findReferenceOrProperty( + Class<?> type, + Map<String, JavaMappedProperty<?>> props, + Map<String, JavaMappedReference> refs) throws AmbiguousConstructorException { + + String name = null; + for (JavaMappedProperty<?> property : props.values()) { + if (property.getJavaType().equals(type)) { + if (name != null) { + AmbiguousConstructorException e = + new AmbiguousConstructorException("Ambiguous property or reference for constructor type"); + e.setIdentifier(type.getName()); + throw e; + } + name = property.getName(); + // do not break since ambiguities must be checked, i.e. more than one prop or ref of the same type + } + } + for (JavaMappedReference reference : refs.values()) { + if (reference.getServiceContract().getInterfaceClass().equals(type)) { + if (name != null) { + AmbiguousConstructorException e = + new AmbiguousConstructorException("Ambiguous property or reference for constructor type"); + e.setIdentifier(type.getName()); + throw e; + } + name = reference.getName(); + // do not break since ambiguities must be checked, i.e. more than one prop or ref of the same type + } + } + return name; + } + + /** + * Returns true if a given type is reference according to the SCA specification rules for determining reference + * types + */ + private boolean isReferenceType(Type operationType) { + Class<?> rawType; + Class<?> referenceType = null; + if (operationType instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) operationType; + rawType = (Class<?>) parameterizedType.getRawType(); + Type[] typeArgs = parameterizedType.getActualTypeArguments(); + if (typeArgs.length == 1) { + referenceType = (Class<?>) typeArgs[0]; + } + } else { + rawType = (Class<?>) operationType; + } + if (rawType.isArray()) { + referenceType = rawType.getComponentType(); + } else if (Collection.class.isAssignableFrom(rawType) && referenceType == null) { + return true; + } + if (referenceType != null) { + return referenceType.getAnnotation(Remotable.class) != null + || referenceType.getAnnotation(Service.class) != null; + } else { + return rawType.getAnnotation(Remotable.class) != null || rawType.getAnnotation(Service.class) != null; + } + } + + /** + * Returns true if the given operation is defined in the collection of service interfaces + */ + private boolean isInServiceInterface(Method operation, Map<String, JavaMappedService> services) { + for (JavaMappedService service : services.values()) { + Class<?> clazz = service.getServiceContract().getInterfaceClass(); + if (operation.getDeclaringClass().equals(clazz)) { + return true; + } + Method[] methods = service.getServiceContract().getInterfaceClass().getMethods(); + for (Method method : methods) { + if (operation.getName().equals(method.getName()) + && operation.getParameterTypes().length == method.getParameterTypes().length) { + Class<?>[] methodTypes = method.getParameterTypes(); + for (int i = 0; i < operation.getParameterTypes().length; i++) { + Class<?> paramType = operation.getParameterTypes()[i]; + if (!paramType.equals(methodTypes[i])) { + break; + } else if (i == operation.getParameterTypes().length - 1) { + return true; + } + } + } + } + } + return false; + } + + /** + * Creates a mapped reference + * + * @param name the reference name + * @param member the injection site the reference maps to + * @param paramType the service interface of the reference + */ + private JavaMappedReference createReference(String name, Member member, Class<?> paramType) + throws ProcessingException { + return implService.createReference(name, member, paramType); + } + + /** + * Creates a mapped property + * + * @param name the property name + * @param member the injection site the reference maps to + * @param paramType the property type + */ + private <T> JavaMappedProperty<T> createProperty(String name, Member member, Class<T> paramType) { + JavaMappedProperty<T> property = new JavaMappedProperty<T>(); + property.setName(name); + property.setMember(member); + property.setOverride(OverrideOptions.MAY); + property.setJavaType(paramType); + return property; + } + + /** + * Populates a component type with a service whose interface type is determined by examining all implemented + * interfaces of the given class and chosing one whose operations match all of the class's non-property and + * non-reference methods + * + * @param clazz the class to examine + * @param type the component type + * @param methods all methods in the class to examine + */ + private void calculateServiceInterface( + Class<?> clazz, + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + Set<Method> methods) throws ProcessingException { + List<Method> nonPropRefMethods = new ArrayList<Method>(); + // Map<String, JavaMappedService> services = type.getServices(); + Map<String, JavaMappedReference> references = type.getReferences(); + Map<String, JavaMappedProperty<?>> properties = type.getProperties(); + // calculate methods that are not properties or references + for (Method method : methods) { + String name = toPropertyName(method.getName()); + if (!references.containsKey(name) && !properties.containsKey(name)) { + nonPropRefMethods.add(method); + } + } + // determine if an implemented interface matches all of the non-property and non-reference methods + Class[] interfaces = clazz.getInterfaces(); + if (interfaces.length == 0) { + return; + } + for (Class interfaze : interfaces) { + if (analyzeInterface(interfaze, nonPropRefMethods)) { + JavaMappedService service; + try { + service = implService.createService(interfaze); + } catch (InvalidServiceContractException e) { + throw new ProcessingException(e); + } + type.getServices().put(service.getName(), service); + } + } + } + + /** + * Determines if the methods of a given interface match the given list of methods + * + * @param interfaze the interface to examine + * @param nonPropRefMethods the list of methods to match against + * @return true if the interface matches + */ + private boolean analyzeInterface(Class<?> interfaze, List<Method> nonPropRefMethods) { + Method[] interfaceMethods = interfaze.getMethods(); + if (nonPropRefMethods.size() != interfaceMethods.length) { + return false; + } + for (Method method : nonPropRefMethods) { + boolean found = false; + for (Method interfaceMethod : interfaceMethods) { + if (interfaceMethod.getName().equals(method.getName())) { + Class<?>[] interfaceParamTypes = interfaceMethod.getParameterTypes(); + Class<?>[] methodParamTypes = method.getParameterTypes(); + if (interfaceParamTypes.length == methodParamTypes.length) { + if (interfaceParamTypes.length == 0) { + found = true; + } else { + for (int i = 0; i < methodParamTypes.length; i++) { + Class<?> param = methodParamTypes[i]; + if (!param.equals(interfaceParamTypes[i])) { + break; + } + if (i == methodParamTypes.length - 1) { + found = true; + } + } + } + } + if (found) { + break; + } + } + } + if (!found) { + return false; + } + } + return true; + } + +} + +/* + * 1) public setter methods that are not included in any service interface 2) protected setter methods 3) public or + * protected fields unless there is a setter method for the same name If the type associated with the member is an array + * or a java.util.Collection, then the basetype will be the element type of the array or the parameterized type of the + * Collection, otherwise the basetype will be the member type. If the basetype is an interface with an @Remotable or + * @Service annotation then the member will be defined as a reference, otherwise it will be defined as a property. + * + * + */ diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalCallbackReferenceException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalCallbackReferenceException.java new file mode 100644 index 0000000000..7ad5b7e526 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalCallbackReferenceException.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.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an illegcal use of {@link org.osoa.sca.annotations.Callback} on a reference + * + * @version $Rev$ $Date$ + */ +public class IllegalCallbackReferenceException extends ProcessingException { + public IllegalCallbackReferenceException() { + } + + public IllegalCallbackReferenceException(String message) { + super(message); + } + + public IllegalCallbackReferenceException(String message, Throwable cause) { + super(message, cause); + } + + public IllegalCallbackReferenceException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalContextException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalContextException.java new file mode 100644 index 0000000000..9c64b3dee8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalContextException.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.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an illegal signature for a method decorated with {@link org.osoa.sca.annotations.Context} + * + * @version $Rev$ $Date$ + */ +public class IllegalContextException extends ProcessingException { + public IllegalContextException() { + } + + public IllegalContextException(String message) { + super(message); + } + + public IllegalContextException(String message, Throwable cause) { + super(message, cause); + } + + public IllegalContextException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalDestructorException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalDestructorException.java new file mode 100644 index 0000000000..b412a38bb9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalDestructorException.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.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an illegal signature for a method decorated with {@link org.osoa.sca.annotations.Destroy} + * + * @version $Rev$ $Date$ + */ +public class IllegalDestructorException extends ProcessingException { + public IllegalDestructorException() { + } + + public IllegalDestructorException(String message) { + super(message); + } + + public IllegalDestructorException(String message, Throwable cause) { + super(message, cause); + } + + public IllegalDestructorException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalInitException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalInitException.java new file mode 100644 index 0000000000..615a81926c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalInitException.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.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an illegal signature for a method decorated with {@link @org.osoa.sca.annotations.Init} + * + * @version $Rev$ $Date$ + */ +public class IllegalInitException extends ProcessingException { + public IllegalInitException() { + } + + public IllegalInitException(String message) { + super(message); + } + + public IllegalInitException(String message, Throwable cause) { + super(message, cause); + } + + public IllegalInitException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalReferenceException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalReferenceException.java new file mode 100644 index 0000000000..10a75baaa5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalReferenceException.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.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an illegal reference definition in a component type + * + * @version $Rev$ $Date$ + */ +public class IllegalReferenceException extends ProcessingException { + public IllegalReferenceException() { + } + + public IllegalReferenceException(String message) { + super(message); + } + + public IllegalReferenceException(String message, Throwable cause) { + super(message, cause); + } + + public IllegalReferenceException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalServiceDefinitionException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalServiceDefinitionException.java new file mode 100644 index 0000000000..60fd13a3e5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/IllegalServiceDefinitionException.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.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an illegal use of the {@link @org.osoa.sca.annotations.Service} annotation + * + * @version $Rev$ $Date$ + */ +public class IllegalServiceDefinitionException extends ProcessingException { + public IllegalServiceDefinitionException() { + } + + public IllegalServiceDefinitionException(String message) { + super(message); + } + + public IllegalServiceDefinitionException(String message, Throwable cause) { + super(message, cause); + } + + public IllegalServiceDefinitionException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceImpl.java new file mode 100644 index 0000000000..2c2b40bc3e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceImpl.java @@ -0,0 +1,339 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Member; +import java.util.List; +import javax.xml.namespace.QName; + +import org.osoa.sca.annotations.Callback; +import org.osoa.sca.annotations.Property; +import org.osoa.sca.annotations.Reference; +import org.osoa.sca.annotations.Remotable; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.implementation.java.DuplicatePropertyException; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.model.OverrideOptions; +import org.apache.tuscany.spi.model.ServiceContract; + +import org.apache.tuscany.core.idl.java.IllegalCallbackException; +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getBaseName; + +/** + * The default implementation of an <code>ImplementationProcessorService</code> + * + * @version $Rev$ $Date$ + */ +public class ImplementationProcessorServiceImpl implements ImplementationProcessorService { + private JavaInterfaceProcessorRegistry registry; + + public ImplementationProcessorServiceImpl(@Autowire JavaInterfaceProcessorRegistry registry) { + this.registry = registry; + } + + public JavaMappedService createService(Class<?> interfaze) throws InvalidServiceContractException { + JavaMappedService service = new JavaMappedService(); + service.setName(getBaseName(interfaze)); + service.setRemotable(interfaze.getAnnotation(Remotable.class) != null); + ServiceContract<?> contract = registry.introspect(interfaze); + service.setServiceContract(contract); + return service; + } + + public void processCallback(Class<?> interfaze, ServiceContract<?> contract) throws IllegalCallbackException { + Callback callback = interfaze.getAnnotation(Callback.class); + if (callback != null && !Void.class.equals(callback.value())) { + Class<?> callbackClass = callback.value(); + contract.setCallbackClass(callbackClass); + contract.setCallbackName(getBaseName(callbackClass)); + } else if (callback != null && Void.class.equals(callback.value())) { + IllegalCallbackException e = new IllegalCallbackException( + "Callback annotation must specify an interface on service type"); + e.setIdentifier(interfaze.getName()); + throw e; + } + } + + public boolean areUnique(Class[] collection) { + if (collection.length == 0) { + return true; + } + return areUnique(collection, 0); + } + + public void addName(List<String> names, int pos, String name) { + if (names.size() < pos) { + for (int i = 0; i < pos; i++) { + names.add(i, ""); + } + names.add(name); + } else if (names.size() > pos) { + names.remove(pos); + names.add(pos, name); + } else { + names.add(pos, name); + } + } + + public boolean processParam( + Class<?> param, + Annotation[] paramAnnotations, + String[] constructorNames, + int pos, + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + List<String> injectionNames) throws ProcessingException { + boolean processed = false; + for (Annotation annot : paramAnnotations) { + if (Autowire.class.equals(annot.annotationType())) { + processed = true; + processAutowire(annot, constructorNames, pos, param, type, injectionNames); + } else if (Property.class.equals(annot.annotationType())) { + processed = true; + processProperty(annot, constructorNames, pos, type, param, injectionNames); + } else if (Reference.class.equals(annot.annotationType())) { + processed = true; + processReference(annot, constructorNames, pos, type, param, injectionNames); + } + } + return processed; + } + + public boolean injectionAnnotationsPresent(Annotation[][] annots) { + for (Annotation[] annotations : annots) { + for (Annotation annotation : annotations) { + Class<? extends Annotation> annotType = annotation.annotationType(); + if (annotType.equals(Autowire.class) || annotType.equals(Property.class) + || annotType.equals(Reference.class)) { + return true; + } + } + } + return false; + } + + /** + * Determines if all the members of a collection have unique types + * + * @param collection the collection to analyze + * @param start the position in the collection to start + * @return true if the types are unique + */ + private boolean areUnique(Class[] collection, int start) { + Object compare = collection[start]; + for (int i = start + 1; i < collection.length; i++) { + if (compare.equals(collection[i])) { + return false; + } + } + if (start + 1 < collection.length) { + return areUnique(collection, start + 1); + } else { + return true; + } + } + + /** + * Processes autowire metadata for a constructor parameter + * + * @param annot the autowire annotation + * @param constructorNames the parameter names as specified in an {@link org.osoa.sca.annotations.Constructor} + * annotation + * @param pos the position of the parameter in the constructor's parameter list + * @param param the parameter type + * @param type the component type associated with the implementation being processed + * @param injectionNames the collection of injection names to update + * @throws InvalidAutowireException + * @throws InvalidConstructorException + */ + private void processAutowire( + Annotation annot, + String[] constructorNames, + int pos, + Class<?> param, + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + List<String> injectionNames) throws InvalidAutowireException, InvalidConstructorException { + // the param is marked as an autowire + Autowire autowireAnnot = (Autowire) annot; + JavaMappedReference reference = new JavaMappedReference(); + reference.setAutowire(true); + String name = autowireAnnot.name(); + if (name == null || name.length() == 0) { + if (constructorNames.length > 1 && (constructorNames.length < pos + 1 || constructorNames[pos] == null)) { + throw new InvalidAutowireException("Names in @Constructor and autowire parameter do not match at " + + (pos + 1)); + } else if (constructorNames.length == 1 && constructorNames[0].length() == 0) { + // special case when @Constructor present with all autowire params not specifying any name + name = param.getName() + String.valueOf(pos); + } else if (constructorNames.length == 1 + && (constructorNames.length < pos + 1 || constructorNames[pos] == null)) { + throw new InvalidAutowireException("Names in @Constructor and autowire parameter do not match at " + + (pos + 1)); + } else if (constructorNames.length == 1 && constructorNames[0].length() > 0) { + name = constructorNames[pos]; + } else if (constructorNames.length == 0 || constructorNames[pos].length() == 0) { + name = param.getName() + String.valueOf(pos); + } else { + name = constructorNames[pos]; + } + } else if (pos < constructorNames.length && constructorNames[pos] != null + && constructorNames[pos].length() != 0 && !name.equals(constructorNames[pos])) { + throw new InvalidConstructorException("Name specified by @Constructor does not match autowire name at " + + (pos + 1)); + } + reference.setName(name); + + reference.setRequired(autowireAnnot.required()); + + ServiceContract<?> contract = new JavaServiceContract(); + contract.setInterfaceClass(param); + reference.setServiceContract(contract); + type.getReferences().put(name, reference); + addName(injectionNames, pos, name); + } + + /** + * Processes parameter metadata for a constructor parameter + * + * @param annot the parameter annotation + * @param constructorNames the parameter names as specified in an {@link org.osoa.sca.annotations.Constructor} + * annotation + * @param pos the position of the parameter in the constructor's parameter list + * @param type the component type associated with the implementation being processed + * @param param the parameter type + * @param explicitNames the collection of injection names to update + * @throws ProcessingException + */ + private <T> void processProperty( + Annotation annot, + String[] constructorNames, + int pos, + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + Class<T> param, + List<String> explicitNames) throws ProcessingException { + // TODO multiplicity + // the param is marked as a property + Property propAnnot = (Property) annot; + JavaMappedProperty<T> property = new JavaMappedProperty<T>(); + String name = propAnnot.name(); + if (name == null || name.length() == 0) { + if (constructorNames.length < pos + 1 || constructorNames[pos] == null + || constructorNames[pos].length() == 0) { + throw new InvalidPropertyException("No name specified for property parameter " + (pos + 1)); + } + name = constructorNames[pos]; + } else if (pos < constructorNames.length && constructorNames[pos] != null + && constructorNames[pos].length() != 0 && !name.equals(constructorNames[pos])) { + throw new InvalidConstructorException("Name specified by @Constructor does not match property name at " + + (pos + 1)); + } + if (type.getProperties().get(name) != null) { + throw new DuplicatePropertyException(name); + } + property.setName(name); + property.setOverride(OverrideOptions.valueOf(propAnnot.override().toUpperCase())); + + property.setXmlType(QName.valueOf(propAnnot.xmlType())); + property.setJavaType(param); + type.getProperties().put(name, property); + addName(explicitNames, pos, name); + } + + /** + * Processes reference metadata for a constructor parameter + * + * @param annot the parameter annotation + * @param constructorNames the parameter names as specified in an {@link org.osoa.sca.annotations.Constructor} + * annotation + * @param pos the position of the parameter in the constructor's parameter list + * @param type the component type associated with the implementation being processed + * @param param the parameter type + * @param explicitNames the collection of injection names to update + * @throws ProcessingException + */ + private void processReference( + Annotation annot, + String[] constructorNames, + int pos, + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + Class<?> param, + List<String> explicitNames) throws ProcessingException { + + // TODO multiplicity + // the param is marked as a reference + Reference refAnnotation = (Reference) annot; + JavaMappedReference reference = new JavaMappedReference(); + String name = refAnnotation.name(); + if (name == null || name.length() == 0) { + if (constructorNames.length < pos + 1 || constructorNames[pos] == null + || constructorNames[pos].length() == 0) { + throw new InvalidReferenceException("No name specified for reference parameter " + (pos + 1)); + } + name = constructorNames[pos]; + } else if (pos < constructorNames.length && constructorNames[pos] != null + && constructorNames[pos].length() != 0 && !name.equals(constructorNames[pos])) { + throw new InvalidConstructorException("Name specified by @Constructor does not match reference name at " + + (pos + 1)); + } + if (type.getReferences().get(name) != null) { + throw new DuplicateReferenceException(name); + } + reference.setName(name); + reference.setRequired(refAnnotation.required()); + try { + ServiceContract<?> contract = registry.introspect(param); + reference.setServiceContract(contract); + } catch (InvalidServiceContractException e) { + throw new ProcessingException(e); + } + type.getReferences().put(name, reference); + addName(explicitNames, pos, name); + } + + public JavaMappedReference createReference(String name, Member member, Class<?> paramType) + throws ProcessingException { + JavaMappedReference reference = new JavaMappedReference(); + reference.setName(name); + reference.setMember(member); + reference.setRequired(false); + ServiceContract contract = null; + try { + contract = registry.introspect(paramType); + } catch (InvalidServiceContractException e1) { + throw new ProcessingException(e1); + } + try { + processCallback(paramType, contract); + } catch (IllegalCallbackException e) { + throw new ProcessingException(e); + } + reference.setServiceContract(contract); + return reference; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InitProcessor.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InitProcessor.java new file mode 100644 index 0000000000..cf32e8b855 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InitProcessor.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.osoa.sca.annotations.Init; + +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; + +/** + * Processes the {@link @Init} annotation on a component implementation and updates the component type with the + * decorated initializer method + * + * @version $Rev$ $Date$ + */ +public class InitProcessor extends ImplementationProcessorExtension { + + public void visitMethod(CompositeComponent parent, Method method, + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + DeploymentContext context) + throws ProcessingException { + Init annotation = method.getAnnotation(Init.class); + if (annotation == null) { + return; + } + if (method.getParameterTypes().length != 0) { + IllegalInitException e = new IllegalInitException("Initializer must not have argments"); + e.setIdentifier(method.toString()); + throw e; + } + if (type.getInitMethod() != null) { + throw new DuplicateInitException("More than one initializer found on implementaton"); + } + if (Modifier.isProtected(method.getModifiers())) { + method.setAccessible(true); + } + type.setEagerInit(annotation.eager()); + type.setInitMethod(method); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidAutowireException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidAutowireException.java new file mode 100644 index 0000000000..1a46b22d8d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidAutowireException.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.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an invalid usage of {@link org.apache.tuscany.spi.annotation.Autowire} + * + * @version $Rev$ $Date$ + */ +public class InvalidAutowireException extends ProcessingException { + + public InvalidAutowireException() { + } + + public InvalidAutowireException(String message) { + super(message); + } + + public InvalidAutowireException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidAutowireException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConstructorException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConstructorException.java new file mode 100644 index 0000000000..ded7b8886a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidConstructorException.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.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an invalid constructor definition, e.g. when the number of injection names specified in {@link + * org.osoa.sca.annotations.Constructor} do not match the number of actual constructor parameters + * + * @version $Rev$ $Date$ + */ +public class InvalidConstructorException extends ProcessingException { + public InvalidConstructorException() { + } + + public InvalidConstructorException(String message) { + super(message); + } + + public InvalidConstructorException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidConstructorException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidPropertyException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidPropertyException.java new file mode 100644 index 0000000000..7a45d22605 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidPropertyException.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.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an invalid usage of {@link org.osoa.sca.annotations.Property} + * + * @version $Rev$ $Date$ + */ +public class InvalidPropertyException extends ProcessingException { + + public InvalidPropertyException() { + } + + public InvalidPropertyException(String message) { + super(message); + } + + public InvalidPropertyException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidPropertyException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidReferenceException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidReferenceException.java new file mode 100644 index 0000000000..634acaaaed --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidReferenceException.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.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Denotes an invalid usage of {@link org.osoa.sca.annotations.Reference} + * + * @version $Rev$ $Date$ + */ +public class InvalidReferenceException extends ProcessingException { + + public InvalidReferenceException() { + } + + public InvalidReferenceException(String message) { + super(message); + } + + public InvalidReferenceException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidReferenceException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidServiceType.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidServiceType.java new file mode 100644 index 0000000000..36936acbfb --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/InvalidServiceType.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.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Thrown when a service type specified by an {@link org.osoa.sca.annotations.Service} annotation is invalid, e.g. it is + * not an interface + * + * @version $Rev$ $Date$ + */ +public class InvalidServiceType extends ProcessingException { + public InvalidServiceType() { + } + + public InvalidServiceType(String message) { + super(message); + } + + public InvalidServiceType(String message, Throwable cause) { + super(message, cause); + } + + public InvalidServiceType(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/MonitorProcessor.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/MonitorProcessor.java new file mode 100644 index 0000000000..e7acce2973 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/MonitorProcessor.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.implementation.java.AbstractPropertyProcessor; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; + +import org.apache.tuscany.api.annotation.Monitor; +import org.apache.tuscany.core.injection.SingletonObjectFactory; +import org.apache.tuscany.host.MonitorFactory; + +/** + * Processes an {@link @Monitor} annotation, updating the component type with corresponding {@link + * org.apache.tuscany.spi.implementation.java.JavaMappedProperty} + * + * @version $Rev$ $Date$ + */ +public class MonitorProcessor extends AbstractPropertyProcessor<Monitor> { + private MonitorFactory monitorFactory; + + public MonitorProcessor(@Autowire MonitorFactory monitorFactory, @Autowire ImplementationProcessorService service) { + super(Monitor.class, service); + this.monitorFactory = monitorFactory; + } + + protected String getName(Monitor annotation) { + return null; + } + + protected <T> void initProperty(JavaMappedProperty<T> property, + Monitor annotation, + CompositeComponent parent, + DeploymentContext context) { + Class<T> javaType = property.getJavaType(); + property.setDefaultValueFactory(new SingletonObjectFactory<T>(monitorFactory.getMonitor(javaType))); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/NoConstructorException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/NoConstructorException.java new file mode 100644 index 0000000000..78a9c6b503 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/NoConstructorException.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.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Thrown when a suitable constructor for a component implementation cannot be found + * + * @version $Rev$ $Date$ + */ +public class NoConstructorException extends ProcessingException { + + public NoConstructorException() { + } + + public NoConstructorException(String message) { + super(message); + } + + public NoConstructorException(String message, Throwable cause) { + super(message, cause); + } + + public NoConstructorException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/PropertyProcessor.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/PropertyProcessor.java new file mode 100644 index 0000000000..09b3c7383d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/PropertyProcessor.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Constructor; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.idl.TypeInfo; +import org.apache.tuscany.spi.implementation.java.AbstractPropertyProcessor; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.model.OverrideOptions; +import org.osoa.sca.annotations.Property; + +/** + * Processes an {@link @Property} annotation, updating the component type with corresponding {@link JavaMappedProperty} + * + * @version $Rev$ $Date$ + */ +public class PropertyProcessor extends AbstractPropertyProcessor<Property> { + private SimpleTypeMapperExtension typeMapper = new SimpleTypeMapperExtension(); + + public PropertyProcessor(@Autowire ImplementationProcessorService service) { + super(Property.class, service); + } + + protected String getName(Property annotation) { + return annotation.name(); + } + + protected <T> void initProperty(JavaMappedProperty<T> property, + Property annotation, + CompositeComponent parent, + DeploymentContext context) { + property.setOverride(OverrideOptions.valueOf(annotation.override().toUpperCase())); + String xmlType = annotation.xmlType(); + if (xmlType != null && xmlType.length() != 0) { + property.setXmlType(QName.valueOf(annotation.xmlType())); + } else { + TypeInfo type = typeMapper.getXMLType(property.getJavaType()); + if (type != null) { + property.setXmlType(type.getQName()); + } + } + } + + public <T> void visitConstructor(CompositeComponent parent, Constructor<T> constructor, + PojoComponentType<JavaMappedService, JavaMappedReference, + JavaMappedProperty<?>> type, + DeploymentContext context) throws ProcessingException { + // override since heuristic pojo processor evalautes properties + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ReferenceProcessor.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ReferenceProcessor.java new file mode 100644 index 0000000000..d96f31023b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ReferenceProcessor.java @@ -0,0 +1,155 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import org.osoa.sca.annotations.Reference; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.model.ServiceContract; + +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.toPropertyName; + +/** + * Processes an {@link @Reference} annotation, updating the component type with corresponding {@link + * org.apache.tuscany.spi.implementation.java.JavaMappedReference} + * + * @version $Rev$ $Date$ + */ +public class ReferenceProcessor extends ImplementationProcessorExtension { + + private JavaInterfaceProcessorRegistry regsitry; + + public ReferenceProcessor(@Autowire JavaInterfaceProcessorRegistry registry) { + this.regsitry = registry; + } + + public void visitMethod(CompositeComponent parent, Method method, + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + DeploymentContext context) + throws ProcessingException { + Reference annotation = method.getAnnotation(Reference.class); + Autowire autowire = method.getAnnotation(Autowire.class); + boolean isAutowire = autowire != null; + if (annotation == null && !isAutowire) { + return; //Not a reference or autowire annotation. + } + if (method.getParameterTypes().length != 1) { + IllegalReferenceException e = new IllegalReferenceException("Setter must have one parameter"); + e.setIdentifier(method.toString()); + throw e; + } + //process autowire required first let reference override. or if conflicting should this fault? + boolean required = false; + if (isAutowire) { + required = autowire.required(); + } + + String name = null; + + if (annotation != null) { + if (annotation.name() != null && annotation.name().length() > 0) { + name = annotation.name(); + } + required = annotation.required(); + } + if (name == null) { + name = method.getName(); + if (method.getName().startsWith("set")) { + name = toPropertyName(method.getName()); + } + } + if (type.getReferences().get(name) != null) { + throw new DuplicateReferenceException(name); + } + + JavaMappedReference reference = new JavaMappedReference(); + reference.setMember(method); + reference.setAutowire(isAutowire); + reference.setRequired(required); + reference.setName(name); + ServiceContract contract; + try { + contract = regsitry.introspect(method.getParameterTypes()[0]); + } catch (InvalidServiceContractException e) { + throw new ProcessingException(e); + } + reference.setServiceContract(contract); + type.getReferences().put(name, reference); + } + + public void visitField(CompositeComponent parent, Field field, + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + DeploymentContext context) throws ProcessingException { + Reference annotation = field.getAnnotation(Reference.class); + boolean autowire = field.getAnnotation(Autowire.class) != null; + if (annotation == null && !autowire) { + return; + } + String name = field.getName(); + boolean required = false; + if (annotation != null) { + if (annotation.name() != null) { + name = annotation.name(); + } + required = annotation.required(); + } + if (name.length() == 0) { + name = field.getName(); + } + if (type.getReferences().get(name) != null) { + throw new DuplicateReferenceException(name); + } + JavaMappedReference reference = new JavaMappedReference(); + reference.setMember(field); + reference.setRequired(required); + reference.setAutowire(autowire); + reference.setName(name); + ServiceContract contract; + try { + contract = regsitry.introspect(field.getType()); + } catch (InvalidServiceContractException e) { + throw new ProcessingException(e); + } + reference.setServiceContract(contract); + type.getReferences().put(name, reference); + } + + public <T> void visitConstructor(CompositeComponent parent, Constructor<T> constructor, + PojoComponentType<JavaMappedService, JavaMappedReference, + JavaMappedProperty<?>> type, + DeploymentContext context) throws ProcessingException { + + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ScopeProcessor.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ScopeProcessor.java new file mode 100644 index 0000000000..3827a82652 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ScopeProcessor.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.model.Scope; + +/** + * Processes the {@link Scope} annotation and updates the component type with the corresponding implmentation scope + * + * @version $Rev$ $Date$ + */ +public class ScopeProcessor extends ImplementationProcessorExtension { + + public <T> void visitClass(CompositeComponent parent, Class<T> clazz, + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + DeploymentContext context) + throws ProcessingException { + org.osoa.sca.annotations.Scope annotation = clazz.getAnnotation(org.osoa.sca.annotations.Scope.class); + if (annotation == null) { + type.setImplementationScope(Scope.STATELESS); + return; + } + //FIXME deal with eager init + String name = annotation.value(); + Scope scope; + if ("MODULE".equals(name)) { + scope = Scope.MODULE; + } else if ("SESSION".equals(name)) { + scope = Scope.SESSION; + } else if ("REQUEST".equals(name)) { + scope = Scope.REQUEST; + } else if ("COMPOSITE".equals(name)) { + scope = Scope.COMPOSITE; + } else { + scope = new Scope(name); + } + type.setImplementationScope(scope); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceProcessor.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceProcessor.java new file mode 100644 index 0000000000..5e4e561228 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceProcessor.java @@ -0,0 +1,161 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Set; + +import org.osoa.sca.annotations.Callback; +import org.osoa.sca.annotations.Remotable; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorExtension; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService; +import org.apache.tuscany.spi.model.ServiceContract; + +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getAllInterfaces; +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.toPropertyName; + +/** + * Processes an {@link org.osoa.sca.annotations.Service} annotation and updates the component type with corresponding + * {@link JavaMappedService}s. Also processes related {@link org.osoa.sca.annotations.Callback} annotations. + * + * @version $Rev$ $Date$ + */ +public class ServiceProcessor extends ImplementationProcessorExtension { + + private ImplementationProcessorService implService; + + public ServiceProcessor(@Autowire ImplementationProcessorService implService) { + this.implService = implService; + } + + public <T> void visitClass(CompositeComponent parent, Class<T> clazz, + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + DeploymentContext context) throws ProcessingException { + org.osoa.sca.annotations.Service annotation = clazz.getAnnotation(org.osoa.sca.annotations.Service.class); + if (annotation == null) { + // scan intefaces for remotable + Set<Class> interfaces = getAllInterfaces(clazz); + for (Class<?> interfaze : interfaces) { + if (interfaze.getAnnotation(Remotable.class) != null) { + JavaMappedService service; + try { + service = implService.createService(interfaze); + } catch (InvalidServiceContractException e) { + throw new ProcessingException(e); + } + type.getServices().put(service.getName(), service); + } + } + return; + } + Class<?>[] interfaces = annotation.interfaces(); + if (interfaces.length == 0) { + Class<?> interfaze = annotation.value(); + if (Void.class.equals(interfaze)) { + throw new IllegalServiceDefinitionException("No interfaces specified"); + } else { + interfaces = new Class<?>[1]; + interfaces[0] = interfaze; + } + } + for (Class<?> interfaze : interfaces) { + if (!interfaze.isInterface()) { + InvalidServiceType e = new InvalidServiceType("Service must be an interface"); + e.setIdentifier(interfaze.getName()); + throw e; + } + JavaMappedService service; + try { + service = implService.createService(interfaze); + } catch (InvalidServiceContractException e) { + throw new ProcessingException(e); + } + type.getServices().put(service.getName(), service); + } + } + + + public void visitMethod(CompositeComponent parent, + Method method, + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + DeploymentContext context) throws ProcessingException { + + Callback annotation = method.getAnnotation(Callback.class); + if (annotation == null) { + return; + } + if (method.getParameterTypes().length != 1) { + IllegalCallbackReferenceException e = + new IllegalCallbackReferenceException("Setter must have one parameter"); + e.setIdentifier(method.toString()); + throw e; + } + String name = toPropertyName(method.getName()); + JavaMappedService callbackService = null; + Class<?> callbackClass = method.getParameterTypes()[0]; + for (JavaMappedService service : type.getServices().values()) { + ServiceContract serviceContract = service.getServiceContract(); + if (serviceContract.getCallbackClass().equals(callbackClass)) { + callbackService = service; + } + } + if (callbackService == null) { + throw new IllegalCallbackReferenceException("Callback type does not match a service callback interface"); + } + callbackService.setCallbackReferenceName(name); + callbackService.setCallbackMember(method); + } + + public void visitField(CompositeComponent parent, Field field, + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type, + DeploymentContext context) throws ProcessingException { + + Callback annotation = field.getAnnotation(Callback.class); + if (annotation == null) { + return; + } + String name = field.getName(); + JavaMappedService callbacksService = null; + Class<?> callbackClass = field.getType(); + for (JavaMappedService service : type.getServices().values()) { + ServiceContract serviceContract = service.getServiceContract(); + if (serviceContract.getCallbackClass().equals(callbackClass)) { + callbacksService = service; + } + } + if (callbacksService == null) { + throw new IllegalCallbackReferenceException("Callback type does not match a service callback interface"); + } + callbacksService.setCallbackReferenceName(name); + callbacksService.setCallbackMember(field); + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceTypeNotFoundException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceTypeNotFoundException.java new file mode 100644 index 0000000000..a84e8f3850 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/ServiceTypeNotFoundException.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.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +/** + * Thrown when a service interface cannot be determined based on a heuristic evaluation of an implementation + * + * @version $Rev$ $Date$ + */ +public class ServiceTypeNotFoundException extends ProcessingException { + public ServiceTypeNotFoundException() { + } + + public ServiceTypeNotFoundException(String message) { + super(message); + } + + public ServiceTypeNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public ServiceTypeNotFoundException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/UnknownContextTypeException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/UnknownContextTypeException.java new file mode 100644 index 0000000000..875f10a4fd --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/processor/UnknownContextTypeException.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +/** + * Thrown when a method or field marked with {@link org.osoa.sca.annotations.Context} takes an unknown type + * + * @version $Rev$ $Date$ + */ +public class UnknownContextTypeException extends IllegalContextException { + public UnknownContextTypeException() { + } + + public UnknownContextTypeException(String message) { + super(message); + } + + public UnknownContextTypeException(String message, Throwable cause) { + super(message, cause); + } + + public UnknownContextTypeException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemBindingBuilder.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemBindingBuilder.java new file mode 100644 index 0000000000..059ae0e768 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemBindingBuilder.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.builder; + +import org.apache.tuscany.spi.QualifiedName; +import org.apache.tuscany.spi.builder.BindingBuilder; +import org.apache.tuscany.spi.builder.BuilderConfigException; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.model.BoundReferenceDefinition; +import org.apache.tuscany.spi.model.BoundServiceDefinition; +import org.apache.tuscany.spi.wire.InboundWire; + +import org.apache.tuscany.core.implementation.system.component.SystemReference; +import org.apache.tuscany.core.implementation.system.component.SystemReferenceImpl; +import org.apache.tuscany.core.implementation.system.component.SystemService; +import org.apache.tuscany.core.implementation.system.component.SystemServiceImpl; +import org.apache.tuscany.core.implementation.system.model.SystemBinding; +import org.apache.tuscany.core.implementation.system.wire.SystemInboundWire; +import org.apache.tuscany.core.implementation.system.wire.SystemInboundWireImpl; +import org.apache.tuscany.core.implementation.system.wire.SystemOutboundAutowire; +import org.apache.tuscany.core.implementation.system.wire.SystemOutboundWire; +import org.apache.tuscany.core.implementation.system.wire.SystemOutboundWireImpl; + +/** + * Creates {@link SystemService}s and {@link org.apache.tuscany.core.implementation.system.component.SystemReference}s + * by evaluating an assembly definition + * + * @version $$Rev$$ $$Date$$ + */ +public class SystemBindingBuilder implements BindingBuilder<SystemBinding> { + + public SystemService build(CompositeComponent parent, + BoundServiceDefinition<SystemBinding> boundServiceDefinition, + DeploymentContext deploymentContext) { + Class<?> interfaze = boundServiceDefinition.getServiceContract().getInterfaceClass(); + QualifiedName targetName = new QualifiedName(boundServiceDefinition.getTarget().getPath()); + Component target = (Component) parent.getSystemChild(targetName.getPartName()); + if (target == null) { + throw new BuilderConfigException("Target not found: [" + targetName + ']'); + } + String name = boundServiceDefinition.getName(); + InboundWire inboundWire = + new SystemInboundWireImpl(name, interfaze, target); + SystemOutboundWire outboundWire = + new SystemOutboundWireImpl(name, targetName, interfaze); + SystemService service = new SystemServiceImpl(boundServiceDefinition.getName(), parent); + service.setInboundWire(inboundWire); + service.setOutboundWire(outboundWire); + return service; + } + + public SystemReference build(CompositeComponent parent, + BoundReferenceDefinition<SystemBinding> boundReferenceDefinition, + DeploymentContext deploymentContext) { + CompositeComponent autowireComponent = parent.getParent(); + Class<?> interfaze = boundReferenceDefinition.getServiceContract().getInterfaceClass(); + String name = boundReferenceDefinition.getName(); + SystemReferenceImpl reference = new SystemReferenceImpl(name, interfaze, parent); + SystemInboundWire inboundWire = new SystemInboundWireImpl(name, interfaze); + String refName = boundReferenceDefinition.getName(); + boolean required = boundReferenceDefinition.isRequired(); + SystemOutboundWire outboundWire = new SystemOutboundAutowire(refName, interfaze, autowireComponent, required); + reference.setInboundWire(inboundWire); + reference.setOutboundWire(outboundWire); + return reference; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemComponentBuilder.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemComponentBuilder.java new file mode 100644 index 0000000000..ceff57f9f9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemComponentBuilder.java @@ -0,0 +1,174 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.builder; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.Map; + +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.QualifiedName; +import org.apache.tuscany.spi.builder.BuilderConfigException; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.ComponentBuilderExtension; +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.PropertyValue; +import org.apache.tuscany.spi.model.ReferenceDefinition; +import org.apache.tuscany.spi.model.ReferenceTarget; +import org.apache.tuscany.spi.model.ServiceDefinition; +import org.apache.tuscany.spi.wire.OutboundWire; + +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.core.implementation.system.component.SystemAtomicComponentImpl; +import org.apache.tuscany.core.implementation.system.model.SystemImplementation; +import org.apache.tuscany.core.implementation.system.wire.SystemInboundWire; +import org.apache.tuscany.core.implementation.system.wire.SystemInboundWireImpl; +import org.apache.tuscany.core.implementation.system.wire.SystemOutboundAutowire; +import org.apache.tuscany.core.implementation.system.wire.SystemOutboundWireImpl; +import org.apache.tuscany.core.injection.MethodEventInvoker; +import org.apache.tuscany.core.injection.PojoObjectFactory; + +/** + * Produces system atomic components from a component definition + * + * @version $$Rev$$ $$Date$$ + */ +public class SystemComponentBuilder extends ComponentBuilderExtension<SystemImplementation> { + + protected Class<SystemImplementation> getImplementationType() { + return SystemImplementation.class; + } + + @SuppressWarnings("unchecked") + public AtomicComponent build(CompositeComponent parent, + ComponentDefinition<SystemImplementation> definition, + DeploymentContext deploymentContext) throws BuilderConfigException { + PojoComponentType<ServiceDefinition, JavaMappedReference, JavaMappedProperty<?>> componentType = + definition.getImplementation().getComponentType(); + + PojoConfiguration configuration = new PojoConfiguration(); + configuration.setParent(parent); + configuration.setScopeContainer(deploymentContext.getModuleScope()); + if (definition.getInitLevel() != null) { + configuration.setInitLevel(definition.getInitLevel()); + } else { + configuration.setInitLevel(componentType.getInitLevel()); + } + Method initMethod = componentType.getInitMethod(); + if (initMethod != null) { + configuration.setInitInvoker(new MethodEventInvoker<Object>(initMethod)); + } + Method destroyMethod = componentType.getDestroyMethod(); + if (destroyMethod != null) { + configuration.setDestroyInvoker(new MethodEventInvoker<Object>(destroyMethod)); + } + for (ServiceDefinition serviceDefinition : componentType.getServices().values()) { + configuration.addServiceInterface(serviceDefinition.getServiceContract().getInterfaceClass()); + } + // setup property injection sites + for (JavaMappedProperty<?> property : componentType.getProperties().values()) { + configuration.addPropertySite(property.getName(), property.getMember()); + } + // setup reference injection sites + for (JavaMappedReference reference : componentType.getReferences().values()) { + Member member = reference.getMember(); + if (member != null) { + // could be null if the reference is mapped to a constructor + configuration.addReferenceSite(reference.getName(), member); + } + } + // setup constructor injection + ConstructorDefinition<?> ctorDef = componentType.getConstructorDefinition(); + Constructor<?> constr = ctorDef.getConstructor(); + PojoObjectFactory<?> instanceFactory = new PojoObjectFactory(constr); + configuration.setInstanceFactory(instanceFactory); + configuration.getConstructorParamNames().addAll(ctorDef.getInjectionNames()); + SystemAtomicComponentImpl component = new SystemAtomicComponentImpl(definition.getName(), configuration); + // handle properties + Map<String, PropertyValue<?>> propertyValues = definition.getPropertyValues(); + processProperties(propertyValues, componentType.getProperties().values(), component); + // handle inbound wires + for (ServiceDefinition serviceDefinition : componentType.getServices().values()) { + Class<?> interfaze = serviceDefinition.getServiceContract().getInterfaceClass(); + String name = serviceDefinition.getName(); + SystemInboundWire wire = new SystemInboundWireImpl(name, interfaze, component); + component.addInboundWire(wire); + } + // handle references + processReferences(definition, componentType.getReferences(), parent, component); + // FIXME we need a way to build configuration references from autowires in the loader to eliminate this eval + for (ReferenceDefinition reference : componentType.getReferences().values()) { + if (reference.isAutowire()) { + Class interfaze = reference.getServiceContract().getInterfaceClass(); + OutboundWire wire = + new SystemOutboundAutowire(reference.getName(), interfaze, parent, reference.isRequired()); + component.addOutboundWire(wire); + } + } + return component; + } + + private void processReferences(ComponentDefinition<SystemImplementation> definition, + Map<String, JavaMappedReference> references, + CompositeComponent parent, + SystemAtomicComponentImpl component) { + // no proxies needed for system components + for (ReferenceTarget target : definition.getReferenceTargets().values()) { + String referenceName = target.getReferenceName(); + JavaMappedReference referenceDefiniton = references.get(referenceName); + Class interfaze = referenceDefiniton.getServiceContract().getInterfaceClass(); + OutboundWire wire; + if (referenceDefiniton.isAutowire()) { + boolean required = referenceDefiniton.isRequired(); + wire = new SystemOutboundAutowire(referenceName, interfaze, parent, required); + } else { + //FIXME support multiplicity! + assert target.getTargets().size() == 1 : "Multiplicity not yet implemented"; + QualifiedName targetName = new QualifiedName(target.getTargets().get(0).getPath()); + wire = new SystemOutboundWireImpl(referenceName, targetName, interfaze); + } + component.addOutboundWire(wire); + } + } + + private void processProperties(Map<String, PropertyValue<?>> propertyValues, + Collection<JavaMappedProperty<?>> properties, + SystemAtomicComponentImpl component) { + for (JavaMappedProperty<?> property : properties) { + PropertyValue value = propertyValues.get(property.getName()); + ObjectFactory<?> factory; + if (value != null) { + factory = value.getValueFactory(); + } else { + factory = property.getDefaultValueFactory(); + } + if (factory != null) { + component.addPropertyFactory(property.getName(), factory); + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemCompositeBuilder.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemCompositeBuilder.java new file mode 100644 index 0000000000..77fc5bf17c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/builder/SystemCompositeBuilder.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.core.implementation.system.builder; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.spi.builder.BuilderConfigException; +import org.apache.tuscany.spi.builder.BuilderRegistry; +import org.apache.tuscany.spi.builder.Connector; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.ComponentBuilderExtension; +import org.apache.tuscany.spi.model.Binding; +import org.apache.tuscany.spi.model.BoundServiceDefinition; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.Implementation; +import org.apache.tuscany.spi.model.ServiceDefinition; + +import org.apache.tuscany.core.implementation.composite.CompositeComponentImpl; +import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation; + +/** + * Produces system composite components by evaluating an assembly. + * + * @version $Rev$ $Date$ + */ +public class SystemCompositeBuilder extends ComponentBuilderExtension<SystemCompositeImplementation> { + public SystemCompositeBuilder() { + } + + public SystemCompositeBuilder(BuilderRegistry builderRegistry, Connector connector) { + this.builderRegistry = builderRegistry; + this.connector = connector; + } + + protected Class<SystemCompositeImplementation> getImplementationType() { + return SystemCompositeImplementation.class; + } + + public Component build(CompositeComponent parent, + ComponentDefinition<SystemCompositeImplementation> componentDefinition, + DeploymentContext deploymentContext) throws BuilderConfigException { + SystemCompositeImplementation impl = componentDefinition.getImplementation(); + CompositeComponentType<?, ?, ?> componentType = impl.getComponentType(); + + // create lists of all components and services in this composite + List<ComponentDefinition<? extends Implementation<?>>> allComponents = + new ArrayList<ComponentDefinition<? extends Implementation<?>>>(); + allComponents.addAll(componentType.getComponents().values()); + + List<BoundServiceDefinition<? extends Binding>> allBoundServices = + new ArrayList<BoundServiceDefinition<? extends Binding>>(); + for (ServiceDefinition serviceDefinition : componentType.getServices().values()) { + if (serviceDefinition instanceof BoundServiceDefinition) { + BoundServiceDefinition<? extends Binding> boundService = + (BoundServiceDefinition<? extends Binding>) serviceDefinition; + allBoundServices.add(boundService); + } + } + + /* + // add in components and services from included composites + for (Include include : componentType.getIncludes().values()) { + CompositeComponentType<?, ?, ?> included = include.getIncluded(); + allComponents.addAll(included.getComponents().values()); + for (ServiceDefinition serviceDefinition : included.getServices().values()) { + if (serviceDefinition instanceof BoundServiceDefinition) { + BoundServiceDefinition<? extends Binding> boundService = + (BoundServiceDefinition<? extends Binding>) serviceDefinition; + allBoundServices.add(boundService); + } + } + } + */ + + // create the composite component + String name = componentDefinition.getName(); + CompositeComponent component = new CompositeComponentImpl(name, parent, connector, null); + for (ComponentDefinition<? extends Implementation> childComponentDefinition : allComponents) { + component.register(builderRegistry.build(component, childComponentDefinition, deploymentContext)); + } + + for (BoundServiceDefinition<? extends Binding> serviceDefinition : allBoundServices) { + component.register(builderRegistry.build(component, serviceDefinition, deploymentContext)); + } + return component; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemAtomicComponentImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemAtomicComponentImpl.java new file mode 100644 index 0000000000..cc9926280c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemAtomicComponentImpl.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.core.implementation.system.component; + +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.component.SystemAtomicComponent; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.wire.RuntimeWire; +import org.apache.tuscany.spi.wire.TargetInvoker; + +import org.apache.tuscany.core.implementation.PojoAtomicComponent; +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.core.implementation.system.wire.SystemOutboundWire; + +/** + * Default implementation of a system atomic context + * + * @version $$Rev$$ $$Date$$ + */ +public class SystemAtomicComponentImpl extends PojoAtomicComponent implements SystemAtomicComponent { + + public SystemAtomicComponentImpl(String name, PojoConfiguration configuration) { + super(name, configuration); + scope = Scope.MODULE; + } + + public Object getServiceInstance(String name) throws TargetException { + return getTargetInstance(); + } + + public Object getServiceInstance() throws TargetException { + return getTargetInstance(); + } + + public TargetInvoker createTargetInvoker(String targetName, Operation operation) { + return null; + } + + public boolean isSystem() { + return true; + } + + protected ObjectFactory<?> createWireFactory(RuntimeWire wire) { + assert wire instanceof SystemOutboundWire : "Wire must be an instance of " + SystemOutboundWire.class.getName(); + SystemOutboundWire systemWire = (SystemOutboundWire) wire; + return new SystemWireObjectFactory(systemWire); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemReference.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemReference.java new file mode 100644 index 0000000000..5c15edb957 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemReference.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.component; + +import org.apache.tuscany.spi.component.Reference; + +/** + * A marker for SCA references configured with the + * {@link org.apache.tuscany.core.implementation.system.model.SystemBinding} + * + * @version $$Rev$$ $$Date$$ + */ +public interface SystemReference extends Reference { +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemReferenceImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemReferenceImpl.java new file mode 100644 index 0000000000..a9a23b028c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemReferenceImpl.java @@ -0,0 +1,115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.component; + +import org.apache.tuscany.spi.component.AbstractSCAObject; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.TargetInvoker; +import org.apache.tuscany.spi.wire.WireInvocationHandler; + +import org.apache.tuscany.core.implementation.system.wire.SystemInboundWire; +import org.apache.tuscany.core.implementation.system.wire.SystemOutboundWire; + +/** + * Default implementation of a reference configured with the + * {@link org.apache.tuscany.core.implementation.system.model.SystemBinding} + * + * @version $Rev$ $Date$ + */ +public class SystemReferenceImpl extends AbstractSCAObject implements SystemReference { + + protected SystemInboundWire inboundWire; + protected SystemOutboundWire outboundWire; + protected Class<?> referenceInterface; + + + public SystemReferenceImpl(String name, Class<?> referenceInterface, CompositeComponent parent) { + super(name, parent); + assert referenceInterface != null : "Reference interface was null"; + this.referenceInterface = referenceInterface; + } + + public Scope getScope() { + return Scope.COMPOSITE; + } + + public void setInboundWire(InboundWire wire) { + assert wire instanceof SystemInboundWire : "Wire must be a " + SystemInboundWire.class.getName(); + this.inboundWire = (SystemInboundWire) wire; + } + + public InboundWire getInboundWire() { + return inboundWire; + } + + public OutboundWire getOutboundWire() { + return outboundWire; + } + + public void setOutboundWire(OutboundWire wire) { + assert wire instanceof SystemOutboundWire : "Wire must be a " + SystemOutboundWire.class.getName(); + this.outboundWire = (SystemOutboundWire) wire; + } + + public Class<?> getInterface() { + return referenceInterface; + } + + public void setInterface(Class<?> referenceInterface) { + this.referenceInterface = referenceInterface; + } + + public Object getServiceInstance() throws TargetException { + return referenceInterface.cast(inboundWire.getTargetService()); + } + + public WireInvocationHandler getHandler() throws TargetException { + throw new UnsupportedOperationException(); + } + + public TargetInvoker createTargetInvoker(ServiceContract contract, Operation operation) { + throw new UnsupportedOperationException(); + } + + public TargetInvoker createCallbackTargetInvoker(ServiceContract contract, Operation operation) { + throw new UnsupportedOperationException(); + } + + public TargetInvoker createAsyncTargetInvoker(OutboundWire wire, Operation operation) { + throw new UnsupportedOperationException(); + } + + public ServiceContract<?> getBindingServiceContract() { + throw new UnsupportedOperationException(); + } + + public void setBindingServiceContract(ServiceContract<?> serviceContract) { + throw new UnsupportedOperationException(); + } + + public boolean isSystem() { + return true; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemService.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemService.java new file mode 100644 index 0000000000..95999c5045 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemService.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.component; + +import org.apache.tuscany.spi.component.Service; + +/** + * Marker for services configured with the {@link org.apache.tuscany.core.implementation.system.model.SystemBinding} + * + * @version $$Rev$$ $$Date$$ + */ +public interface SystemService extends Service { + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemServiceImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemServiceImpl.java new file mode 100644 index 0000000000..1a8cd490ae --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemServiceImpl.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.component; + +import org.apache.tuscany.spi.CoreRuntimeException; +import org.apache.tuscany.spi.component.AbstractSCAObject; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.TargetInvoker; +import org.apache.tuscany.spi.wire.WireInvocationHandler; + +import org.apache.tuscany.core.implementation.system.wire.SystemInboundWire; +import org.apache.tuscany.core.implementation.system.wire.SystemOutboundWire; + +/** + * Default implementation for services configured with the + * {@link org.apache.tuscany.core.implementation.system.model.SystemBinding} + * + * @version $$Rev$$ $$Date$$ + */ +public class SystemServiceImpl extends AbstractSCAObject implements SystemService { + + protected SystemInboundWire inboundWire; + protected SystemOutboundWire outboundWire; + + public SystemServiceImpl(String name, CompositeComponent parent) throws CoreRuntimeException { + super(name, parent); + } + + public Scope getScope() { + return Scope.COMPOSITE; + } + + public InboundWire getInboundWire() { + return inboundWire; + } + + public void setInboundWire(InboundWire wire) { + assert wire instanceof SystemInboundWire : "wire must be a " + SystemInboundWire.class.getName(); + this.inboundWire = (SystemInboundWire) wire; + } + + public OutboundWire getOutboundWire() { + return outboundWire; + } + + public void setOutboundWire(OutboundWire wire) { + assert wire instanceof SystemOutboundWire : "wire must be a " + SystemOutboundWire.class.getName(); + this.outboundWire = (SystemOutboundWire) wire; + } + + public Class<?> getInterface() { + return inboundWire.getServiceContract().getInterfaceClass(); + } + + public WireInvocationHandler getHandler() { + // system services do not proxy + throw new UnsupportedOperationException(); + } + + public Object getServiceInstance() throws TargetException { + return inboundWire.getTargetService(); + } + + + public TargetInvoker createCallbackTargetInvoker(ServiceContract contract, Operation operation) { + throw new UnsupportedOperationException(); + } + + public ServiceContract<?> getBindingServiceContract() { + throw new UnsupportedOperationException(); + } + + public void setBindingServiceContract(ServiceContract<?> serviceContract) { + throw new UnsupportedOperationException(); + } + + public boolean isSystem() { + return true; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemSingletonAtomicComponent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemSingletonAtomicComponent.java new file mode 100644 index 0000000000..a40cc9785c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemSingletonAtomicComponent.java @@ -0,0 +1,131 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.component; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.component.AbstractSCAObject; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.component.SystemAtomicComponent; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.TargetInvoker; + +/** + * An {@link org.apache.tuscany.spi.component.AtomicComponent} used when registering objects directly into a composite + * + * @version $$Rev$$ $$Date$$ + */ +public class SystemSingletonAtomicComponent<S, T extends S> extends AbstractSCAObject + implements SystemAtomicComponent { + + private T instance; + private List<Class<?>> serviceInterfaces; + + public SystemSingletonAtomicComponent(String name, CompositeComponent parent, Class<S> interfaze, T instance) { + super(name, parent); + this.instance = instance; + serviceInterfaces = new ArrayList<Class<?>>(1); + serviceInterfaces.add(interfaze); + } + + public List<Class<?>> getServiceInterfaces() { + return serviceInterfaces; + } + + public Scope getScope() { + return Scope.MODULE; + } + + public boolean isEagerInit() { + return false; + } + + public int getInitLevel() { + return 0; + } + + public T getTargetInstance() throws TargetException { + return instance; + } + + public Object getServiceInstance(String name) throws TargetException { + return getTargetInstance(); + } + + public Object getServiceInstance() throws TargetException { + return getTargetInstance(); + } + + public void init(Object instance) throws TargetException { + + } + + public void destroy(Object instance) throws TargetException { + + } + + public Object createInstance() throws ObjectCreationException { + throw new UnsupportedOperationException(); + } + + public void addInboundWire(InboundWire wire) { + throw new UnsupportedOperationException(); + } + + public Map<String, InboundWire> getInboundWires() { + return Collections.emptyMap(); + } + + public InboundWire getInboundWire(String serviceName) { + return null; + } + + public void addOutboundWire(OutboundWire wire) { + throw new UnsupportedOperationException(); + } + + public void addOutboundWires(Class<?> multiplicityClass, List<OutboundWire> wires) { + throw new UnsupportedOperationException(); + } + + public Map<String, List<OutboundWire>> getOutboundWires() { + return Collections.emptyMap(); + } + + + public TargetInvoker createTargetInvoker(String targetName, Operation operation) { + return null; + } + + public TargetInvoker createAsyncTargetInvoker(InboundWire wire, Operation operation) { + return null; + } + + public boolean isSystem() { + return true; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemWireObjectFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemWireObjectFactory.java new file mode 100644 index 0000000000..2399bee076 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/component/SystemWireObjectFactory.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.core.implementation.system.component; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; + +import org.apache.tuscany.core.implementation.system.wire.SystemOutboundWire; + +/** + * Uses a system wire to return an object instance + * + * @version $Rev$ $Date$ + */ +public class SystemWireObjectFactory implements ObjectFactory { + + private SystemOutboundWire wire; + + public SystemWireObjectFactory(SystemOutboundWire factory) { + this.wire = factory; + } + + public Object getInstance() throws ObjectCreationException { + return wire.getTargetService(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemBindingLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemBindingLoader.java new file mode 100644 index 0000000000..4db167a852 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemBindingLoader.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.loader; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.core.implementation.system.model.SystemBinding; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.LoaderUtil; +import org.apache.tuscany.spi.annotation.Autowire; + +/** + * Loads a system binding specified in an XML-based assembly + * + * @version $Rev$ $Date$ + */ +public class SystemBindingLoader extends LoaderExtension<SystemBinding> { + public static final QName SYSTEM_BINDING = + new QName("http://incubator.apache.org/tuscany/xmlns/system/1.0-incubator-M2", "binding.system"); + + @Constructor({"registry"}) + public SystemBindingLoader(@Autowire LoaderRegistry registry) { + super(registry); + } + + public QName getXMLType() { + return SYSTEM_BINDING; + } + + public SystemBinding load(CompositeComponent parent, XMLStreamReader reader, DeploymentContext deploymentContext) + throws XMLStreamException, LoaderException { + LoaderUtil.skipToEndElement(reader); + return new SystemBinding(); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemComponentTypeLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemComponentTypeLoader.java new file mode 100644 index 0000000000..90165c21c0 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemComponentTypeLoader.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.loader; + +import java.net.URL; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.ComponentTypeLoaderExtension; +import org.apache.tuscany.spi.implementation.java.IntrospectionRegistry; +import org.apache.tuscany.spi.implementation.java.Introspector; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; + +import org.apache.tuscany.core.implementation.system.model.SystemImplementation; +import org.apache.tuscany.core.util.JavaIntrospectionHelper; + +/** + * Loads a system component type + * + * @version $Rev$ $Date$ + */ +public class SystemComponentTypeLoader extends ComponentTypeLoaderExtension<SystemImplementation> { + private Introspector introspector; + + public SystemComponentTypeLoader() { + } + + public SystemComponentTypeLoader(Introspector introspector) { + this.introspector = introspector; + } + + public SystemComponentTypeLoader(LoaderRegistry loaderRegistry, Introspector introspector) { + super(loaderRegistry); + this.introspector = introspector; + } + + //FIXME autowire to support multiple interfaces + @Autowire + public void setIntrospector(IntrospectionRegistry introspector) { + this.introspector = introspector; + } + + public void load(CompositeComponent parent, SystemImplementation implementation, + DeploymentContext deploymentContext) throws LoaderException { + Class<?> implClass = implementation.getImplementationClass(); + URL sidefile = implClass.getResource(JavaIntrospectionHelper.getBaseName(implClass) + ".componentType"); + PojoComponentType componentType; + if (sidefile == null) { + componentType = loadByIntrospection(parent, implementation, deploymentContext); + } else { + componentType = loadFromSidefile(sidefile, deploymentContext); + } + implementation.setComponentType(componentType); + } + + protected Class<SystemImplementation> getImplementationClass() { + return SystemImplementation.class; + } + + protected PojoComponentType loadByIntrospection(CompositeComponent parent, + SystemImplementation implementation, + DeploymentContext deploymentContext) throws ProcessingException { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> componentType = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Class<?> implClass = implementation.getImplementationClass(); + introspector.introspect(parent, implClass, componentType, deploymentContext); + return componentType; + } + + + protected PojoComponentType loadFromSidefile(URL url, DeploymentContext deploymentContext) throws LoaderException { + return loaderRegistry.load(null, url, PojoComponentType.class, deploymentContext); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemCompositeComponentTypeLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemCompositeComponentTypeLoader.java new file mode 100644 index 0000000000..74ce87673e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemCompositeComponentTypeLoader.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.loader; + +import java.net.URL; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.ComponentTypeLoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.CompositeComponentType; + +import org.apache.tuscany.core.deployer.ChildDeploymentContext; +import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation; + +/** + * Loads a system composite component type + * + * @version $Rev$ $Date$ + */ +public class SystemCompositeComponentTypeLoader extends ComponentTypeLoaderExtension<SystemCompositeImplementation> { + public SystemCompositeComponentTypeLoader() { + } + + public SystemCompositeComponentTypeLoader(LoaderRegistry loaderRegistry) { + super(loaderRegistry); + } + + protected Class<SystemCompositeImplementation> getImplementationClass() { + return SystemCompositeImplementation.class; + } + + public void load(CompositeComponent parent, SystemCompositeImplementation implementation, + DeploymentContext deploymentContext) + throws LoaderException { + URL scdlLocation = implementation.getScdlLocation(); + if (scdlLocation == null) { + throw new LoaderException("SCDL location not found"); + } + ClassLoader cl = implementation.getClassLoader(); + deploymentContext = new ChildDeploymentContext(deploymentContext, cl, scdlLocation); + CompositeComponentType componentType = loadFromSidefile(parent, scdlLocation, deploymentContext); + implementation.setComponentType(componentType); + } + + + protected CompositeComponentType loadFromSidefile(CompositeComponent parent, + URL url, + DeploymentContext deploymentContext) + throws LoaderException { + return loaderRegistry.load(parent, url, CompositeComponentType.class, deploymentContext); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemImplementationLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemImplementationLoader.java new file mode 100644 index 0000000000..7db92e07ef --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/loader/SystemImplementationLoader.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.loader; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.core.implementation.system.model.SystemImplementation; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.LoaderUtil; +import org.apache.tuscany.spi.annotation.Autowire; + +/** + * Loads information for a system implementation + * + * @version $Rev$ $Date$ + */ +public class SystemImplementationLoader extends LoaderExtension<SystemImplementation> { + public static final QName SYSTEM_IMPLEMENTATION = + new QName("http://incubator.apache.org/tuscany/xmlns/system/1.0-incubator-M2", "implementation.system"); + + @Constructor({"registry"}) + public SystemImplementationLoader(@Autowire LoaderRegistry registry) { + super(registry); + } + + public SystemImplementation load(CompositeComponent parent, + XMLStreamReader reader, + DeploymentContext deploymentContext + ) + throws XMLStreamException, LoaderException { + assert SYSTEM_IMPLEMENTATION.equals(reader.getName()); + SystemImplementation implementation = new SystemImplementation(); + String implClass = reader.getAttributeValue(null, "class"); + Class<?> implementationClass = LoaderUtil.loadClass(implClass, deploymentContext.getClassLoader()); + implementation.setImplementationClass(implementationClass); + registry.loadComponentType(parent, implementation, deploymentContext); + LoaderUtil.skipToEndElement(reader); + return implementation; + } + + public QName getXMLType() { + return SYSTEM_IMPLEMENTATION; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemBinding.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemBinding.java new file mode 100644 index 0000000000..36a439c61b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemBinding.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.model; + +import org.apache.tuscany.spi.model.Binding; + +/** + * A by-reference binding used by runtime system services + * + * @version $$Rev$$ $$Date$$ + */ +public class SystemBinding extends Binding { +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemCompositeImplementation.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemCompositeImplementation.java new file mode 100644 index 0000000000..e634609c5b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemCompositeImplementation.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.model; + +import java.net.URL; + +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.Implementation; + +/** + * Represents a system composite type + * + * @version $Rev$ $Date$ + */ +public class SystemCompositeImplementation extends Implementation<CompositeComponentType> { + private URL scdlLocation; + private ClassLoader classLoader; + + public SystemCompositeImplementation() { + } + + public SystemCompositeImplementation(CompositeComponentType componentType) { + super(componentType); + } + + public URL getScdlLocation() { + return scdlLocation; + } + + public void setScdlLocation(URL scdlLocation) { + this.scdlLocation = scdlLocation; + } + + public ClassLoader getClassLoader() { + return classLoader; + } + + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemImplementation.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemImplementation.java new file mode 100644 index 0000000000..ce48ed3fe5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/model/SystemImplementation.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.model; + +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.model.AtomicImplementation; + +/** + * Represents the system composite implementation + * + * @version $Rev$ $Date$ + */ +public class SystemImplementation extends AtomicImplementation<PojoComponentType> { + private Class<?> implementationClass; + + public SystemImplementation(PojoComponentType componentType, Class<?> implementationClass) { + super(componentType); + this.implementationClass = implementationClass; + } + + public SystemImplementation() { + } + + public SystemImplementation(Class<?> implementationClass) { + this.implementationClass = implementationClass; + } + + public Class<?> getImplementationClass() { + return implementationClass; + } + + public void setImplementationClass(Class<?> implementationClass) { + this.implementationClass = implementationClass; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/wire/SystemInboundWire.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/wire/SystemInboundWire.java new file mode 100644 index 0000000000..188a813800 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/wire/SystemInboundWire.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.core.implementation.system.wire; + +import org.apache.tuscany.spi.wire.InboundWire; + +/** + * Specified by a {@link org.apache.tuscany.core.implementation.system.model.SystemBinding}, a specialized inbound wire + * that returns a direct reference to the target. + * + * @version $$Rev$$ $$Date$$ + */ +public interface SystemInboundWire extends InboundWire { + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/wire/SystemInboundWireImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/wire/SystemInboundWireImpl.java new file mode 100644 index 0000000000..7938f3ad48 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/wire/SystemInboundWireImpl.java @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.wire; + +import java.util.Collections; +import java.util.Map; + +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; + +/** + * Default implementation of an inbound system wire + * + * @version $$Rev$$ $$Date$$ + */ +public class SystemInboundWireImpl implements SystemInboundWire { + private String serviceName; + private ServiceContract serviceContract; + private Component component; + private SystemOutboundWire wire; + private SCAObject container; + private Class<?> interfaze; + + /** + * Constructs a new inbound wire + * + * @param serviceName the name of the service the inbound wire represents + * @param interfaze the service interface + * @param target the target context the wire is connected to + */ + public SystemInboundWireImpl(String serviceName, Class<?> interfaze, Component target) { + this.serviceName = serviceName; + this.component = target; + serviceContract = new JavaServiceContract(interfaze); + this.interfaze = interfaze; + } + + public SystemInboundWireImpl(String serviceName, Class<?> interfaze) { + this(serviceName, interfaze, null); + } + + public ServiceContract getServiceContract() { + return serviceContract; + } + + public void setServiceContract(ServiceContract serviceContract) { + this.serviceContract = serviceContract; + } + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + throw new UnsupportedOperationException(); + } + + public Object getTargetService() throws TargetException { + if (wire != null) { + return interfaze.cast(wire.getTargetService()); + } + return interfaze.cast(component.getServiceInstance(serviceName)); + } + + public Class[] getImplementedInterfaces() { + return new Class[0]; + } + + public Map<Operation<?>, InboundInvocationChain> getInvocationChains() { + return Collections.emptyMap(); + } + + public void addInvocationChain(Operation<?> operation, InboundInvocationChain chain) { + throw new UnsupportedOperationException(); + } + + public void addInvocationChains(Map chains) { + throw new UnsupportedOperationException(); + } + + public Map<Operation<?>, OutboundInvocationChain> getSourceCallbackInvocationChains(Object targetAddr) { + throw new UnsupportedOperationException(); + } + + public void addSourceCallbackInvocationChains(Object targetAddr, + Map<Operation<?>, + OutboundInvocationChain> chains) { + throw new UnsupportedOperationException(); + } + + public void addSourceCallbackInvocationChain(Object targetAddr, Operation operation, + OutboundInvocationChain chain) { + throw new UnsupportedOperationException(); + } + + public void addInterface(Class claz) { + throw new UnsupportedOperationException(); + } + + public String getCallbackReferenceName() { + return null; + } + + public void setCallbackReferenceName(String callbackReferenceName) { + throw new UnsupportedOperationException(); + } + + public boolean isOptimizable() { + return true; // system wires are always optimizable + } + + public void setTargetWire(OutboundWire wire) { + assert wire instanceof SystemOutboundWire : "wire must be a " + SystemOutboundWireImpl.class.getName(); + this.wire = (SystemOutboundWire) wire; + } + + public SCAObject getContainer() { + return container; + } + + public void setContainer(SCAObject container) { + this.container = container; + } + + public void addMapping(Object messageId, Object fromAddress) { + throw new UnsupportedOperationException(); + } + + public Object retrieveMapping(Object messageId) { + return null; + } + + public void removeMapping(Object messageId) { + throw new UnsupportedOperationException(); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/wire/SystemOutboundAutowire.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/wire/SystemOutboundAutowire.java new file mode 100644 index 0000000000..ff4cad9795 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/wire/SystemOutboundAutowire.java @@ -0,0 +1,152 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.wire; + +import java.util.Collections; +import java.util.Map; + +import org.apache.tuscany.spi.QualifiedName; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.component.TargetNotFoundException; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; + +import org.apache.tuscany.core.wire.OutboundAutowire; + +/** + * A specialization of <code>OutboundAutowire</code> that returns a direct reference to the target + * + * @version $$Rev$$ $$Date$$ + */ +public class SystemOutboundAutowire implements OutboundAutowire, SystemOutboundWire { + private String referenceName; + private ServiceContract serviceContract; + private CompositeComponent component; + private final boolean required; + private SCAObject container; + + public SystemOutboundAutowire(String referenceName, Class<?> interfaze, CompositeComponent component, + boolean required) { + + this.referenceName = referenceName; + this.component = component; + serviceContract = new JavaServiceContract(interfaze); + this.required = required; + } + + public ServiceContract getServiceContract() { + return serviceContract; + } + + public void setServiceContract(ServiceContract serviceContract) { + this.serviceContract = serviceContract; + } + + public String getReferenceName() { + return referenceName; + } + + public void setReferenceName(String referenceName) { + this.referenceName = referenceName; + } + + public QualifiedName getTargetName() { + return null; + } + + public void setTargetName(QualifiedName targetName) { + } + + public Object getTargetService() throws TargetException { + Class<?> interfaze = serviceContract.getInterfaceClass(); + Object service = component.resolveSystemInstance(interfaze); + if (service == null && required) { + TargetNotFoundException e = new TargetNotFoundException("Autowire target not found"); + e.setIdentifier(interfaze.getName()); + throw e; + } + return service; + } + + public void setCallbackInterface(Class<?> interfaze) { + throw new UnsupportedOperationException(); + } + + public Class<?> getCallbackInterface() { + throw new UnsupportedOperationException(); + } + + public void addCallbackInterface(Class<?> claz) { + throw new UnsupportedOperationException(); + } + + public Class[] getImplementedCallbackInterfaces() { + throw new UnsupportedOperationException(); + } + + public void setTargetWire(InboundWire wire) { + throw new UnsupportedOperationException(); + } + + public Map<Operation<?>, OutboundInvocationChain> getInvocationChains() { + return Collections.emptyMap(); + } + + public void addInvocationChain(Operation operation, OutboundInvocationChain chains) { + throw new UnsupportedOperationException(); + } + + public void addInvocationChains(Map<Operation<?>, OutboundInvocationChain> chains) { + throw new UnsupportedOperationException(); + } + + public Map<Operation<?>, InboundInvocationChain> getTargetCallbackInvocationChains() { + throw new UnsupportedOperationException(); + } + + public void addTargetCallbackInvocationChains(Map<Operation<?>, InboundInvocationChain> chains) { + throw new UnsupportedOperationException(); + } + + public void addTargetCallbackInvocationChain(Operation operation, InboundInvocationChain chain) { + throw new UnsupportedOperationException(); + } + + public void addInterface(Class claz) { + throw new UnsupportedOperationException(); + } + + public boolean isOptimizable() { + return true; + } + + public SCAObject getContainer() { + return container; + } + + public void setContainer(SCAObject container) { + this.container = container; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/wire/SystemOutboundWire.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/wire/SystemOutboundWire.java new file mode 100644 index 0000000000..bf9ccdd5a1 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/wire/SystemOutboundWire.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.wire; + +import org.apache.tuscany.spi.wire.OutboundWire; + +/** + * Specified by a {@link org.apache.tuscany.core.implementation.system.model.SystemBinding}, a specialized outbound wire + * that returns a direct reference to the target. + * + * @version $$Rev$$ $$Date$$ + */ +public interface SystemOutboundWire extends OutboundWire { + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/wire/SystemOutboundWireImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/wire/SystemOutboundWireImpl.java new file mode 100644 index 0000000000..ae20b89b55 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/implementation/system/wire/SystemOutboundWireImpl.java @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.wire; + +import java.util.Collections; +import java.util.Map; + +import org.apache.tuscany.spi.QualifiedName; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; + +/** + * Default implementation of a system outbound wire + * + * @version $$Rev$$ $$Date$$ + */ +public class SystemOutboundWireImpl implements SystemOutboundWire { + private String referenceName; + private QualifiedName targetName; + private ServiceContract serviceContract; + private SystemInboundWire targetWire; + private SCAObject container; + private Class<?> interfaze; + + public SystemOutboundWireImpl(String referenceName, QualifiedName targetName, Class<?> interfaze) { + this.referenceName = referenceName; + this.targetName = targetName; + serviceContract = new JavaServiceContract(interfaze); + this.interfaze = interfaze; + } + + public ServiceContract getServiceContract() { + return serviceContract; + } + + public void setServiceContract(ServiceContract serviceContract) { + this.serviceContract = serviceContract; + } + + public String getReferenceName() { + return referenceName; + } + + public void setReferenceName(String referenceName) { + this.referenceName = referenceName; + } + + public QualifiedName getTargetName() { + return targetName; + } + + public void setTargetName(QualifiedName targetName) { + this.targetName = targetName; + } + + public Object getTargetService() throws TargetException { + if (targetWire == null) { + throw new TargetException("No target wire connected to source wire"); + } + return interfaze.cast(targetWire.getTargetService()); + } + + public void setCallbackInterface(Class<?> interfaze) { + throw new UnsupportedOperationException(); + } + + public Class<?> getCallbackInterface() { + throw new UnsupportedOperationException(); + } + + public void addCallbackInterface(Class<?> claz) { + throw new UnsupportedOperationException(); + } + + public Class[] getImplementedCallbackInterfaces() { + throw new UnsupportedOperationException(); + } + + public Map<Operation<?>, OutboundInvocationChain> getInvocationChains() { + return Collections.emptyMap(); + } + + public void addInvocationChain(Operation operation, OutboundInvocationChain chains) { + throw new UnsupportedOperationException(); + } + + public void addInvocationChains(Map chains) { + throw new UnsupportedOperationException(); + } + + public Map<Operation<?>, InboundInvocationChain> getTargetCallbackInvocationChains() { + throw new UnsupportedOperationException(); + } + + public void addTargetCallbackInvocationChains(Map<Operation<?>, InboundInvocationChain> chains) { + throw new UnsupportedOperationException(); + } + + public void addTargetCallbackInvocationChain(Operation operation, InboundInvocationChain chain) { + throw new UnsupportedOperationException(); + } + + public void addInterface(Class claz) { + throw new UnsupportedOperationException(); + } + + public void setTargetWire(InboundWire wire) { + assert wire instanceof SystemInboundWire : "wire must be a " + SystemInboundWire.class.getName(); + this.targetWire = (SystemInboundWire) wire; + } + + public boolean isOptimizable() { + return true; + } + + public SCAObject getContainer() { + return container; + } + + public void setContainer(SCAObject container) { + this.container = container; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ArrayMultiplicityObjectFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ArrayMultiplicityObjectFactory.java new file mode 100644 index 0000000000..1a441dcf87 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/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.core.injection; + +import java.lang.reflect.Array; +import java.util.List; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.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-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/CallbackWireObjectFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/CallbackWireObjectFactory.java new file mode 100644 index 0000000000..87f3a46218 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/CallbackWireObjectFactory.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.WireService; + +/** + * Returns proxy instance for a wire callback + * + * @version $Rev$ $Date$ + */ +public class CallbackWireObjectFactory implements ObjectFactory { + + private WireService wireService; + private ServiceContract<?> contract; + private InboundWire wire; + + public CallbackWireObjectFactory(ServiceContract<?> contract, WireService wireService, InboundWire wire) { + this.contract = contract; + this.wireService = wireService; + this.wire = wire; + } + + public Object getInstance() throws ObjectCreationException { + return wireService.createCallbackProxy(contract, wire); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ContextInjector.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ContextInjector.java new file mode 100644 index 0000000000..a422500f3c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/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.core.injection; + +import org.apache.tuscany.spi.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-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/EventInvoker.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/EventInvoker.java new file mode 100644 index 0000000000..af2382b36a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/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.core.injection; + +/** + * Performs an invocation on an instance + * + * @version $Rev$ $Date$ + */ +public interface EventInvoker<T> { + + /** + * Performs the invocation on a given instance + * + * @throws ObjectCallbackException + */ + void invokeEvent(T instance) throws ObjectCallbackException; +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/FieldInjector.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/FieldInjector.java new file mode 100644 index 0000000000..e9f8f42aa1 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/FieldInjector.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import java.lang.reflect.Field; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; + +/** + * Injects a value created by an {@link org.apache.tuscany.spi.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 field, ObjectFactory<?> objectFactory) { + this.field = field; + this.field.setAccessible(true); + this.objectFactory = objectFactory; + } + + /** + * Inject a new value on the given isntance + */ + public void inject(T instance) throws ObjectCreationException { + try { + field.set(instance, objectFactory.getInstance()); + } catch (IllegalAccessException e) { + throw new AssertionError("Field is not accessible [" + field + "]"); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/InjectionRuntimeException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/InjectionRuntimeException.java new file mode 100644 index 0000000000..2b2dbc9056 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/InjectionRuntimeException.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.core.injection; + +import org.apache.tuscany.api.TuscanyRuntimeException; + +/** + * Root unchecked exception for the injection package + * + * @version $Rev$ $Date$ + */ +public abstract class InjectionRuntimeException extends TuscanyRuntimeException { + + public InjectionRuntimeException() { + super(); + } + + public InjectionRuntimeException(String message) { + super(message); + } + + public InjectionRuntimeException(String message, Throwable cause) { + super(message, cause); + } + + public InjectionRuntimeException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/Injector.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/Injector.java new file mode 100644 index 0000000000..c2125d8212 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/Injector.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import org.apache.tuscany.spi.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; + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/InvalidAccessorException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/InvalidAccessorException.java new file mode 100644 index 0000000000..d263830d69 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/InvalidAccessorException.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.core.injection; + +/** + * @version $$Rev$$ $$Date$$ + */ +public class InvalidAccessorException extends InjectionRuntimeException { + public InvalidAccessorException() { + } + + public InvalidAccessorException(String message) { + super(message); + } + + public InvalidAccessorException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidAccessorException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/JNDIObjectFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/JNDIObjectFactory.java new file mode 100644 index 0000000000..0189d8245b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/JNDIObjectFactory.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.core.injection; + +import javax.naming.Context; +import javax.naming.NamingException; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; + +/** + * An implementation of ObjectFactory that creates instances by looking them up in a JNDI context. + * + * @version $Rev$ $Date$ + */ +public class JNDIObjectFactory<T> implements ObjectFactory<T> { + private final Context context; + private final String name; + + public JNDIObjectFactory(Context context, String name) { + this.context = context; + this.name = name; + } + + + @SuppressWarnings("unchecked") + public T getInstance() throws ObjectCreationException { + try { + return (T) context.lookup(name); + } catch (NamingException e) { + throw new ObjectCreationException(e); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ListMultiplicityObjectFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ListMultiplicityObjectFactory.java new file mode 100644 index 0000000000..b261bcda53 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ListMultiplicityObjectFactory.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.core.injection; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.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<List> { + + private ObjectFactory[] factories; + + public ListMultiplicityObjectFactory(List<ObjectFactory<?>> factories) { + assert factories != null : "Object factories were null"; + this.factories = factories.toArray(new ObjectFactory[factories.size()]); + } + + public List getInstance() throws ObjectCreationException { + List<Object> list = new ArrayList<Object>(); + for (ObjectFactory factory : factories) { + list.add(factory.getInstance()); + } + return list; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/MethodEventInvoker.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/MethodEventInvoker.java new file mode 100644 index 0000000000..e748c228d0 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/MethodEventInvoker.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.core.injection; + +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; + + /** + * Intantiates an invoker for the given method + */ + public MethodEventInvoker(Method method) { + assert method != null; + this.method = method; + } + + public void invokeEvent(T instance) throws ObjectCallbackException { + try { + method.invoke(instance, (Object[]) null); + } catch (IllegalAccessException e) { + throw new AssertionError("Method is not accessible [" + method + "]"); + } catch (InvocationTargetException e) { + throw new ObjectCallbackException("Exception thrown by callback method [" + method + "]", e.getCause()); + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/MethodInjector.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/MethodInjector.java new file mode 100644 index 0000000000..d645d7efac --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/MethodInjector.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; + +/** + * Injects a value created by an {@link org.apache.tuscany.spi.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 method, ObjectFactory<?> objectFactory) { + assert method != null; + assert objectFactory != null; + this.method = method; + this.method.setAccessible(true); + this.objectFactory = objectFactory; + } + + public void inject(T instance) throws ObjectCreationException { + try { + method.invoke(instance, objectFactory.getInstance()); + } catch (IllegalAccessException e) { + throw new AssertionError("Method is not accessible [" + method + "]"); + } catch (IllegalArgumentException e) { + ObjectCreationException oce = new ObjectCreationException("Exception thrown by setter", e); + oce.setIdentifier(method.getName()); + throw oce; + } catch (InvocationTargetException e) { + ObjectCreationException oce = new ObjectCreationException("Exception thrown by setter", e); + oce.setIdentifier(method.getName()); + throw oce; + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/NoAccessorException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/NoAccessorException.java new file mode 100644 index 0000000000..b3109074e3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/NoAccessorException.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.core.injection; + +/** + * @version $$Rev$$ $$Date$$ + */ +public class NoAccessorException extends InjectionRuntimeException { + public NoAccessorException() { + } + + public NoAccessorException(String message) { + super(message); + } + + public NoAccessorException(String message, Throwable cause) { + super(message, cause); + } + + public NoAccessorException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ObjectCallbackException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ObjectCallbackException.java new file mode 100644 index 0000000000..46f7c8253b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/ObjectCallbackException.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.core.injection; + +/** + * Denotes an error when invoking on an object + * + * @version $Rev$ $Date$ + */ +public class ObjectCallbackException extends InjectionRuntimeException { + + public ObjectCallbackException() { + super(); + } + + public ObjectCallbackException(String message) { + super(message); + } + + public ObjectCallbackException(String message, Throwable cause) { + super(message, cause); + } + + public ObjectCallbackException(Throwable cause) { + super(cause); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/PojoObjectFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/PojoObjectFactory.java new file mode 100644 index 0000000000..21f9196b06 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/PojoObjectFactory.java @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.List; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; + +/** + * Creates new instances of a Java class + * + * @version $Rev$ $Date$ + * @see org.apache.tuscany.core.injection.Injector + */ +public class PojoObjectFactory<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 PojoObjectFactory(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 PojoObjectFactory(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]; + initargs[i] = objectFactory.getInstance(); + } + try { + ctr.setAccessible(true); + return ctr.newInstance(initargs); + } catch (InstantiationException e) { + throw new AssertionError("Class is not instantiable [" + ctr.getDeclaringClass().getName() + "]"); + } catch (IllegalAccessException e) { + throw new AssertionError("Constructor is not accessible [" + ctr + "]"); + } catch (InvocationTargetException e) { + throw new ObjectCreationException("Exception thrown by constructor [" + ctr + "]", e); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/SingletonObjectFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/SingletonObjectFactory.java new file mode 100644 index 0000000000..713c1ae54f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/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.core.injection; + +import org.apache.tuscany.spi.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-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/WireObjectFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/WireObjectFactory.java new file mode 100644 index 0000000000..2355272496 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/injection/WireObjectFactory.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.core.injection; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.wire.RuntimeWire; +import org.apache.tuscany.spi.wire.WireService; + +/** + * Uses a wire to return an object instance + * + * @version $Rev$ $Date$ + */ +public class WireObjectFactory implements ObjectFactory { + + private RuntimeWire wire; + private WireService wireService; + + public WireObjectFactory(RuntimeWire wire, WireService wireService) { + this.wire = wire; + this.wireService = wireService; + } + + public Object getInstance() throws ObjectCreationException { + return wireService.createProxy(wire); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/CompositeContextImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/CompositeContextImpl.java new file mode 100644 index 0000000000..46004d90d2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/CompositeContextImpl.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.launcher; + +import org.osoa.sca.CompositeContext; +import org.osoa.sca.RequestContext; +import org.osoa.sca.SCA; +import org.osoa.sca.ServiceReference; + +import org.apache.tuscany.spi.component.CompositeComponent; + + +public class CompositeContextImpl extends SCA implements CompositeContext { + protected final CompositeComponent composite; + + public CompositeContextImpl(final CompositeComponent composite) { + this.composite = composite; + } + + public void start() { + setCompositeContext(this); + } + + public void stop() { + setCompositeContext(null); + } + + public ServiceReference createServiceReferenceForSession(Object arg0) { + return null; + } + + public ServiceReference createServiceReferenceForSession(Object arg0, String arg1) { + return null; + } + + public String getCompositeName() { + return null; + } + + public String getCompositeURI() { + return null; + } + + public RequestContext getRequestContext() { + return null; + } + + public <T> T locateService(Class<T> serviceInterface, String serviceName) { + return composite.locateService(serviceInterface, serviceName); + } + + public ServiceReference newSession(String arg0) { + return null; + } + + public ServiceReference newSession(String arg0, Object arg1) { + return null; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/InvalidMainException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/InvalidMainException.java new file mode 100644 index 0000000000..ff8978445f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/InvalidMainException.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.launcher; + +/** + * Exception indicating that application's main method is missing or invalid + * (for example it may not be static). + * + * @version $Rev$ $Date$ + */ +public class InvalidMainException extends LaunchException { + public InvalidMainException(String message) { + super(message); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LaunchException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LaunchException.java new file mode 100644 index 0000000000..dbd8dcad74 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LaunchException.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.core.launcher; + +import org.apache.tuscany.api.TuscanyException; + +/** + * Exception indicating that there was a problem launching an application. + * + * @version $Rev$ $Date$ + */ +public abstract class LaunchException extends TuscanyException { + public LaunchException() { + } + + public LaunchException(String message) { + super(message); + } + + public LaunchException(String message, Throwable cause) { + super(message, cause); + } + + public LaunchException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherImpl.java new file mode 100644 index 0000000000..1655ebbea6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherImpl.java @@ -0,0 +1,230 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.launcher; + +import java.io.File; +import java.net.URL; + +import javax.xml.stream.XMLInputFactory; + +import org.osoa.sca.CompositeContext; + +import org.apache.tuscany.spi.bootstrap.ComponentNames; +import org.apache.tuscany.spi.bootstrap.RuntimeComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.Deployer; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.CompositeImplementation; + +import org.apache.tuscany.api.TuscanyException; +import org.apache.tuscany.core.bootstrap.Bootstrapper; +import org.apache.tuscany.core.bootstrap.DefaultBootstrapper; +import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation; +import org.apache.tuscany.host.Launcher; +import org.apache.tuscany.host.MonitorFactory; +import org.apache.tuscany.host.RuntimeInfo; + +/** + * Basic launcher implementation. + * + * @version $Rev$ $Date$ + */ +public class LauncherImpl implements Launcher { + /** + * A conventional META-INF based location for the system SCDL. + * + * @see #bootRuntime(URL, MonitorFactory) + */ + public static final String METAINF_SYSTEM_SCDL_PATH = "META-INF/tuscany/system.scdl"; + + /** + * A conventional META-INF based location for the application SCDL. + */ + public static final String METAINF_APPLICATION_SCDL_PATH = "META-INF/sca/default.scdl"; + + private ClassLoader applicationLoader; + + private RuntimeComponent runtime; + + private Deployer deployer; + + private CompositeComponent composite; + + public void bootRuntime(URL systemScdl, ClassLoader systemClassLoader, MonitorFactory monitor) + throws TuscanyException { + if (systemScdl == null) { + throw new LoaderException("Null system SCDL URL"); + } + + XMLInputFactory xmlFactory = XMLInputFactory.newInstance("javax.xml.stream.XMLInputFactory", systemClassLoader); + Bootstrapper bootstrapper = new DefaultBootstrapper(monitor, xmlFactory); + Deployer bootDeployer = bootstrapper.createDeployer(); + + // create and start the core runtime + runtime = bootstrapper.createRuntime(); + runtime.start(); // REVIEW: is this redundant w/ the composite.start() call below? + + // initialize the runtime info + CompositeComponent parent = runtime.getSystemComponent(); + RuntimeInfo runtimeInfo = new LauncherRuntimeInfo(getInstallDirectory(), getApplicationRootDirectory(), true); + parent.registerJavaObject("RuntimeInfo", RuntimeInfo.class, runtimeInfo); + + // registory the monitor factory + parent.registerJavaObject("MonitorFactory", MonitorFactory.class, monitor); + + // create a ComponentDefinition to represent the component we are going to deploy + SystemCompositeImplementation moduleImplementation = new SystemCompositeImplementation(); + moduleImplementation.setScdlLocation(systemScdl); + moduleImplementation.setClassLoader(systemClassLoader); + ComponentDefinition<SystemCompositeImplementation> definition = + new ComponentDefinition<SystemCompositeImplementation>( + ComponentNames.TUSCANY_SYSTEM, moduleImplementation); + + // deploy the component into the runtime under the system parent + composite = (CompositeComponent) bootDeployer.deploy(parent, definition); + + // start the system + composite.start(); + + deployer = (Deployer) composite.getSystemChild("deployer").getServiceInstance(); + } + + /** + * Shuts down the active runtime being managed by this instance. + */ + public void shutdownRuntime() { + if (composite != null) { + composite.stop(); + composite = null; + } + + if (runtime != null) { + runtime.stop(); + runtime = null; + } + } + + public CompositeContext bootApplication(URL applicationScdl, ClassLoader applicationLoader) { + // FIXME implement + throw new UnsupportedOperationException(); + } + + /** + * Returns the classloader for application classes. + * + * @return the classloader for application classes + */ + public ClassLoader getApplicationLoader() { + return applicationLoader; + } + + /** + * Set the classloader to be used for application classes. You should almost always supply your own application + * classloader, based on the hosting environment that the runtime is embedded in. + * + * @param applicationLoader the classloader to be used for application classes + */ + public void setApplicationLoader(ClassLoader applicationLoader) { + this.applicationLoader = applicationLoader; + } + + /** + * Boots the runtime defined by the specified SCDL. + * + * @param systemScdl a resource path to the SCDL defining the system. + * @return a CompositeComponent for the newly booted runtime system + * @throws LoaderException + */ + @Deprecated + public CompositeComponent bootRuntime(URL systemScdl, MonitorFactory monitor) throws TuscanyException { + ClassLoader systemClassLoader = getClass().getClassLoader(); + bootRuntime(systemScdl, systemClassLoader, monitor); + return composite; + } + + /** + * Boots the application defined by the specified SCDL. + * + * @param name the name of the application component + * @param appScdl URL to the SCDL defining the application + * @return a CompositeComponent for the newly booted application + * @throws LoaderException + * @see METAINF_APPLICATION_SCDL_PATH + */ + @Deprecated + public CompositeComponent bootApplication(String name, URL appScdl) throws TuscanyException { + ClassLoader applicationLoader = getApplicationLoader(); + + if (appScdl == null) { + throw new LoaderException("No application scdl found"); + } + + // create a ComponentDefinition to represent the component we are going to deploy + CompositeImplementation impl = new CompositeImplementation(); + impl.setScdlLocation(appScdl); + impl.setClassLoader(applicationLoader); + ComponentDefinition<CompositeImplementation> moduleDefinition = + new ComponentDefinition<CompositeImplementation>(name, impl); + + // deploy the component into the runtime under the system parent + CompositeComponent parent = runtime.getRootComponent(); + // FIXME andyp -- this seems bogus when running inside an appserver + ClassLoader ccl = Thread.currentThread().getContextClassLoader(); + + try { + + Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); + + return (CompositeComponent) deployer.deploy(parent, moduleDefinition); + } finally { + Thread.currentThread().setContextClassLoader(ccl); + } + } + + public File getInstallDirectory() { + String property = System.getProperty("tuscany.installDir"); + if (property != null) { + return new File(property); + } + + // TODO: TUSCANY-648, should this throw an exception if it not running from a jar? + + URL url = getClass().getResource("LauncherImpl.class"); + String jarLocation = url.toString(); + if ("jar".equals(url.getProtocol())) { + jarLocation = jarLocation.substring(4, jarLocation.lastIndexOf("!/")); + } + if (jarLocation.startsWith("file:")) { + jarLocation = jarLocation.substring(5); + } + + File jarFile = new File(jarLocation); + return jarFile.getParentFile().getParentFile(); + } + + public File getApplicationRootDirectory() { + String property = System.getProperty("tuscany.applicationRootDir"); + if (property != null) { + return new File(property); + } + + return new File(System.getProperty("user.dir")); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherRuntimeInfo.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherRuntimeInfo.java new file mode 100644 index 0000000000..6b1f7fa4fa --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/launcher/LauncherRuntimeInfo.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.launcher; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; + +import org.apache.tuscany.host.RuntimeInfo; + +/** + * @version $Rev$ $Date$ + */ +public class LauncherRuntimeInfo implements RuntimeInfo { + + /** Install directory */ + private final File installDirectory; + + /** Application root directory */ + private final File applicationRootDirectory; + + private final boolean online; + + /** + * Initializes the installation and application root directories. + * + * @param installDirectory Installation directory. + * @param applicationRootDirectory Application root directory. + */ + public LauncherRuntimeInfo(File installDirectory, File applicationRootDirectory, boolean online) { + this.installDirectory = installDirectory; + this.applicationRootDirectory = applicationRootDirectory; + this.online = online; + } + + /** + * Return the directory where the running runtime was installed. + * + * @return the directory where the runtime was installed + */ + public File getInstallDirectory() { + return installDirectory; + } + + /** + * Return the root directory used to resolve application file paths. + * + * @return the directory used to resolve application file paths. + */ + public File getApplicationRootDirectory() { + return applicationRootDirectory; + } + + /** + * Gets the base URL for the runtime. + * + * @return The base URL for the runtime. + */ + public URL getBaseURL() { + try { + return getInstallDirectory().toURL(); + } catch (MalformedURLException e) { + // TODO Decide on how to handle the exception + throw new RuntimeException(e); + } + } + + public boolean isOnline() { + return online; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentLoader.java new file mode 100644 index 0000000000..5f9ed6dde1 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentLoader.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.core.loader; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Map; +import java.lang.reflect.Type; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.ParserConfigurationException; +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.w3c.dom.Document; +import static org.osoa.sca.Version.XML_NAMESPACE_1_0; +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.databinding.extension.DOMHelper; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.InvalidReferenceException; +import org.apache.tuscany.spi.loader.InvalidValueException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.LoaderUtil; +import org.apache.tuscany.spi.loader.MissingImplementationException; +import org.apache.tuscany.spi.loader.MissingMustOverridePropertyException; +import org.apache.tuscany.spi.loader.NotOverridablePropertyException; +import org.apache.tuscany.spi.loader.PropertyObjectFactory; +import org.apache.tuscany.spi.loader.UndefinedPropertyException; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.ComponentType; +import org.apache.tuscany.spi.model.Implementation; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.model.OverrideOptions; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.model.PropertyValue; +import org.apache.tuscany.spi.model.ReferenceTarget; + +import org.apache.tuscany.core.implementation.system.model.SystemImplementation; +import org.apache.tuscany.core.property.SimplePropertyObjectFactory; + +/** + * Loads a component definition from an XML-based assembly file + * + * @version $Rev$ $Date$ + */ +public class ComponentLoader extends LoaderExtension<ComponentDefinition<?>> { + private static final QName COMPONENT = new QName(XML_NAMESPACE_1_0, "component"); + private static final QName PROPERTY = new QName(XML_NAMESPACE_1_0, "property"); + private static final QName REFERENCE = new QName(XML_NAMESPACE_1_0, "reference"); + + private static final String PROPERTY_FILE_ATTR = "file"; + private static final String PROPERTY_NAME_ATTR = "name"; + private static final String PROPERTY_SOURCE_ATTR = "source"; + + private PropertyObjectFactory propertyFactory; + + @Constructor({"registry", "propertyFactory"}) + public ComponentLoader(@Autowire LoaderRegistry registry, @Autowire PropertyObjectFactory propertyFactory) { + super(registry); + this.propertyFactory = propertyFactory; + } + + @SuppressWarnings("unchecked") + private void populatePropertyValues(ComponentDefinition<Implementation<?>> componentDefinition) + throws MissingMustOverridePropertyException { + ComponentType componentType = componentDefinition.getImplementation().getComponentType(); + if (componentType != null) { + Map<String, Property<?>> properties = componentType.getProperties(); + Map<String, PropertyValue<?>> propertyValues = componentDefinition.getPropertyValues(); + + for (Property<?> aProperty : properties.values()) { + if (propertyValues.get(aProperty.getName()) == null) { + if (aProperty.getOverride() == OverrideOptions.MUST) { + throw new MissingMustOverridePropertyException(aProperty.getName()); + } else { + PropertyValue propertyValue = new PropertyValue(); + propertyValue.setName(aProperty.getName()); + propertyValue.setValue(aProperty.getDefaultValue()); + // propertyValue.setValueFactory(aProperty.getDefaultValueFactory()); + propertyValue.setValueFactory(new SimplePropertyObjectFactory(aProperty, + propertyValue + .getValue())); + propertyValues.put(aProperty.getName(), propertyValue); + } + } + } + } + } + + public QName getXMLType() { + return COMPONENT; + } + + public ComponentDefinition<?> load(CompositeComponent parent, + XMLStreamReader reader, + DeploymentContext deploymentContext) throws XMLStreamException, + LoaderException { + assert COMPONENT.equals(reader.getName()); + String name = reader.getAttributeValue(null, "name"); + String initLevel = reader.getAttributeValue(null, "initLevel"); + + try { + Implementation<?> impl = loadImplementation(parent, reader, deploymentContext); + registry.loadComponentType(parent, impl, deploymentContext); + + ComponentDefinition<Implementation<?>> componentDefinition = + new ComponentDefinition<Implementation<?>>(name, impl); + + if (initLevel != null) { + if (initLevel.length() == 0) { + componentDefinition.setInitLevel(0); + } else { + try { + componentDefinition.setInitLevel(Integer.valueOf(initLevel)); + } catch (NumberFormatException e) { + InvalidValueException ive = new InvalidValueException(initLevel, e); + ive.setIdentifier("initValue"); + ive.addContextName(name); + throw ive; + } + } + } + + while (true) { + switch (reader.next()) { + case START_ELEMENT: + QName qname = reader.getName(); + if (PROPERTY.equals(qname)) { + loadProperty(reader, deploymentContext, componentDefinition); + } else if (REFERENCE.equals(qname)) { + loadReference(reader, deploymentContext, componentDefinition); + } + reader.next(); + break; + case END_ELEMENT: + if (reader.getName().equals(COMPONENT)) { + // hack to leave alone SystemImplementation + if (!((Implementation) componentDefinition + .getImplementation() instanceof SystemImplementation)) { + populatePropertyValues(componentDefinition); + } + + return componentDefinition; + } + break; + } + } + } catch (LoaderException e) { + e.addContextName(name); + throw e; + } + } + + protected Implementation<?> loadImplementation(CompositeComponent parent, + XMLStreamReader reader, + DeploymentContext deploymentContext) + throws XMLStreamException, LoaderException { + reader.nextTag(); + ModelObject o = registry.load(parent, reader, deploymentContext); + if (!(o instanceof Implementation)) { + throw new MissingImplementationException(); + } + return (Implementation<?>) o; + } + + @SuppressWarnings("unchecked") + protected void loadProperty(XMLStreamReader reader, + DeploymentContext deploymentContext, + ComponentDefinition<?> componentDefinition) throws XMLStreamException, + LoaderException { + String name = reader.getAttributeValue(null, PROPERTY_NAME_ATTR); + Implementation<?> implementation = componentDefinition.getImplementation(); + ComponentType<?, ?, ?> componentType = implementation.getComponentType(); + Property<Type> property = (Property<Type>)componentType.getProperties().get(name); + if (property == null) { + throw new UndefinedPropertyException(name); + } else if (OverrideOptions.NO.equals(property.getOverride())) { + throw new NotOverridablePropertyException(name); + } + PropertyValue<Type> propertyValue; + String source = reader.getAttributeValue(null, PROPERTY_SOURCE_ATTR); + String file = reader.getAttributeValue(null, PROPERTY_FILE_ATTR); + if (source != null || file != null) { + propertyValue = new PropertyValue<Type>(name, source, file); + LoaderUtil.skipToEndElement(reader); + } else { + try { + DocumentBuilder documentBuilder = DOMHelper.newDocumentBuilder(); + Document value = StAXUtil.createPropertyValue(reader, property.getXmlType(), documentBuilder); + propertyValue = new PropertyValue<Type>(name, value); + } catch (ParserConfigurationException e) { + throw new LoaderException(e); + } + } + ObjectFactory<Type> objectFactory = propertyFactory.createObjectFactory(property, propertyValue); + // propertyValue.setValueFactory(new SimplePropertyObjectFactory(property, propertyValue.getValue())); + propertyValue.setValueFactory(objectFactory); + componentDefinition.add(propertyValue); + } + + protected void loadReference(XMLStreamReader reader, + DeploymentContext deploymentContext, + ComponentDefinition<?> componentDefinition) throws XMLStreamException, + LoaderException { + String name = reader.getAttributeValue(null, "name"); + String text = reader.getElementText(); + String target = text != null ? text.trim() : null; + + if (name == null || target == null) { + InvalidReferenceException le = new InvalidReferenceException(); + le.setIdentifier(target); + throw le; + } + + ReferenceTarget referenceTarget = new ReferenceTarget(); + referenceTarget.setReferenceName(name); + try { + referenceTarget.addTarget(new URI(target)); + } catch (URISyntaxException e) { + InvalidReferenceException le = new InvalidReferenceException(e); + le.setIdentifier(target); + throw le; + } + componentDefinition.add(referenceTarget); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentTypeElementLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentTypeElementLoader.java new file mode 100644 index 0000000000..b7b01d1b65 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ComponentTypeElementLoader.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import javax.xml.namespace.QName; +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import static org.osoa.sca.Version.XML_NAMESPACE_1_0; +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.ComponentType; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.model.ReferenceDefinition; +import org.apache.tuscany.spi.model.ServiceDefinition; +import org.apache.tuscany.spi.annotation.Autowire; + +/** + * @version $Rev$ $Date$ + */ +public class ComponentTypeElementLoader extends LoaderExtension<ComponentType> { + public static final QName COMPONENT_TYPE = new QName(XML_NAMESPACE_1_0, "componentType"); + + @Constructor({"registry"}) + public ComponentTypeElementLoader(@Autowire LoaderRegistry registry) { + super(registry); + } + + public QName getXMLType() { + return COMPONENT_TYPE; + } + + public ComponentType load(CompositeComponent parent, + XMLStreamReader reader, + DeploymentContext deploymentContext) throws XMLStreamException, LoaderException { + assert COMPONENT_TYPE.equals(reader.getName()); + ComponentType<ServiceDefinition, ReferenceDefinition, Property<?>> componentType + = new ComponentType<ServiceDefinition, ReferenceDefinition, Property<?>>(); + + while (true) { + switch (reader.next()) { + case START_ELEMENT: + ModelObject o = registry.load(parent, reader, deploymentContext); + if (o instanceof ServiceDefinition) { + componentType.add((ServiceDefinition) o); + } else if (o instanceof ReferenceDefinition) { + componentType.add((ReferenceDefinition) o); + } else if (o instanceof Property) { + componentType.add((Property<?>) o); + } + break; + case END_ELEMENT: + return componentType; + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/IncludeLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/IncludeLoader.java new file mode 100644 index 0000000000..f5c36c3f83 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/IncludeLoader.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.core.loader; + +import java.net.URL; +import java.net.MalformedURLException; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import static org.osoa.sca.Version.XML_NAMESPACE_1_0; +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderUtil; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.MissingResourceException; +import org.apache.tuscany.spi.loader.MissingIncludeException; +import org.apache.tuscany.spi.model.Include; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.core.deployer.ChildDeploymentContext; + +/** + * Loader that handles <include> elements. + * + * @version $Rev$ $Date$ + */ +public class IncludeLoader extends LoaderExtension<Include> { + private static final QName INCLUDE = new QName(XML_NAMESPACE_1_0, "include"); + + @Constructor({"registry"}) + public IncludeLoader(@Autowire LoaderRegistry registry) { + super(registry); + } + + public QName getXMLType() { + return INCLUDE; + } + + public Include load(CompositeComponent parent, XMLStreamReader reader, DeploymentContext deploymentContext) + throws XMLStreamException, LoaderException { + + assert INCLUDE.equals(reader.getName()); + String name = reader.getAttributeValue(null, "name"); + String scdlLocation = reader.getAttributeValue(null, "scdlLocation"); + String scdlResource = reader.getAttributeValue(null, "scdlResource"); + LoaderUtil.skipToEndElement(reader); + + ClassLoader cl = deploymentContext.getClassLoader(); + URL url; + if (scdlLocation != null) { + try { + url = new URL(deploymentContext.getScdlLocation(), scdlLocation); + } catch (MalformedURLException e) { + MissingResourceException mre = new MissingResourceException(scdlLocation, e); + mre.setIdentifier(name); + throw mre; + } + } else if (scdlResource != null) { + url = cl.getResource(scdlResource); + if (url == null) { + MissingResourceException mre = new MissingResourceException(scdlResource); + mre.setIdentifier(name); + throw mre; + } + } else { + MissingIncludeException mie = new MissingIncludeException(); + mie.setIdentifier(name); + throw mie; + } + + DeploymentContext childContext = new ChildDeploymentContext(deploymentContext, cl, url); + CompositeComponentType composite = loadFromSidefile(parent, url, childContext); + + Include include = new Include(); + include.setName(name); + include.setScdlLocation(url); + include.setIncluded(composite); + return include; + } + + protected CompositeComponentType loadFromSidefile(CompositeComponent parent, + URL url, + DeploymentContext deploymentContext) + throws LoaderException { + return registry.load(parent, url, CompositeComponentType.class, deploymentContext); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/JNDIPropertyFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/JNDIPropertyFactory.java new file mode 100644 index 0000000000..8759377840 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/JNDIPropertyFactory.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.core.loader; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; + +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.PropertyObjectFactory; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.model.PropertyValue; + +import org.apache.tuscany.core.injection.JNDIObjectFactory; + +/** + * A StAXPropertyFactory that creates property values by looking them up in the default JNDI InitialContext. <p/> This + * can be used to locate resources in a J2EE environment and inject them as configuration properties. For example, to + * access a database a component could write: <code> &at;Property DataSource myDB; </code> and configure with <code> + * <properties> <v:myDb>java:comp/env/jdbc/MyDatabase</v:myDB> </properties> </code> + * + * @version $Rev$ $Date$ + */ +public class JNDIPropertyFactory implements PropertyObjectFactory { + public <T> ObjectFactory<T> createObjectFactory(Property<T> property, PropertyValue<T> value) + throws LoaderException { + String text = value.getValue().getDocumentElement().getTextContent(); + try { + Context context = new InitialContext(); + return new JNDIObjectFactory<T>(context, text); + } catch (NamingException e) { + throw new LoaderException(e); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/LoaderRegistryImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/LoaderRegistryImpl.java new file mode 100644 index 0000000000..b0a666b8ae --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/LoaderRegistryImpl.java @@ -0,0 +1,184 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.osoa.sca.annotations.Init; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.loader.ComponentTypeLoader; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.StAXElementLoader; +import org.apache.tuscany.spi.loader.UnrecognizedElementException; +import org.apache.tuscany.spi.model.Implementation; +import org.apache.tuscany.spi.model.ModelObject; + +/** + * The default implementation of a loader registry + * + * @version $Rev$ $Date$ + */ +public class LoaderRegistryImpl implements LoaderRegistry { + private Monitor monitor; + private final Map<QName, StAXElementLoader<? extends ModelObject>> loaders = + new HashMap<QName, StAXElementLoader<? extends ModelObject>>(); + private final Map<Class<? extends Implementation<?>>, + ComponentTypeLoader<? extends Implementation<?>>> componentTypeLoaders = + new HashMap<Class<? extends Implementation<?>>, ComponentTypeLoader<? extends Implementation<?>>>(); + + + public LoaderRegistryImpl() { + } + + public LoaderRegistryImpl(Monitor monitor) { + this.monitor = monitor; + } + + @org.apache.tuscany.api.annotation.Monitor + public void setMonitor(Monitor monitor) { + this.monitor = monitor; + } + + @Init(eager = true) + public void init() { + + } + + public <T extends ModelObject> void registerLoader(QName element, StAXElementLoader<T> loader) { + monitor.registeringLoader(element); + loaders.put(element, loader); + } + + public <T extends ModelObject> void unregisterLoader(QName element, StAXElementLoader<T> loader) { + monitor.unregisteringLoader(element); + loaders.remove(element); + } + + public ModelObject load(CompositeComponent parent, XMLStreamReader reader, + DeploymentContext deploymentContext) throws XMLStreamException, LoaderException { + QName name = reader.getName(); + monitor.elementLoad(name); + StAXElementLoader<? extends ModelObject> loader = loaders.get(name); + if (loader == null) { + throw new UnrecognizedElementException(name); + } + return loader.load(parent, reader, deploymentContext); + } + + public <MO extends ModelObject> MO load(CompositeComponent parent, + URL url, + Class<MO> type, + DeploymentContext ctx) throws LoaderException { + try { + XMLStreamReader reader; + InputStream is; + is = url.openStream(); + try { + XMLInputFactory factory = ctx.getXmlFactory(); + reader = factory.createXMLStreamReader(is); + try { + reader.nextTag(); + QName name = reader.getName(); + ModelObject mo = load(parent, reader, ctx); + if (type.isInstance(mo)) { + return type.cast(mo); + } else { + UnrecognizedElementException e = new UnrecognizedElementException(name); + e.setResourceURI(url.toString()); + throw e; + } + } finally { + try { + reader.close(); + } catch (XMLStreamException e) { + // ignore + } + } + } finally { + try { + is.close(); + } catch (IOException e) { + // ignore + } + } + } catch (IOException e) { + LoaderException sfe = new LoaderException(e); + sfe.setResourceURI(url.toString()); + throw sfe; + } catch (XMLStreamException e) { + LoaderException sfe = new LoaderException(e); + sfe.setResourceURI(url.toString()); + throw sfe; + } + } + + public <I extends Implementation<?>> void registerLoader(Class<I> key, ComponentTypeLoader<I> loader) { + componentTypeLoaders.put(key, loader); + } + + public <I extends Implementation<?>> void unregisterLoader(Class<I> key) { + componentTypeLoaders.remove(key); + } + + @SuppressWarnings("unchecked") + public <I extends Implementation<?>> void loadComponentType(CompositeComponent parent, I implementation, + DeploymentContext deploymentContext) + throws LoaderException { + Class<I> key = (Class<I>) implementation.getClass(); + ComponentTypeLoader<I> loader = (ComponentTypeLoader<I>) componentTypeLoaders.get(key); + if (loader == null) { + throw new UnsupportedOperationException(); + } + loader.load(parent, implementation, deploymentContext); + } + + public static interface Monitor { + /** + * Event emitted when a StAX element loader is registered. + * + * @param xmlType the QName of the element the loader will handle + */ + void registeringLoader(QName xmlType); + + /** + * Event emitted when a StAX element loader is unregistered. + * + * @param xmlType the QName of the element the loader will handle + */ + void unregisteringLoader(QName xmlType); + + /** + * Event emitted when a request is made to load an element. + * + * @param xmlType the QName of the element that should be loaded + */ + void elementLoad(QName xmlType); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/PropertyLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/PropertyLoader.java new file mode 100644 index 0000000000..7ce3c10af5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/PropertyLoader.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import static org.osoa.sca.Version.XML_NAMESPACE_1_0; +import org.osoa.sca.annotations.Constructor; +import org.w3c.dom.Document; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.OverrideOptions; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.annotation.Autowire; + +/** + * Loads a property from an XML-based assembly file + * + * @version $Rev$ $Date$ + */ +public class PropertyLoader extends LoaderExtension<Property> { + public static final String PROPERTY_NAME_ATTR = "name"; + public static final String PROPERTY_TYPE_ATTR = "type"; + public static final String PROPERTY_MANY_ATTR = "many"; + public static final String PROPERTY_OVERRIDE_ATTR = "override"; + + public static final QName PROPERTY = new QName(XML_NAMESPACE_1_0, "property"); + private final DocumentBuilder documentBuilder; + + @Constructor({"registry"}) + public PropertyLoader(@Autowire LoaderRegistry registry) { + super(registry); + try { + documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + } catch (ParserConfigurationException e) { + // we should be able to construct the default DocumentBuilder + throw new AssertionError(e); + } + } + + public QName getXMLType() { + return PROPERTY; + } + + public Property<?> load(CompositeComponent parent, XMLStreamReader reader, DeploymentContext ctx) + throws XMLStreamException, LoaderException { + assert PROPERTY.equals(reader.getName()); + String name = reader.getAttributeValue(null, PROPERTY_NAME_ATTR); + String typeName = reader.getAttributeValue(null, PROPERTY_TYPE_ATTR); + QName xmlType = null; + if (typeName != null) { + int index = typeName.indexOf(':'); + if (index != -1) { + String prefix = typeName.substring(0, index); + String localName = typeName.substring(index + 1); + String ns = reader.getNamespaceURI(prefix); + xmlType = new QName(ns, localName, prefix); + } + } + boolean many = Boolean.parseBoolean(reader.getAttributeValue(null, PROPERTY_MANY_ATTR)); + String override = reader.getAttributeValue(null, PROPERTY_OVERRIDE_ATTR); + + Document value = StAXUtil.createPropertyValue(reader, xmlType, documentBuilder); + + Property<?> property = new Property(); + property.setName(name); + property.setXmlType(xmlType); + property.setMany(many); + + if (override != null) { + property.setOverride(OverrideOptions.valueOf(override.toUpperCase())); + } + property.setDefaultValue(value); + return property; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ReferenceLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ReferenceLoader.java new file mode 100644 index 0000000000..a36ebe92ff --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ReferenceLoader.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import javax.xml.namespace.QName; +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import static org.osoa.sca.Version.XML_NAMESPACE_1_0; +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.Binding; +import org.apache.tuscany.spi.model.BoundReferenceDefinition; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.model.Multiplicity; +import org.apache.tuscany.spi.model.ReferenceDefinition; +import org.apache.tuscany.spi.model.ServiceContract; + +/** + * Loads a reference from an XML-based assembly file + * + * @version $Rev$ $Date$ + */ +public class ReferenceLoader extends LoaderExtension<ReferenceDefinition> { + public static final QName REFERENCE = new QName(XML_NAMESPACE_1_0, "reference"); + + @Constructor({"registry"}) + public ReferenceLoader(@Autowire LoaderRegistry registry) { + super(registry); + } + + public QName getXMLType() { + return REFERENCE; + } + + public ReferenceDefinition load(CompositeComponent parent, + XMLStreamReader reader, + DeploymentContext deploymentContext + ) + throws XMLStreamException, LoaderException { + assert REFERENCE.equals(reader.getName()); + + String name = reader.getAttributeValue(null, "name"); + Multiplicity multiplicity = + StAXUtil.multiplicity(reader.getAttributeValue(null, "multiplicity"), Multiplicity.ONE_ONE); + Binding binding = null; + ServiceContract serviceContract = null; + while (true) { + switch (reader.next()) { + case START_ELEMENT: + ModelObject o = registry.load(parent, reader, deploymentContext); + if (o instanceof ServiceContract) { + serviceContract = (ServiceContract) o; + } else if (o instanceof Binding) { + binding = (Binding) o; + } + reader.next(); + break; + case END_ELEMENT: + if (binding == null) { + ReferenceDefinition referenceDefinition = new ReferenceDefinition(name, serviceContract); + referenceDefinition.setMultiplicity(multiplicity); + return referenceDefinition; + } else { + BoundReferenceDefinition<Binding> referenceDefinition = new BoundReferenceDefinition<Binding>(); + referenceDefinition.setName(name); + referenceDefinition.setServiceContract(serviceContract); + referenceDefinition.setMultiplicity(multiplicity); + referenceDefinition.setBinding(binding); + return referenceDefinition; + } + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ServiceLoader.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ServiceLoader.java new file mode 100644 index 0000000000..0d5f562b69 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/ServiceLoader.java @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import java.net.URI; +import java.net.URISyntaxException; +import javax.xml.namespace.QName; +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import static org.osoa.sca.Version.XML_NAMESPACE_1_0; +import org.osoa.sca.annotations.Constructor; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.extension.LoaderExtension; +import org.apache.tuscany.spi.loader.InvalidReferenceException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.Binding; +import org.apache.tuscany.spi.model.BindlessServiceDefinition; +import org.apache.tuscany.spi.model.BoundServiceDefinition; +import org.apache.tuscany.spi.model.ModelObject; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.model.ServiceDefinition; + +/** + * Loads a service definition from an XML-based assembly file + * + * @version $Rev$ $Date$ + */ +public class ServiceLoader extends LoaderExtension<ServiceDefinition> { + private static final QName SERVICE = new QName(XML_NAMESPACE_1_0, "service"); + private static final QName REFERENCE = new QName(XML_NAMESPACE_1_0, "reference"); + + @Constructor({"registry"}) + public ServiceLoader(@Autowire LoaderRegistry registry) { + super(registry); + } + + public QName getXMLType() { + return SERVICE; + } + + public ServiceDefinition load(CompositeComponent parent, + XMLStreamReader reader, + DeploymentContext deploymentContext) + throws XMLStreamException, LoaderException { + assert SERVICE.equals(reader.getName()); + String name = reader.getAttributeValue(null, "name"); + String target = null; + Binding binding = null; + ServiceContract serviceContract = null; + while (true) { + int i = reader.next(); + switch (i) { + case START_ELEMENT: + + // there is a reference already using this qname which doesn't seem appropriate. + if (REFERENCE.equals(reader.getName())) { + String text = reader.getElementText(); + target = text != null ? text.trim() : null; + } else { + + ModelObject o = registry.load(parent, reader, deploymentContext); + if (o instanceof ServiceContract) { + serviceContract = (ServiceContract) o; + } else if (o instanceof Binding) { + binding = (Binding) o; + } + } + break; + case END_ELEMENT: + if (SERVICE.equals(reader.getName())) { + if (binding != null) { + if (target == null) { + InvalidReferenceException e = new InvalidReferenceException("No target for service "); + e.setIdentifier(name); + throw e; + } + URI targetURI; + try { + targetURI = new URI(target); + } catch (URISyntaxException e) { + InvalidReferenceException ire = new InvalidReferenceException(target); + ire.setIdentifier(name); + throw ire; + } + + // FIXME need a way to specify "remotable" on a service + return new BoundServiceDefinition<Binding>(name, + serviceContract, + false, + binding, + targetURI); + } else if (target != null) { + URI targetURI; + try { + targetURI = new URI(target); + } catch (URISyntaxException e) { + InvalidReferenceException ire = new InvalidReferenceException(target); + ire.setIdentifier(name); + throw ire; + } + + return new BindlessServiceDefinition(name, serviceContract, false, targetURI); + } else { + // FIXME need a way to specify "remotable" on a service + return new ServiceDefinition(name, serviceContract, false); + } + } + break; + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/StAXUtil.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/StAXUtil.java new file mode 100644 index 0000000000..50dee55c8e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/StAXUtil.java @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import java.util.HashMap; +import java.util.Map; + +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.model.InteractionScope; +import org.apache.tuscany.spi.model.Multiplicity; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * Utility classes to support StAX-based loaders + * + * @version $Rev$ $Date$ + */ +public final class StAXUtil { + private static final Map<String, Multiplicity> MULTIPLICITY = new HashMap<String, Multiplicity>(4); + + static { + MULTIPLICITY.put("0..1", Multiplicity.ZERO_ONE); + MULTIPLICITY.put("1..1", Multiplicity.ONE_ONE); + MULTIPLICITY.put("0..n", Multiplicity.ZERO_N); + MULTIPLICITY.put("1..n", Multiplicity.ONE_N); + } + + private StAXUtil() { + } + + /** + * Convert a "multiplicity" attribute to the equivalent enum value. + * + * @param multiplicity the attribute to convert + * @param def the default value + * @return the enum equivalent + */ + public static Multiplicity multiplicity(String multiplicity, Multiplicity def) { + return multiplicity == null ? def : MULTIPLICITY.get(multiplicity); + } + + /** + * Convert a "scope" attribute to the equivalent enum value. Returns + * CONVERSATIONAL if the value equals (ignoring case) "conversational", + * otherwise returns NONCONVERSATIONAL. + * + * @param scope the attribute to convert + * @return the enum equivalent + */ + public static InteractionScope interactionScope(String scope) { + if ("conversational".equalsIgnoreCase(scope)) { + return InteractionScope.CONVERSATIONAL; + } else { + return InteractionScope.NONCONVERSATIONAL; + } + } + + public static Document createPropertyValue(XMLStreamReader reader, QName type, DocumentBuilder builder) + throws XMLStreamException { + Document doc = builder.newDocument(); + + // root element has no namespace and local name "value" + Element root = doc.createElementNS(null, "value"); + if (type != null) { + Attr xsi = doc.createAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:xsi"); + xsi.setValue(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI); + root.setAttributeNodeNS(xsi); + + String prefix = type.getPrefix(); + if (prefix == null || prefix.length() == 0) { + prefix = "ns"; + } + Attr typeXmlns = doc.createAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:" + prefix); + typeXmlns.setValue(type.getNamespaceURI()); + root.setAttributeNodeNS(typeXmlns); + + Attr xsiType = doc.createAttributeNS(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "xsi:type"); + xsiType.setValue(prefix + ":" + type.getLocalPart()); + root.setAttributeNodeNS(xsiType); + } + doc.appendChild(root); + + loadPropertyValue(reader, root); + return doc; + } + + /** + * Load a property value specification from an StAX stream into a DOM + * Document. Only elements, text and attributes are processed; all comments + * and other whitespace are ignored. + * + * @param reader the stream to read from + * @param root the DOM node to load + */ + public static void loadPropertyValue(XMLStreamReader reader, Node root) throws XMLStreamException { + Document document = root.getOwnerDocument(); + Node current = root; + while (true) { + switch (reader.next()) { + case XMLStreamConstants.START_ELEMENT: + QName name = reader.getName(); + Element child = document.createElementNS(name.getNamespaceURI(), name.getLocalPart()); + + // add the attributes for this element + int count = reader.getAttributeCount(); + for (int i = 0; i < count; i++) { + String ns = reader.getAttributeNamespace(i); + String localPart = reader.getAttributeLocalName(i); + String value = reader.getAttributeValue(i); + child.setAttributeNS(ns, localPart, value); + } + + // push the new element and make it the current one + current.appendChild(child); + current = child; + break; + case XMLStreamConstants.CDATA: + current.appendChild(document.createCDATASection(reader.getText())); + break; + case XMLStreamConstants.CHARACTERS: + current.appendChild(document.createTextNode(reader.getText())); + break; + case XMLStreamConstants.END_ELEMENT: + // if we are back at the root then we are done + if (current == root) { + return; + } + + // pop the element off the stack + current = current.getParentNode(); + } + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/StringParserPropertyFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/StringParserPropertyFactory.java new file mode 100644 index 0000000000..eda09d6f11 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/loader/StringParserPropertyFactory.java @@ -0,0 +1,191 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import java.beans.PropertyEditor; +import java.beans.PropertyEditorManager; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import javax.xml.stream.XMLStreamException; + +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.PropertyObjectFactory; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.model.PropertyValue; + +import org.apache.tuscany.core.injection.SingletonObjectFactory; + +/** + * Implementation of StAXPropertyFactory that interprets the XML as + * + * @version $Rev$ $Date$ + */ +public class StringParserPropertyFactory implements PropertyObjectFactory { + + public <T> ObjectFactory<T> createObjectFactory(Property<T> property, PropertyValue<T> value) + throws LoaderException { + String text = value.getValue().getDocumentElement().getTextContent(); + return new SingletonObjectFactory<T>(createInstance(text, property.getJavaType())); + } + + @SuppressWarnings("unchecked") + public <T> T createInstance(String text, Class<T> type) throws LoaderException { + // Class<T> type = property.getJavaType(); + assert type != null : "property type is null"; + + // degenerate case where property type is a String + if (String.class.equals(type)) { + return type.cast(text); + } + + // special handler to convert hexBinary to a byte[] + if (byte[].class.equals(type)) { + byte[] instance = new byte[text.length() >> 1]; + for (int i = 0; i < instance.length; i++) { + instance[i] = + (byte) (Character.digit(text.charAt(i << 1), 16) << 4 | Character.digit(text + .charAt((i << 1) + 1), 16)); + } + return type.cast(instance); + } + + // does this type have a static valueOf(String) method? + try { + Method valueOf = type.getMethod("valueOf", String.class); + if (Modifier.isStatic(valueOf.getModifiers())) { + try { + return type.cast(valueOf.invoke(null, text)); + } catch (IllegalAccessException e) { + throw new AssertionError("getMethod returned an inaccessible method"); + } catch (InvocationTargetException e) { + // FIXME we should throw something better + throw new LoaderException(e.getCause()); + } + } + } catch (NoSuchMethodException e) { + // try something else + } + + // does this type have a constructor that takes a String? + try { + Constructor<T> ctr = type.getConstructor(String.class); + return ctr.newInstance(text); + } catch (NoSuchMethodException e) { + // try something else + } catch (IllegalAccessException e) { + throw new AssertionError("getConstructor returned an inaccessible method"); + } catch (InstantiationException e) { + throw new LoaderException("Property type cannot be instantiated: " + type.getName()); + } catch (InvocationTargetException e) { + // FIXME we should throw something better + throw new LoaderException(e.getCause()); + } + + // do we have a property editor for it? + PropertyEditor editor = PropertyEditorManager.findEditor(type); + if (editor != null) { + try { + editor.setAsText(text); + return (T) editor.getValue(); + } catch (IllegalArgumentException e) { + // FIXME we should throw something better + throw new LoaderException(e); + + } + } + + // FIXME we should throw something better + throw new LoaderException("Do not have a way to parse a String into a " + type.getName()); + + } + + @SuppressWarnings("unchecked") + public <T> ObjectFactory<T> createObjectFactory(String text, Property<T> property) + throws XMLStreamException, LoaderException { + Class<T> type = property.getJavaType(); + assert type != null : "property type is null"; + + // degenerate case where property type is a String + if (String.class.equals(type)) { + return new SingletonObjectFactory<T>(type.cast(text)); + } + + // special handler to convert hexBinary to a byte[] + if (byte[].class.equals(type)) { + byte[] instance = new byte[text.length() >> 1]; + for (int i = 0; i < instance.length; i++) { + instance[i] = + (byte) (Character.digit(text.charAt(i << 1), 16) << 4 | Character.digit(text + .charAt((i << 1) + 1), 16)); + } + return new SingletonObjectFactory<T>(type.cast(instance)); + } + + // does this type have a static valueOf(String) method? + try { + Method valueOf = type.getMethod("valueOf", String.class); + if (Modifier.isStatic(valueOf.getModifiers())) { + try { + return new SingletonObjectFactory<T>(type.cast(valueOf.invoke(null, text))); + } catch (IllegalAccessException e) { + throw new AssertionError("getMethod returned an inaccessible method"); + } catch (InvocationTargetException e) { + // FIXME we should throw something better + throw new LoaderException(e.getCause()); + } + } + } catch (NoSuchMethodException e) { + // try something else + } + + // does this type have a constructor that takes a String? + try { + Constructor<T> ctr = type.getConstructor(String.class); + return new SingletonObjectFactory<T>(ctr.newInstance(text)); + } catch (NoSuchMethodException e) { + // try something else + } catch (IllegalAccessException e) { + throw new AssertionError("getConstructor returned an inaccessible method"); + } catch (InstantiationException e) { + throw new LoaderException("Property type cannot be instantiated: " + type.getName()); + } catch (InvocationTargetException e) { + // FIXME we should throw something better + throw new LoaderException(e.getCause()); + } + + // do we have a property editor for it? + PropertyEditor editor = PropertyEditorManager.findEditor(type); + if (editor != null) { + try { + editor.setAsText(text); + return new SingletonObjectFactory<T>((T) editor.getValue()); + } catch (IllegalArgumentException e) { + // FIXME we should throw something better + throw new LoaderException(e); + + } + } + + // FIXME we should throw something better + throw new LoaderException("Do not have a way to parse a String into a " + type.getName()); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/InvalidLevelException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/InvalidLevelException.java new file mode 100644 index 0000000000..cf07b0f914 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/InvalidLevelException.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.monitor; + +/** + * Exception indicating an invalid log level has been passed. + * + * @version $Rev$ $Date$ + */ +public class InvalidLevelException extends IllegalArgumentException { + private static final long serialVersionUID = 7767234706427841915L; + private final String method; + private final String level; + + /** + * Constructor specifying the method name and the level affected. + * + * @param method the name of the method being monitored + * @param level the invalid log level value + */ + public InvalidLevelException(String method, String level) { + super(); + this.method = method; + this.level = level; + } + + /** + * Returns the name of the method being monitored. + * + * @return the name of the method being monitored + */ + public String getMethod() { + return method; + } + + /** + * Returns the invalid log level specified. + * + * @return the invalid log level that was specified + */ + public String getLevel() { + return level; + } + + public String getMessage() { + return "Invalid level for method " + method + " : " + level; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/JavaLoggingMonitorFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/JavaLoggingMonitorFactory.java new file mode 100644 index 0000000000..bd5b4598e3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/JavaLoggingMonitorFactory.java @@ -0,0 +1,218 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.monitor; + +import java.lang.ref.WeakReference; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.MissingResourceException; +import java.util.Properties; +import java.util.ResourceBundle; +import java.util.WeakHashMap; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +import org.apache.tuscany.api.annotation.LogLevel; +import org.apache.tuscany.host.MonitorFactory; + +/** + * A factory for monitors that forwards events to a {@link java.util.logging.Logger Java Logging (JSR47) Logger}. + * + * @version $Rev$ $Date$ + * @see java.util.logging + */ +public class JavaLoggingMonitorFactory implements MonitorFactory { + private String bundleName; + private Level defaultLevel; + private Map<String, Level> levels; + + private Map<Class<?>, WeakReference<?>> proxies = new WeakHashMap<Class<?>, WeakReference<?>>(); + + /** + * Construct a MonitorFactory that will monitor the specified methods at the specified levels and generate messages + * using java.util.logging. + * <p/> + * The supplied Properties can be used to specify custom log levels for specific monitor methods. The key should be + * the method name in form returned by <code>Class.getName() + '#' + Method.getName()</code> and the value the log + * level to use as defined by {@link java.util.logging.Level}. + * + * @param levels definition of custom levels for specific monitored methods, may be null or empty. + * @param defaultLevel the default log level to use + * @param bundleName the name of a resource bundle that will be passed to the logger + * @see java.util.logging.Logger + */ + public JavaLoggingMonitorFactory(Properties levels, Level defaultLevel, String bundleName) { + Map<String, Object> configProperties = new HashMap<String, Object>(); + configProperties.put("levels", levels); + configProperties.put("defaultLevel", defaultLevel); + configProperties.put("bundleName", bundleName); + initInternal(configProperties); + } + + /** + * Constructs a MonitorFactory that needs to be subsequently configured via a call to {@link #initialize}. + */ + public JavaLoggingMonitorFactory() { + } + + public void initialize(Map<String, Object> configProperties) { + if (configProperties == null) { + return; + } + initInternal(configProperties); + } + + private void initInternal(Map<String, Object> configProperties) { + try { + this.defaultLevel = (Level) configProperties.get("defaultLevel"); + this.bundleName = (String) configProperties.get("bundleName"); + Properties levels = (Properties) configProperties.get("levels"); + + this.levels = new HashMap<String, Level>(); + if (levels != null) { + for (Map.Entry<Object, Object> entry : levels.entrySet()) { + String method = (String) entry.getKey(); + String level = (String) entry.getValue(); + try { + this.levels.put(method, Level.parse(level)); + } catch (IllegalArgumentException e) { + throw new InvalidLevelException(method, level); + } + } + } + } catch (ClassCastException cce) { + throw new IllegalArgumentException(cce.getLocalizedMessage()); + } + } + + public synchronized <T> T getMonitor(Class<T> monitorInterface) { + T proxy = getCachedMonitor(monitorInterface); + if (proxy == null) { + proxy = createMonitor(monitorInterface, bundleName); + proxies.put(monitorInterface, new WeakReference<T>(proxy)); + } + return proxy; + } + + private <T>T getCachedMonitor(Class<T> monitorInterface) { + WeakReference<?> ref = proxies.get(monitorInterface); + return (ref != null) ? monitorInterface.cast(ref.get()) : null; + } + + private <T>T createMonitor(Class<T> monitorInterface, String bundleName) { + String className = monitorInterface.getName(); + Logger logger = Logger.getLogger(className); + Method[] methods = monitorInterface.getMethods(); + Map<String, Level> levels = new HashMap<String, Level>(methods.length); + for (Method method : methods) { + String key = className + '#' + method.getName(); + Level level = this.levels.get(key); + + // if not specified the in config properties, look for an annotation on the method + if (level == null) { + LogLevel annotation = method.getAnnotation(LogLevel.class); + if (annotation != null && annotation.value() != null) { + try { + level = Level.parse(annotation.value()); + } catch (IllegalArgumentException e) { + // bad value, just use the default + level = defaultLevel; + } + } + } + if (level == null) { + level = defaultLevel; + } + levels.put(method.getName(), level); + } + + ResourceBundle bundle = locateBundle(monitorInterface, bundleName); + + InvocationHandler handler = new LoggingHandler(logger, levels, bundle); + return monitorInterface + .cast(Proxy.newProxyInstance(monitorInterface.getClassLoader(), new Class<?>[]{monitorInterface}, handler)); + } + + private static <T>ResourceBundle locateBundle(Class<T> monitorInterface, String bundleName) { + Locale locale = Locale.getDefault(); + ClassLoader cl = monitorInterface.getClassLoader(); + String packageName = monitorInterface.getPackage().getName(); + while (true) { + try { + return ResourceBundle.getBundle(packageName + '.' + bundleName, locale, cl); + } catch (MissingResourceException e) { + //ok + } + int index = packageName.lastIndexOf('.'); + if (index == -1) { + break; + } + packageName = packageName.substring(0, index); + } + try { + return ResourceBundle.getBundle(bundleName, locale, cl); + } catch (Exception e) { + return null; + } + } + + private static final class LoggingHandler implements InvocationHandler { + private final Logger logger; + private final Map<String, Level> methodLevels; + private final ResourceBundle bundle; + + public LoggingHandler(Logger logger, Map<String, Level> methodLevels, ResourceBundle bundle) { + this.logger = logger; + this.methodLevels = methodLevels; + this.bundle = bundle; + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + String sourceMethod = method.getName(); + Level level = methodLevels.get(sourceMethod); + if (level != null && logger.isLoggable(level)) { + // construct the key for the resource bundle + String className = logger.getName(); + String key = className + '#' + sourceMethod; + + LogRecord logRecord = new LogRecord(level, key); + logRecord.setLoggerName(className); + logRecord.setSourceClassName(className); + logRecord.setSourceMethodName(sourceMethod); + logRecord.setParameters(args); + if (args != null) { + for (Object o : args) { + if (o instanceof Throwable) { + logRecord.setThrown((Throwable) o); + break; + } + } + } + logRecord.setResourceBundle(bundle); + logger.log(logRecord); + } + return null; + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/MonitorFactoryUtil.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/MonitorFactoryUtil.java new file mode 100644 index 0000000000..92224d469f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/MonitorFactoryUtil.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.monitor; + +import org.apache.tuscany.host.MonitorFactory; + +import java.util.Map; + +/** + * Helper for creating MonitorFactory instances. + * + * @version $$Rev$$ $$Date$$ + */ + +public final class MonitorFactoryUtil { + /** + * Hide the constructor + */ + private MonitorFactoryUtil() { + } + + /** + * Creates a MonitorFactory instance of the specified type. + * @param name fully qualified classname of the desired MonitorFactory type + * @param props collection of initialization properties + * @return a configured MonitorFactory instance, or null if the factory could not be instantiated. + */ + @SuppressWarnings("unchecked") + public static MonitorFactory createMonitorFactory(String name, Map<String, Object> props) { + Class<? extends MonitorFactory> clazz; + try { + clazz = (Class<? extends MonitorFactory>) Class.forName(name); + } catch (ClassNotFoundException cnfe) { + return null; + } catch (ClassCastException cce) { + return null; + } + + return createMonitorFactory(clazz, props); + } + + /** + * Creates a MonitorFactory instance of the specified type. + * @param mfc class of the desired MonitorFactory type + * @param props collection of initialization properties + * @return a configured MonitorFactory instance, or null if the factory could not be instantiated. + */ + public static MonitorFactory createMonitorFactory(Class<? extends MonitorFactory> mfc, Map<String, Object> props) { + MonitorFactory mf; + try { + mf = mfc.newInstance(); + mf.initialize(props); + } catch (InstantiationException e) { + throw new AssertionError(e); + } catch (IllegalAccessException e) { + throw new AssertionError(e); + } + // allow IllegalArgumentException to propogate out + + return mf; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/NullMonitorFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/NullMonitorFactory.java new file mode 100644 index 0000000000..938ca3fe98 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/monitor/NullMonitorFactory.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.monitor; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Map; + +import org.osoa.sca.annotations.Init; + +import org.apache.tuscany.host.MonitorFactory; + +/** + * Implementation of a {@link MonitorFactory} that produces implementations that simply return. + * + * @version $Rev$ $Date$ + */ +public class NullMonitorFactory implements MonitorFactory { + /** + * Singleton wire hander that does nothing. + */ + private static final InvocationHandler NULL_MONITOR = new InvocationHandler() { + public Object invoke(Object proxy, Method method, Object[] args) { + return null; + } + }; + + @Init(eager = true) + public void init() { + } + + public void initialize(Map<String, Object> configProperties) { + } + + public <T> T getMonitor(Class<T> monitorInterface) { + /* + * This uses a reflection proxy to implement the monitor interface which + * is a simple but perhaps not very performant solution. Performance + * might be improved by code generating an implementation with empty methods. + */ + return monitorInterface.cast( + Proxy.newProxyInstance(monitorInterface.getClassLoader(), new Class<?>[]{monitorInterface}, NULL_MONITOR)); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyBuilderRegistryImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyBuilderRegistryImpl.java new file mode 100644 index 0000000000..e80d5c7b00 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/policy/PolicyBuilderRegistryImpl.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.core.policy; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.spi.builder.BuilderException; +import org.apache.tuscany.spi.model.ReferenceDefinition; +import org.apache.tuscany.spi.model.ServiceDefinition; +import org.apache.tuscany.spi.policy.PolicyBuilderRegistry; +import org.apache.tuscany.spi.policy.SourcePolicyBuilder; +import org.apache.tuscany.spi.policy.TargetPolicyBuilder; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundWire; + +/** + * The default policy builder + * + * @version $Rev$ $Date$ + */ +public class PolicyBuilderRegistryImpl implements PolicyBuilderRegistry { + + private final List<List<SourcePolicyBuilder>> sourceBuilders; + private final List<List<TargetPolicyBuilder>> targetBuilders; + + public PolicyBuilderRegistryImpl() { + sourceBuilders = new ArrayList<List<SourcePolicyBuilder>>(); + targetBuilders = new ArrayList<List<TargetPolicyBuilder>>(); + for (int i = 0; i <= FINAL; i++) { + sourceBuilders.add(new ArrayList<SourcePolicyBuilder>()); + targetBuilders.add(new ArrayList<TargetPolicyBuilder>()); + } + } + + public void registerTargetBuilder(int phase, TargetPolicyBuilder builder) { + assert INITIAL <= phase && phase <= FINAL : "Illegal phase"; + targetBuilders.get(phase).add(builder); + } + + public void registerSourceBuilder(int phase, SourcePolicyBuilder builder) { + assert INITIAL <= phase && phase <= FINAL : "Illegal phase"; + sourceBuilders.get(phase).add(builder); + } + + + public void buildSource(ReferenceDefinition referenceDefinition, OutboundWire wire) throws BuilderException { + for (List<SourcePolicyBuilder> builders : sourceBuilders) { + for (SourcePolicyBuilder builder : builders) { + builder.build(referenceDefinition, wire); + } + } + } + + public void buildTarget(ServiceDefinition serviceDefinition, InboundWire wire) throws BuilderException { + for (List<TargetPolicyBuilder> builders : targetBuilders) { + for (TargetPolicyBuilder builder : builders) { + builder.build(serviceDefinition, wire); + } + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyHelper.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyHelper.java new file mode 100644 index 0000000000..77e3a6829f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyHelper.java @@ -0,0 +1,197 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.property; + +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.util.Iterator; +import java.util.Map; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.apache.tuscany.core.databinding.xml.InputStream2Node; +import org.apache.tuscany.spi.databinding.extension.DOMHelper; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.loader.InvalidValueException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.Implementation; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.model.PropertyValue; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/** + * The property factory backed by the DataBindingframework + */ +public final class PropertyHelper { + + private static final XPathFactory FACTORY = XPathFactory.newInstance(); + + private PropertyHelper() { + } + + public static Document evaluate(NamespaceContext nsContext, Node node, String xPathExpression) + throws XPathExpressionException, ParserConfigurationException { + XPath path = FACTORY.newXPath(); + if (nsContext != null) { + path.setNamespaceContext(nsContext); + } else { + path.setNamespaceContext(new DOMNamespeceContext(node)); + } + XPathExpression expression = path.compile(xPathExpression); + Node result = (Node)expression.evaluate(node, XPathConstants.NODE); + if (result == null) { + return null; + } + + // TODO: How to wrap the result into a Document? + Document document = DOMHelper.newDocument(); + if (result instanceof Document) { + return document; + } else { + document.appendChild(document.importNode(result, true)); + return document; + } + } + + public static Document loadFromFile(String file, DeploymentContext deploymentContext) + throws LoaderException { + try { + URI uri = URI.create(file); + URL url = null; + if (!uri.isAbsolute()) { + url = deploymentContext.getClassLoader().getResource(file); + } else { + url = uri.toURL(); + } + InputStream is = url.openStream(); + try { + InputStream2Node transformer = new InputStream2Node(); + return (Document)transformer.transform(is, null); + } finally { + is.close(); + } + } catch (Exception e) { + throw new LoaderException(e); + } + } + + @SuppressWarnings("unchecked") + public static void processProperties(CompositeComponentType<?, ?, Property<?>> parent, + ComponentDefinition<? extends Implementation<?>> componentDefinition, + DeploymentContext deploymentContext) throws LoaderException { + Map<String, PropertyValue<?>> propertyValues = componentDefinition.getPropertyValues(); + for (PropertyValue propValue : propertyValues.values()) { + Document node = propValue.getValue(); + String source = propValue.getSource(); + String file = propValue.getFile(); + if (source != null) { + try { + // $<name>/... + int index = source.indexOf('/'); + if (index == -1) { + // Tolerating $prop + source = source + "/"; + index = source.length() - 1; + } + if (source.charAt(0) == '$') { + String name = source.substring(1, index); + Property<?> compositeProp = parent.getProperties().get(name); + if (compositeProp == null) { + InvalidValueException ex = + new InvalidValueException( + "The 'source' cannot be resolved to a composite property"); + ex.addContextName(source); + throw ex; + } + Document document = compositeProp.getDefaultValue(); + // Adding /value because the document root is "value" + String path = source.substring(index); + String xpath = null; + if ("/".equals(path)) { + // trailing / is not legal for xpath + xpath = "/value"; + } else { + xpath = "/value" + path; + } + + // FIXME: How to deal with namespaces? + node = evaluate(null, document, xpath); + propValue.setValue(node); + Property<?> prop = + (Property<?>)componentDefinition.getImplementation().getComponentType() + .getProperties().get(propValue.getName()); + propValue + .setValueFactory(new SimplePropertyObjectFactory(prop, propValue.getValue())); + } else { + InvalidValueException ex = + new InvalidValueException("The 'source' has an invalid value"); + ex.addContextName(source); + throw ex; + } + } catch (Exception e) { + throw new LoaderException(e); + } + } else if (file != null) { + node = loadFromFile(propValue.getFile(), deploymentContext); + propValue.setValue(node); + Property<?> prop = + (Property<?>)componentDefinition.getImplementation().getComponentType().getProperties() + .get(propValue.getName()); + propValue.setValueFactory(new SimplePropertyObjectFactory(prop, propValue.getValue())); + } + } + } + + private static class DOMNamespeceContext implements NamespaceContext { + private Node node; + + /** + * @param node + */ + public DOMNamespeceContext(Node node) { + super(); + this.node = node; + } + + public String getNamespaceURI(String prefix) { + return node.lookupNamespaceURI(prefix); + } + + public String getPrefix(String namespaceURI) { + return node.lookupPrefix(namespaceURI); + } + + public Iterator getPrefixes(String namespaceURI) { + return null; + } + + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyObjectFactoryImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyObjectFactoryImpl.java new file mode 100644 index 0000000000..ae8fd52548 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/PropertyObjectFactoryImpl.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.core.property; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.core.databinding.xml.DOMDataBinding; +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.databinding.DataBinding; +import org.apache.tuscany.spi.databinding.DataBindingRegistry; +import org.apache.tuscany.spi.databinding.Mediator; +import org.apache.tuscany.spi.idl.ElementInfo; +import org.apache.tuscany.spi.idl.TypeInfo; +import org.apache.tuscany.spi.loader.PropertyObjectFactory; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.model.PropertyValue; +import org.osoa.sca.annotations.Constructor; +import org.osoa.sca.annotations.Scope; +import org.osoa.sca.annotations.Service; +import org.w3c.dom.Node; + +@Service(PropertyObjectFactory.class) +@Scope("MODULE") +public class PropertyObjectFactoryImpl implements PropertyObjectFactory { + private DataBindingRegistry registry; + private Mediator mediator; + + public PropertyObjectFactoryImpl() { + } + + @Constructor({"registry", "mediator"}) + public PropertyObjectFactoryImpl(@Autowire DataBindingRegistry registry, @Autowire Mediator mediator) { + super(); + this.registry = registry; + this.mediator = mediator; + } + + public <T> ObjectFactory<T> createObjectFactory(Property<T> property, PropertyValue<T> value) { + if (mediator == null) { + return new SimplePropertyObjectFactory<T>(property, value.getValue()); + } + return new ObjectFactoryImpl<T>(property, value); + } + + public class ObjectFactoryImpl<P> implements ObjectFactory<P> { + private Property<P> property; + private PropertyValue<P> propertyValue; + private DataType<QName> sourceDataType; + private DataType<?> targetDataType; + + public ObjectFactoryImpl(Property<P> property, PropertyValue<P> propertyValue) { + this.property = property; + this.propertyValue = propertyValue; + sourceDataType = new DataType<QName>(DOMDataBinding.NAME, Node.class, this.property.getXmlType()); + TypeInfo typeInfo = new TypeInfo(property.getXmlType(), true, null); + ElementInfo elementInfo = new ElementInfo(null, typeInfo); + sourceDataType.setMetadata(ElementInfo.class.getName(), elementInfo); + Class javaType = this.property.getJavaType(); + String dataBinding = (String)property.getExtensions().get(DataBinding.class.getName()); + if (dataBinding != null) { + targetDataType = new DataType<Class>(dataBinding, javaType, javaType); + } else { + targetDataType = registry.introspectType(javaType); + if (targetDataType == null) { + targetDataType = new DataType<Class>("java.lang.Object", javaType, javaType); + } + } + } + + @SuppressWarnings("unchecked") + public P getInstance() throws ObjectCreationException { + return (P)mediator.mediate(propertyValue.getValue(), sourceDataType, targetDataType, null); + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/SimplePropertyObjectFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/SimplePropertyObjectFactory.java new file mode 100644 index 0000000000..b291eb8d96 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/property/SimplePropertyObjectFactory.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.property; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension; +import org.apache.tuscany.spi.idl.TypeInfo; +import org.apache.tuscany.spi.model.Property; +import org.w3c.dom.Document; + +public class SimplePropertyObjectFactory<P> implements ObjectFactory<P> { + private SimpleTypeMapperExtension typeMapper; + private Property<P> property; + private Document value; + private P instance; + + public SimplePropertyObjectFactory(Property<P> property, Document value) { + super(); + this.property = property; + this.value = (value == null) ? property.getDefaultValue() : value; + this.typeMapper = new SimpleTypeMapperExtension(); + } + + @SuppressWarnings("unchecked") + public P getInstance() throws ObjectCreationException { + if (value == null) { + return null; + } + if (instance == null) { + String text = value.getDocumentElement().getTextContent(); + TypeInfo xmlType = null; + if (property.getJavaType() == null) { + xmlType = new TypeInfo(property.getXmlType(), true, null); + } else { + xmlType = typeMapper.getXMLType(property.getJavaType()); + } + if (xmlType == null) { + throw new IllegalArgumentException("Complex property is not supported."); + } + instance = (P)typeMapper.toJavaObject(xmlType, text, null); + } + return instance; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/AbstractRuntime.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/AbstractRuntime.java new file mode 100644 index 0000000000..f054b3bcdb --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/runtime/AbstractRuntime.java @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.runtime; + +import java.net.URL; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.Deployer; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.CompositeImplementation; + +import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation; +import org.apache.tuscany.core.monitor.NullMonitorFactory; +import org.apache.tuscany.host.MonitorFactory; +import org.apache.tuscany.host.RuntimeInfo; +import org.apache.tuscany.host.runtime.TuscanyRuntime; + +/** + * @version $Rev$ $Date$ + */ +public abstract class AbstractRuntime implements TuscanyRuntime { + private URL systemScdl; + private String applicationName; + private URL applicationScdl; + private ClassLoader hostClassLoader; + private ClassLoader applicationClassLoader; + private RuntimeInfo runtimeInfo; + private MonitorFactory monitorFactory; + + public URL getSystemScdl() { + return systemScdl; + } + + public void setSystemScdl(URL systemScdl) { + this.systemScdl = systemScdl; + } + + public String getApplicationName() { + return applicationName; + } + + public void setApplicationName(String applicationName) { + this.applicationName = applicationName; + } + + public URL getApplicationScdl() { + return applicationScdl; + } + + public void setApplicationScdl(URL applicationScdl) { + this.applicationScdl = applicationScdl; + } + + public ClassLoader getApplicationClassLoader() { + return applicationClassLoader; + } + + public void setApplicationClassLoader(ClassLoader applicationClassLoader) { + this.applicationClassLoader = applicationClassLoader; + } + + public ClassLoader getHostClassLoader() { + return hostClassLoader; + } + + public void setHostClassLoader(ClassLoader hostClassLoader) { + this.hostClassLoader = hostClassLoader; + } + + public RuntimeInfo getRuntimeInfo() { + return runtimeInfo; + } + + public void setRuntimeInfo(RuntimeInfo runtimeInfo) { + this.runtimeInfo = runtimeInfo; + } + + public MonitorFactory getMonitorFactory() { + return monitorFactory; + } + + public void setMonitorFactory(MonitorFactory monitorFactory) { + this.monitorFactory = monitorFactory; + } + + public MonitorFactory createDefaultMonitorFactory() { + return new NullMonitorFactory(); + } + + protected CompositeComponent deploySystemScdl(Deployer deployer, + CompositeComponent parent, + String name, + URL systemScdl, + ClassLoader systemClassLoader) + throws LoaderException { + + SystemCompositeImplementation impl = new SystemCompositeImplementation(); + impl.setScdlLocation(systemScdl); + impl.setClassLoader(systemClassLoader); + ComponentDefinition<SystemCompositeImplementation> definition = + new ComponentDefinition<SystemCompositeImplementation>(name, impl); + + return (CompositeComponent) deployer.deploy(parent, definition); + } + + protected CompositeComponent deployApplicationScdl(Deployer deployer, + CompositeComponent parent, + String name, + URL applicationScdl, + ClassLoader applicationClassLoader) + throws LoaderException { + + CompositeImplementation impl = new CompositeImplementation(); + impl.setScdlLocation(applicationScdl); + impl.setClassLoader(applicationClassLoader); + ComponentDefinition<CompositeImplementation> definition = + new ComponentDefinition<CompositeImplementation>(name, impl); + + return (CompositeComponent) deployer.deploy(parent, definition); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/artifact/LocalMavenRepository.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/artifact/LocalMavenRepository.java new file mode 100644 index 0000000000..f50e8544a3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/artifact/LocalMavenRepository.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.artifact; + +import java.io.File; +import java.net.MalformedURLException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collection; + +import org.osoa.sca.annotations.Property; + +import org.apache.tuscany.spi.services.artifact.Artifact; +import org.apache.tuscany.spi.services.artifact.ArtifactRepository; + +/** + * An implementation of ArtifactRepository that uses a local Maven2 repository. + * + * @version $Rev$ $Date$ + */ +public class LocalMavenRepository implements ArtifactRepository { + private File localRepo; + + /** + * Constructor specifying the location of the local repo. Relative paths are resolved against the user's home + * directory. + * + * @param repoPath the path to the local repo + */ + public LocalMavenRepository(@Property(name = "repository") String repoPath) { + String home = AccessController.doPrivileged(new PrivilegedAction<String>() { + public String run() { + return System.getProperty("user.home"); + } + }); + this.localRepo = new File(home, repoPath); + } + + public void resolve(Artifact artifact) { + if (artifact.getUrl() != null) { + return; + } + + String path = getPath(artifact); + File artifactFile = new File(localRepo, path); + if (artifactFile.exists()) { + try { + artifact.setUrl(artifactFile.toURI().toURL()); + } catch (MalformedURLException e) { + // toURI should have escaped the filename to allow it to be converted to a URL + throw new AssertionError(); + } + } + } + + /** + * Return the path into the repo for an artifact. The path for an artifact is ${group.replace('.', + * '/')}/$[name}/${version}/${name}-${version}[-${classifier}].${type} + * + * @param artifact the artifact to resolve + * @return the path into the repo for the artifact + */ + protected String getPath(Artifact artifact) { + StringBuilder builder = new StringBuilder(); + if (artifact.getGroup() != null) { + builder.append(artifact.getGroup().replace('.', '/')).append('/'); + } + builder.append(artifact.getName()).append('/'); + builder.append(artifact.getVersion()).append('/'); + + builder.append(artifact.getName()).append('-').append(artifact.getVersion()); + if (artifact.getClassifier() != null) { + builder.append('-').append(artifact.getClassifier()); + } + builder.append('.').append(artifact.getType()); + return builder.toString(); + } + + public void resolve(Collection<? extends Artifact> artifacts) { + for (Artifact artifact : artifacts) { + resolve(artifact); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/extension/AbstractExtensionDeployer.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/extension/AbstractExtensionDeployer.java new file mode 100644 index 0000000000..2727e8a108 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/extension/AbstractExtensionDeployer.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.core.services.extension; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; + +import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.CompositeClassLoader; +import org.apache.tuscany.spi.deployer.Deployer; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.model.ComponentDefinition; + +/** + * @version $Rev$ $Date$ + */ +public class AbstractExtensionDeployer { + protected Deployer deployer; + protected CompositeComponent parent; + + @Autowire + public void setDeployer(Deployer deployer) { + this.deployer = deployer; + } + + @Autowire + public void setParent(CompositeComponent parent) { + this.parent = parent; + } + + protected void deployExtension(File file) { + // extension name is file name less any extension + String name = file.getName(); + int dot = name.lastIndexOf('.'); + if (dot > 0) { + name = name.substring(0, dot); + } + URL url; + try { + url = file.toURI().toURL(); + } catch (MalformedURLException e) { + // toURI should have encoded the URL + throw new AssertionError(); + } + + deployExtension(name, url); + } + + protected void deployExtension(String name, URL url) { + // FIXME for now, assume this class's ClassLoader is the Tuscany system classloader + // FIXME we should really use the one associated with the parent composite + CompositeClassLoader extensionCL = new CompositeClassLoader(getClass().getClassLoader()); + + // see if the URL points to a composite JAR by looking for a default SCDL file inside it + URL scdlLocation; + try { + scdlLocation = new URL("jar:" + url.toExternalForm() + "!/META-INF/sca/default.scdl"); + } catch (MalformedURLException e) { + // the form of the jar: URL should be correct given url.toExternalForm() worked + throw new AssertionError(); + } + try { + scdlLocation.openStream().close(); + // we connected to the SCDL so let's add the JAR file to the classloader + extensionCL.addURL(url); + } catch (IOException e) { + // assume that the URL we were given is not a JAR file so just use the supplied resource + scdlLocation = url; + } + + // create a ComponentDefinition to represent the component we are going to deploy + SystemCompositeImplementation implementation = new SystemCompositeImplementation(); + implementation.setScdlLocation(scdlLocation); + implementation.setClassLoader(extensionCL); + ComponentDefinition<SystemCompositeImplementation> definition = + new ComponentDefinition<SystemCompositeImplementation>(name, implementation); + + // FIXME: [rfeng] Should we reset the thread context class loader here? + // From the debugger with tomcat, the current TCCL is the RealmClassLoader + // ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); + try { + // Thread.currentThread().setContextClassLoader(extensionCL); + Component component = deployer.deploy(parent, definition); + component.start(); + } catch (LoaderException e) { + // FIXME handle the exception + e.printStackTrace(); + } finally { + // Thread.currentThread().setContextClassLoader(contextCL); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jca/JcaWorkScheduler.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jca/JcaWorkScheduler.java new file mode 100644 index 0000000000..79b7bf4ca1 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jca/JcaWorkScheduler.java @@ -0,0 +1,206 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.work.jca; + +import javax.resource.spi.work.Work; +import javax.resource.spi.work.WorkEvent; +import javax.resource.spi.work.WorkException; +import javax.resource.spi.work.WorkListener; +import javax.resource.spi.work.WorkManager; +import javax.resource.spi.work.WorkRejectedException; + +import org.apache.tuscany.spi.services.work.NotificationListener; +import org.apache.tuscany.spi.services.work.WorkScheduler; +import org.apache.tuscany.spi.services.work.WorkSchedulerException; + +/** + * A work scheduler implementation based on the JCA SPI work manager. + * <p/> + * <p/> + * This needs a JCA SPI work manager implementation available for scheduling work. Instances can be configured with a + * work manager implementation that is injected in. It is the responsibility of the runtime environment to make a work + * manager implementaion available. </p> + */ +public class JcaWorkScheduler implements WorkScheduler { + + /** + * Underlying JCA work manager + */ + private WorkManager jcaWorkManager; + + /** + * Initializes the JCA work manager. + * + * @param jcaWorkManager JCA work manager. + */ + public JcaWorkScheduler(WorkManager jcaWorkManager) { + + if (jcaWorkManager == null) { + throw new IllegalArgumentException("Work manager cannot be null"); + } + this.jcaWorkManager = jcaWorkManager; + + } + + /** + * Schedules a unit of work for future execution. The notification listener is used to register interest in + * callbacks regarding the status of the work. + * + * @param work The unit of work that needs to be asynchronously executed. + */ + public <T extends Runnable> void scheduleWork(T work) { + scheduleWork(work, null); + } + + /** + * Schedules a unit of work for future execution. The notification listener is used to register interest in + * callbacks regarding the status of the work. + * + * @param work The unit of work that needs to be asynchronously executed. + * @param listener Notification listener for callbacks. + */ + public <T extends Runnable> void scheduleWork(T work, NotificationListener<T> listener) { + + if (work == null) { + throw new IllegalArgumentException("Work cannot be null"); + } + + JcaWork<T> jcaWork = new JcaWork<T>(work); + try { + if (listener == null) { + jcaWorkManager.scheduleWork(jcaWork); + } else { + JcaWorkListener<T> jcaWorkListener = new JcaWorkListener<T>(listener); + // TODO Clarify the usage of timeout and execution context + jcaWorkManager.scheduleWork(jcaWork, -1, null, jcaWorkListener); + } + } catch (WorkRejectedException ex) { + if (listener != null) { + listener.workRejected(work); + } else { + throw new WorkSchedulerException(ex); + } + } catch (WorkException ex) { + throw new WorkSchedulerException(ex); + } + + } + + /* + * Worklistener for keeping track of work status callbacks. + * + */ + private class JcaWorkListener<T extends Runnable> implements WorkListener { + + // Notification listener + private NotificationListener<T> listener; + + /* + * Initializes the notification listener. + */ + public JcaWorkListener(NotificationListener<T> listener) { + this.listener = listener; + } + + /* + * Callback when the work is accepted. + */ + public void workAccepted(WorkEvent workEvent) { + T work = getWork(workEvent); + listener.workAccepted(work); + } + + /* + * Callback when the work is rejected. + */ + public void workRejected(WorkEvent workEvent) { + T work = getWork(workEvent); + listener.workRejected(work); + } + + /* + * Callback when the work is started. + */ + public void workStarted(WorkEvent workEvent) { + T work = getWork(workEvent); + listener.workStarted(work); + } + + /* + * Callback when the work is completed. + */ + public void workCompleted(WorkEvent workEvent) { + T work = getWork(workEvent); + Exception exception = workEvent.getException(); + if (exception != null) { + listener.workFailed(work, exception); + } else { + listener.workCompleted(work); + } + } + + /* + * Gets the underlying work from the work event. + */ + @SuppressWarnings("unchecked") + private T getWork(WorkEvent workEvent) { + JcaWork<T> jcaWork = (JcaWork<T>) workEvent.getWork(); + return jcaWork.getWork(); + } + + } + + /* + * JCA work wrapper. + */ + private class JcaWork<T extends Runnable> implements Work { + + // Work that is being executed. + private T work; + + /* + * Initializes the work instance. + */ + public JcaWork(T work) { + this.work = work; + } + + /* + * Releases the work. + */ + public void release() { + } + + /* + * Performs the work. + */ + public void run() { + work.run(); + } + + /* + * Returns the completed work. + */ + public T getWork() { + return work; + } + + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkScheduler.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkScheduler.java new file mode 100644 index 0000000000..c65ddb12c0 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkScheduler.java @@ -0,0 +1,217 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.work.jsr237; + +import org.osoa.sca.annotations.Scope; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.services.work.NotificationListener; +import org.apache.tuscany.spi.services.work.WorkScheduler; +import org.apache.tuscany.spi.services.work.WorkSchedulerException; + +import commonj.work.Work; +import commonj.work.WorkEvent; +import commonj.work.WorkException; +import commonj.work.WorkListener; +import commonj.work.WorkManager; +import commonj.work.WorkRejectedException; + +/** + * A work scheduler implementation based on a JSR 237 work manager. + * <p/> + * <p/> + * This needs a JSR 237 work manager implementation available for scheduling work. Instances can be configured with a + * work manager implementation that is injected in. It is the responsibility of the runtime environment to make a work + * manager implementaion available. For example, if the managed environment supports work manager the runtime can use + * the appropriate lookup mechanism to inject the work manager implementation. </p> + */ +@Scope("MODULE") +public class Jsr237WorkScheduler implements WorkScheduler { + + /** + * Underlying JSR-237 work manager + */ + private WorkManager jsr237WorkManager; + + /** + * Initializes the JSR 237 work manager. + * + * @param jsr237WorkManager JSR 237 work manager. + */ + public Jsr237WorkScheduler(@Autowire WorkManager jsr237WorkManager) { + if (jsr237WorkManager == null) { + throw new IllegalArgumentException("Work manager cannot be null"); + } + this.jsr237WorkManager = jsr237WorkManager; + } + + /** + * Schedules a unit of work for future execution. The notification listener is used to register interest in + * callbacks regarding the status of the work. + * + * @param work The unit of work that needs to be asynchronously executed. + */ + public <T extends Runnable> void scheduleWork(T work) { + scheduleWork(work, null); + } + + /** + * Schedules a unit of work for future execution. The notification listener is used to register interest in + * callbacks regarding the status of the work. + * + * @param work The unit of work that needs to be asynchronously executed. + * @param listener Notification listener for callbacks. + */ + public <T extends Runnable> void scheduleWork(T work, NotificationListener<T> listener) { + + if (work == null) { + throw new IllegalArgumentException("Work cannot be null"); + } + + Jsr237Work<T> jsr237Work = new Jsr237Work<T>(work); + try { + if (listener == null) { + jsr237WorkManager.schedule(jsr237Work); + } else { + Jsr237WorkListener<T> jsr237WorkListener = new Jsr237WorkListener<T>(listener, work); + jsr237WorkManager.schedule(jsr237Work, jsr237WorkListener); + } + } catch (WorkRejectedException ex) { + if (listener != null) { + listener.workRejected(work); + } else { + throw new WorkSchedulerException(ex); + } + } catch (WorkException ex) { + throw new WorkSchedulerException(ex); + } + + } + + /* + * Worklistener for keeping track of work status callbacks. + * + */ + private class Jsr237WorkListener<T extends Runnable> implements WorkListener { + + // Notification listener + private NotificationListener<T> listener; + + // Work + private T work; + + /* + * Initializes the notification listener. + */ + public Jsr237WorkListener(NotificationListener<T> listener, T work) { + this.listener = listener; + this.work = work; + } + + /* + * Callback when the work is accepted. + */ + public void workAccepted(WorkEvent workEvent) { + T work = getWork(); + listener.workAccepted(work); + } + + /* + * Callback when the work is rejected. + */ + public void workRejected(WorkEvent workEvent) { + T work = getWork(); + listener.workRejected(work); + } + + /* + * Callback when the work is started. + */ + public void workStarted(WorkEvent workEvent) { + T work = getWork(); + listener.workStarted(work); + } + + /* + * Callback when the work is completed. + */ + public void workCompleted(WorkEvent workEvent) { + T work = getWork(); + Exception exception = workEvent.getException(); + if (exception != null) { + listener.workFailed(work, exception); + } else { + listener.workCompleted(work); + } + } + + /* + * Gets the underlying work from the work event. + */ + private T getWork() { + return work; + } + + } + + /* + * JCA work wrapper. + */ + private class Jsr237Work<T extends Runnable> implements Work { + + // Work that is being executed. + private T work; + + /* + * Initializes the work instance. + */ + public Jsr237Work(T work) { + this.work = work; + } + + /* + * Returns the completed work. + */ + public T getWork() { + return work; + } + + /* + * Release the work. + */ + public void release() { + } + + /* + * Work attributes are not daemon. + */ + public boolean isDaemon() { + return false; + } + + /* + * Runs the work. + */ + public void run() { + work.run(); + } + + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkEvent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkEvent.java new file mode 100644 index 0000000000..c391d0b597 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkEvent.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.work.jsr237.workmanager; + +import commonj.work.WorkEvent; +import commonj.work.WorkException; +import commonj.work.WorkItem; + +/** + * Default immutable implementation of the <code>WorkEvent</code> class. + */ +class DefaultWorkEvent implements WorkEvent { + + // Work item for this event + private WorkItem workItem; + + // Exception if something has gone wrong + private WorkException exception; + + /** + * Instantiates the event. + * + * @param workItem Work item for this event. + */ + public DefaultWorkEvent(final DefaultWorkItem workItem) { + this.workItem = workItem; + this.exception = workItem.getException(); + } + + /** + * Returns the work type based on whether the work was accepted, started, + * rejected or completed. + * + * @return Work type. + */ + public int getType() { + return workItem.getStatus(); + } + + /** + * Returns the work item associated with this work type. + * + * @return Work item. + */ + public WorkItem getWorkItem() { + return workItem; + } + + /** + * Returns the exception if the work completed with an exception. + * + * @return Work exception. + */ + public WorkException getException() { + return exception; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkItem.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkItem.java new file mode 100644 index 0000000000..0adc005bb0 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/DefaultWorkItem.java @@ -0,0 +1,166 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.work.jsr237.workmanager; + +import commonj.work.Work; +import commonj.work.WorkException; +import commonj.work.WorkItem; + +/** + * An identity based immutable implementation of the <code>WorkItem</code> + * interface. + * + */ +class DefaultWorkItem implements WorkItem { + + // Id scoped for the VM + private String id; + + // Status + private int status = -1; + + // Result + private Work result; + + // Original work + private Work originalWork; + + // Exception + private WorkException exception; + + /** + * Instantiates an id for this item. + * + * @param id of this work event. + */ + protected DefaultWorkItem(final String id, final Work orginalWork) { + this.id = id; + this.originalWork = orginalWork; + } + + /** + * Returns the id. + * + * @return Id of this item. + */ + public String getId() { + return id; + } + + /** + * Returns the original work. + * + * @return Original work. + */ + public Work getOriginalWork() { + return originalWork; + } + + /** + * Returns the work result if the work completed. + * + * @return Work. + * @throws WorkException If the work completed with an exception. + */ + public Work getResult() throws WorkException { + return result; + } + + /** + * Sets the result. + * + * @param result Result. + */ + protected void setResult(final Work result) { + this.result = result; + } + + /** + * Returns the exception if work completed with an exception. + * + * @return Work exception. + */ + protected WorkException getException() { + return exception; + } + + /** + * Sets the exception. + * + * @param exception Exception. + */ + protected void setException(final WorkException exception) { + this.exception = exception; + } + + /** + * Returns the work type based on whether the work was accepted, started, + * rejected or completed. + * + * @return Work status. + */ + public int getStatus() { + return status; + } + + /** + * Sets the status. + * + * @param status Status. + */ + protected void setStatus(final int status) { + this.status = status; + } + + /** + * @see Object#hashCode() + */ + public int hashCode() { + return id.hashCode(); + } + + /** + * Indicates whether some other object is "equal to" this one. + * + * @param obj Object to be compared. + * @return true if this object is the same as the obj argument; false + * otherwise.. + */ + public boolean equals(final Object obj) { + return (obj != null) && (obj.getClass() == DefaultWorkItem.class) && ((DefaultWorkItem) obj).id.equals(id); + } + + /** + * Compares this object with the specified object for order. Returns a + * negative integer, zero, or a positive integer as this object is less + * than, equal to, or greater than the specified object. + * + * @param o Object to be compared. + * @return A negative integer, zero, or a positive integer as this object + * is less than, equal to, or greater than the specified object. + * @throws ClassCastException needs better documentation. + */ + public int compareTo(final Object o) { + if (o.getClass() != DefaultWorkItem.class) { + throw new ClassCastException(o.getClass().getName()); + } else { + return ((DefaultWorkItem) o).getId().compareTo(getId()); + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/ThreadPoolWorkManager.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/ThreadPoolWorkManager.java new file mode 100644 index 0000000000..1a7639b41d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/services/work/jsr237/workmanager/ThreadPoolWorkManager.java @@ -0,0 +1,220 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.work.jsr237.workmanager; + +import java.rmi.server.UID; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.RejectedExecutionException; + +import org.osoa.sca.annotations.Destroy; +import org.osoa.sca.annotations.Property; + +import commonj.work.Work; +import commonj.work.WorkEvent; +import commonj.work.WorkException; +import commonj.work.WorkItem; +import commonj.work.WorkListener; +import commonj.work.WorkManager; +import commonj.work.WorkRejectedException; + +/** + * A thread-pool based implementation for the JSR-237 work manager. + * <p/> + * <p/> + * This implementation supports only local work. + * <p/> + * TODO Elaborate the implementation. </p> + */ +public class ThreadPoolWorkManager implements WorkManager { + + // Map of work items currently handled by the work manager + private Map<DefaultWorkItem, WorkListener> workItems = new ConcurrentHashMap<DefaultWorkItem, WorkListener>(); + + // Thread-pool + private ExecutorService executor; + + /** + * Initializes the thread-pool. + * + * @param threadPoolSize Thread-pool size. + */ + public ThreadPoolWorkManager(@Property(name = "poolSize") int threadPoolSize) { + executor = Executors.newFixedThreadPool(threadPoolSize); + } + + /** + * Schedules a unit of work asynchronously. + * + * @param work Work that needs to be scheduled. + * @return Work Work item representing the asynchronous work + */ + public WorkItem schedule(Work work) throws WorkException { + return schedule(work, null); + } + + /** + * Schedules a unit of work asynchronously. + * + * @param work Work that needs to be scheduled. + * @param workListener Work listener for callbacks. + * @return Work Work item representing the asynchronous work + */ + public WorkItem schedule(Work work, WorkListener workListener) throws WorkRejectedException { + + DefaultWorkItem workItem = new DefaultWorkItem(new UID().toString(), work); + if (workListener != null) { + workItems.put(workItem, workListener); + } + workAccepted(workItem, work); + if (scheduleWork(work, workItem)) { + return workItem; + } else { + workItem.setStatus(WorkEvent.WORK_REJECTED); + if (workListener != null) { + workListener.workRejected(new DefaultWorkEvent(workItem)); + } + throw new WorkRejectedException("Unable to schedule work"); + } + } + + /** + * Wait for all the specified units of work to finish. + * + * @param works Units of the work that need to finish. + * @param timeout Timeout for waiting for the units of work to finish. + */ + public boolean waitForAll(Collection works, long timeout) { + throw new UnsupportedOperationException("waitForAll not supported"); + } + + /** + * Wait for any of the specified units of work to finish. + * + * @param works Units of the work that need to finish. + * @param timeout Timeout for waiting for the units of work to finish. + */ + public Collection waitForAny(Collection works, long timeout) { + throw new UnsupportedOperationException("waitForAny not supported"); + } + + /** + * Method provided for subclasses to indicate a work accptance. + * + * @param workItem Work item representing the work that was accepted. + * @param work Work that was accepted. + */ + private void workAccepted(final DefaultWorkItem workItem, final Work work) { + WorkListener listener = workItems.get(workItem); + if (listener != null) { + workItem.setStatus(WorkEvent.WORK_ACCEPTED); + WorkEvent event = new DefaultWorkEvent(workItem); + listener.workAccepted(event); + } + } + + /* + * Method to indicate a work start. + */ + private void workStarted(final DefaultWorkItem workItem, final Work work) { + WorkListener listener = workItems.get(workItem); + if (listener != null) { + workItem.setStatus(WorkEvent.WORK_STARTED); + WorkEvent event = new DefaultWorkEvent(workItem); + listener.workStarted(event); + } + } + + /* + * Method to indicate a work completion. + */ + private void workCompleted(final DefaultWorkItem workItem, final Work work) { + workCompleted(workItem, work, null); + } + + /* + * Method to indicate a work completion. + */ + private void workCompleted(final DefaultWorkItem workItem, final Work work, final WorkException exception) { + WorkListener listener = workItems.get(workItem); + if (listener != null) { + workItem.setStatus(WorkEvent.WORK_COMPLETED); + workItem.setResult(work); + workItem.setException(exception); + WorkEvent event = new DefaultWorkEvent(workItem); + listener.workCompleted(event); + workItems.remove(workItem); + } + } + + /* + * Schedules the work using the threadpool. + */ + private boolean scheduleWork(final Work work, final DefaultWorkItem workItem) { + try { + executor.execute(new DecoratingWork(workItem, work)); + return true; + } catch (RejectedExecutionException ex) { + return false; + } + } + + /* + * Class that decorates the original worker so that it can get callbacks when work is done. + */ + private final class DecoratingWork implements Runnable { + + // Work item for this work. + private DefaultWorkItem workItem; + + // The original work. + private Work decoratedWork; + + /* + * Initializes the work item and underlying work. + */ + private DecoratingWork(final DefaultWorkItem workItem, final Work decoratedWork) { + this.workItem = workItem; + this.decoratedWork = decoratedWork; + } + + /* + * Overrides the run method. + */ + public void run() { + workStarted(workItem, decoratedWork); + try { + decoratedWork.run(); + workCompleted(workItem, decoratedWork); + } catch (Throwable th) { + workCompleted(workItem, decoratedWork, new WorkException(th.getMessage(), th)); + } + } + + } + + @Destroy + public void destroy() { + executor.shutdown(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/ClassLoaderHelper.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/ClassLoaderHelper.java new file mode 100644 index 0000000000..a8c57db9d1 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/ClassLoaderHelper.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.util; + +import java.io.File; +import java.net.URL; +import java.net.MalformedURLException; +import java.net.URLClassLoader; + +/** + * Functions to create & manipulate classloaders. + * + * @version $$Rev$$ $$Date$$ + */ + +public final class ClassLoaderHelper { + /** + * Hide constructor + */ + private ClassLoaderHelper() { + } + + /** + * Create a classloader for the supplied classpath. + * + * @param path a list of file/directory names separated by the platform path separator + * @param parent the parent for the new classloader + * @return a classloader that will load classes from the supplied path + */ + public static ClassLoader createClassLoader(ClassLoader parent, String path) { + String[] files = path.split(File.pathSeparator); + return createClassLoader(parent, files); + } + + /** + * Create a classloader for a classpath supplied as individual file names. + * + * @param files a list of file/directory names + * @param parent the parent for the new classloader + * @return a classloader that will load classes from the supplied path + */ + public static ClassLoader createClassLoader(ClassLoader parent, String[] files) { + URL[] urls = new URL[files.length]; + for (int i = 0; i < files.length; i++) { + try { + File file = new File(files[i]); + urls[i] = file.toURI().toURL(); + } catch (MalformedURLException e) { + // just ignore this value + continue; + } + } + + return new URLClassLoader(urls, parent); + } + + /** + * Create a classloader for a classpath supplied as a list of files. + * + * @param files a list of files + * @param parent the parent for the new classloader + * @return a classloader that will load classes from the supplied path + */ + public static ClassLoader createClassLoader(ClassLoader parent, File[] files) { + URL[] urls = new URL[files.length]; + for (int i = 0; i < files.length; i++) { + try { + File file = files[i]; + urls[i] = file.toURI().toURL(); + } catch (MalformedURLException e) { + + continue; + } + } + return new URLClassLoader(urls, parent); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/JavaIntrospectionHelper.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/JavaIntrospectionHelper.java new file mode 100644 index 0000000000..21dea46935 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/util/JavaIntrospectionHelper.java @@ -0,0 +1,439 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.util; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * Implements various reflection-related operations + * + * @version $Rev$ $Date$ + */ +public final class JavaIntrospectionHelper { + + private static final Class[] EMPTY_CLASS_ARRY = new Class[0]; + + /** + * Hide the constructor + */ + private JavaIntrospectionHelper() { + } + + + /** + * Returns a collection of public, and protected fields declared by a class or one of its supertypes + */ + public static Set<Field> getAllPublicAndProtectedFields(Class clazz) { + return getAllPublicAndProtectedFields(clazz, new HashSet<Field>()); + } + + /** + * Recursively evaluates the type hierachy to return all fields that are public or protected + */ + private static Set<Field> getAllPublicAndProtectedFields(Class clazz, Set<Field> fields) { + if (clazz == null || clazz.isArray() || Object.class.equals(clazz)) { + return fields; + } + fields = getAllPublicAndProtectedFields(clazz.getSuperclass(), fields); + Field[] declaredFields = clazz.getDeclaredFields(); + for (Field field : declaredFields) { + int modifiers = field.getModifiers(); + if ((Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers)) && !Modifier.isStatic(modifiers)) { + field.setAccessible(true); // ignore Java accessibility + fields.add(field); + } + } + return fields; + } + + /** + * Returns a collection of public and protected methods declared by a class or one of its supertypes. Note that + * overriden methods will not be returned in the collection (i.e. only the method override will be). <p/> This + * method can potentially be expensive as reflection information is not cached. It is assumed that this method will + * be used during a configuration phase. + */ + public static Set<Method> getAllUniquePublicProtectedMethods(Class clazz) { + return getAllUniqueMethods(clazz, new HashSet<Method>()); + } + + /** + * Recursively evaluates the type hierarchy to return all unique methods + */ + private static Set<Method> getAllUniqueMethods(Class pClass, Set<Method> methods) { + if (pClass == null || pClass.isArray() || Object.class.equals(pClass)) { + return methods; + } + // we first evaluate methods of the subclass and then move to the parent + Method[] declaredMethods = pClass.getDeclaredMethods(); + for (Method declaredMethod : declaredMethods) { + int modifiers = declaredMethod.getModifiers(); + if ((!Modifier.isPublic(modifiers) && !Modifier.isProtected(modifiers)) || Modifier.isStatic(modifiers)) { + continue; + } + if (methods.size() == 0) { + methods.add(declaredMethod); + } else { + List<Method> temp = new ArrayList<Method>(); + boolean matched = false; + for (Method method : methods) { + // only add if not already in the set from a supclass (i.e. the + // method is not overrided) + if (exactMethodMatch(declaredMethod, method)) { + matched = true; + break; + } + } + if (!matched) { + // TODO ignore Java accessibility + declaredMethod.setAccessible(true); + temp.add(declaredMethod); + } + methods.addAll(temp); + temp.clear(); + } + } + // evaluate class hierarchy - this is done last to track inherited methods + methods = getAllUniqueMethods(pClass.getSuperclass(), methods); + return methods; + } + + /** + * Finds the closest matching field with the given name, that is, a field of the exact specified type or, + * alternately, of a supertype. + * + * @param name the name of the field + * @param type the field type + * @param fields the collection of fields to search + * @return the matching field or null if not found + */ + public static Field findClosestMatchingField(String name, Class type, Set<Field> fields) { + Field candidate = null; + for (Field field : fields) { + if (field.getName().equals(name)) { + if (field.getType().equals(type)) { + return field; // exact match + } else if (field.getType().isAssignableFrom(type) + || (field.getType().isPrimitive() && primitiveAssignable(field.getType(), type))) { + // We could have the situation where a field parameter is a primitive and the demarshalled value is + // an object counterpart (e.g. Integer and int) + // @spec issue + // either an interface or super class, so keep a reference until + // we know there are no closer types + candidate = field; + } + } + } + if (candidate != null) { + return candidate; + } else { + return null; + } + } + + /** + * Finds the closest matching method with the given name, that is, a method taking the exact parameter types or, + * alternately, parameter supertypes. + * + * @param name the name of the method + * @param types the method parameter types + * @param methods the collection of methods to search + * @return the matching method or null if not found + */ + public static Method findClosestMatchingMethod(String name, Class[] types, Set<Method> methods) { + if (types == null) { + types = EMPTY_CLASS_ARRY; + } + Method candidate = null; + for (Method method : methods) { + if (method.getName().equals(name) && method.getParameterTypes().length == types.length) { + Class<?>[] params = method.getParameterTypes(); + boolean disqualify = false; + boolean exactMatch = true; + for (int i = 0; i < params.length; i++) { + if (!params[i].equals(types[i]) && !params[i].isAssignableFrom(types[i])) { + // no match + disqualify = true; + exactMatch = false; + break; + } else if (!params[i].equals(types[i]) && params[i].isAssignableFrom(types[i])) { + // not exact match + exactMatch = false; + } + } + if (disqualify) { + continue; + } else if (exactMatch) { + return method; + } else { + candidate = method; + } + } + } + if (candidate != null) { + return candidate; + } else { + return null; + } + } + + /** + * Searches a collection of fields for one that matches by name and has a multiplicity type. i.e. a List or Array of + * interfaces + * + * @return a matching field or null + */ + public static Field findMultiplicityFieldByName(String name, Set<Field> fields) { + for (Field candidate : fields) { + if (candidate.getName().equals(name) + && (List.class.isAssignableFrom(candidate.getType()) || (candidate.getType().isArray() + && candidate.getType().getComponentType() != null && candidate.getType().getComponentType() + .isInterface()))) { + return candidate; + } + } + return null; + } + + /** + * Searches a collection of method for one that matches by name and has single parameter of a multiplicity type. + * i.e. a List or Array of interfaces + * + * @return a matching method or null + */ + public static Method findMultiplicityMethodByName(String name, Set<Method> methods) { + for (Method candidate : methods) { + if (candidate.getName().equals(name) + && candidate.getParameterTypes().length == 1 + && (List.class.isAssignableFrom(candidate.getParameterTypes()[0]) + || (candidate.getParameterTypes()[0].isArray() + && candidate.getParameterTypes()[0].getComponentType() != null + && candidate.getParameterTypes()[0].getComponentType().isInterface()))) { + return candidate; + } + } + return null; + } + + /** + * Determines if two methods "match" - that is, they have the same method names and exact parameter types (one is + * not a supertype of the other) + */ + public static boolean exactMethodMatch(Method method1, Method method2) { + if (!method1.getName().equals(method2.getName())) { + return false; + } + Class[] types1 = method1.getParameterTypes(); + Class[] types2 = method2.getParameterTypes(); + if (types1.length == 0 && types2.length == 0) { + return true; + } else if (types1.length == types2.length) { + for (int n = 0; n < types1.length; n++) { + if (!types1[n].equals(types2[n])) { + return false; + } + } + return true; + } + return false; + } + + public static <T> Constructor<T> getDefaultConstructor(Class<T> clazz) throws NoSuchMethodException { + return clazz.getConstructor((Class[])null); + } + + /** + * Loads a class corresponding to the class name using the current context class loader. + * + * @throws ClassNotFoundException if the class was not found on the classpath + */ + public static Class loadClass(String pName) throws ClassNotFoundException { + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + return Class.forName(pName, true, loader); + } + + /** + * Returns the simple name of a class - i.e. the class name devoid of its package qualifier + * + * @param implClass + */ + public static String getBaseName(Class<?> implClass) { + String baseName = implClass.getName(); + int lastDot = baseName.lastIndexOf('.'); + if (lastDot != -1) { + baseName = baseName.substring(lastDot + 1); + } + return baseName; + } + + public static boolean isImmutable(Class clazz) { + return String.class == clazz + || clazz.isPrimitive() + || Number.class.isAssignableFrom(clazz) + || Boolean.class.isAssignableFrom(clazz) + || Character.class.isAssignableFrom(clazz) + || Byte.class.isAssignableFrom(clazz); + } + + /** + * Takes a property name and converts it to a getter method name according to JavaBean conventions. For example, + * property <code>foo<code> is returned as <code>getFoo</code> + */ + public static String toGetter(String name) { + return "get" + name.toUpperCase().substring(0, 1) + name.substring(1); + } + + /** + * Takes a setter or getter method name and converts it to a property name according to JavaBean conventions. For + * example, <code>setFoo(var)</code> is returned as property <code>foo<code> + */ + public static String toPropertyName(String name) { + if (!name.startsWith("set")) { + return name; + } + return Character.toLowerCase(name.charAt(3)) + name.substring(4); + } + + /** + * Takes a property name and converts it to a setter method name according to JavaBean conventions. For example, the + * property <code>foo<code> is returned as <code>setFoo(var)</code> + */ + public static String toSetter(String name) { + return "set" + name.toUpperCase().substring(0, 1) + name.substring(1); + } + + /** + * Compares a two types, assuming one is a primitive, to determine if the other is its object counterpart + */ + private static boolean primitiveAssignable(Class memberType, Class param) { + if (memberType == Integer.class) { + return param == Integer.TYPE; + } else if (memberType == Double.class) { + return param == Double.TYPE; + } else if (memberType == Float.class) { + return param == Float.TYPE; + } else if (memberType == Short.class) { + return param == Short.TYPE; + } else if (memberType == Character.class) { + return param == Character.TYPE; + } else if (memberType == Boolean.class) { + return param == Boolean.TYPE; + } else if (memberType == Byte.class) { + return param == Byte.TYPE; + } else if (param == Integer.class) { + return memberType == Integer.TYPE; + } else if (param == Double.class) { + return memberType == Double.TYPE; + } else if (param == Float.class) { + return memberType == Float.TYPE; + } else if (param == Short.class) { + return memberType == Short.TYPE; + } else if (param == Character.class) { + return memberType == Character.TYPE; + } else if (param == Boolean.class) { + return memberType == Boolean.TYPE; + } else if (param == Byte.class) { + return memberType == Byte.TYPE; + } else { + return false; + } + } + + /** + * Returns the generic types represented in the given type. Usage as follows: <code> + * JavaIntrospectionHelper.getGenerics(field.getGenericType()); + * <p/> + * JavaIntrospectionHelper.getGenerics(m.getGenericParameterTypes()[0];); </code> + * + * @return the generic types in order of declaration or an empty array if the type is not genericized + */ + public static List<? extends Type> getGenerics(Type genericType) { + List<Type> classes = new ArrayList<Type>(); + if (genericType instanceof ParameterizedType) { + ParameterizedType ptype = (ParameterizedType) genericType; + // get the type arguments + Type[] targs = ptype.getActualTypeArguments(); + for (Type targ : targs) { + classes.add(targ); + } + } + return classes; + } + + /** + * Returns the generic type specified by the class at the given position as in: + * <p/> + * <code> public class Foo<Bar,Baz>{ //.. } + * <p/> + * JavaIntrospectionHelper.introspectGeneric(Foo.class,1); <code> + * <p/> + * will return Baz. + */ + public static Class introspectGeneric(Class<?> clazz, int pos) { + assert clazz != null : "No class specified"; + Type type = clazz.getGenericSuperclass(); + if (type instanceof ParameterizedType) { + Type[] args = ((ParameterizedType) type).getActualTypeArguments(); + if (args.length <= pos) { + throw new IllegalArgumentException("Invalid index value for generic class " + clazz.getName()); + } + return (Class) ((ParameterizedType) type).getActualTypeArguments()[pos]; + } else { + Type[] interfaces = clazz.getGenericInterfaces(); + for (Type itype : interfaces) { + if (!(itype instanceof ParameterizedType)) { + continue; + } + ParameterizedType interfaceType = (ParameterizedType) itype; + return (Class) interfaceType.getActualTypeArguments()[0]; + } + } + return null; + } + + /** + * Returns the set of interfaces implemented by the given class and its ancestors or a blank set if none + */ + public static Set<Class> getAllInterfaces(Class clazz) { + Set<Class> implemented = new HashSet<Class>(); + getAllInterfaces(clazz, implemented); + return implemented; + } + + private static void getAllInterfaces(Class clazz, Set<Class> implemented) { + Class[] interfaces = clazz.getInterfaces(); + for (Class interfaze : interfaces) { + implemented.add(interfaze); + } + Class<?> superClass = clazz.getSuperclass(); + // Object has no superclass so check for null + if (superClass != null && !superClass.equals(Object.class)) { + getAllInterfaces(superClass, implemented); + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/BridgingInterceptor.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/BridgingInterceptor.java new file mode 100644 index 0000000000..c1766fbb6f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/BridgingInterceptor.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import org.apache.tuscany.spi.wire.Interceptor; + +/** + * Responsible for bridging an outbound to an inbound invocation chain associated with a source and target respectively + * + * @version $Rev$ $Date$ + */ +public interface BridgingInterceptor extends Interceptor { +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundInvocationChainImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundInvocationChainImpl.java new file mode 100644 index 0000000000..45b580d419 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundInvocationChainImpl.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.InboundInvocationChain; + +/** + * Contains a target-side invocation chain + * + * @version $Rev$ $Date$ + */ +public class InboundInvocationChainImpl extends InvocationChainImpl implements InboundInvocationChain { + + /** + * Creates an new target-side chain for the given operation + */ + public InboundInvocationChainImpl(Operation operation) { + super(operation); + } + + public void prepare() { + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundWireImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundWireImpl.java new file mode 100644 index 0000000000..d940427e5a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InboundWireImpl.java @@ -0,0 +1,160 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; + +/** + * Default implementation of an inbound wire + * + * @version $Rev$ $Date$ + */ +public class InboundWireImpl implements InboundWire { + + private String serviceName; + private ServiceContract serviceContract; + private OutboundWire targetWire; + private String callbackReferenceName; + private Map<Operation<?>, InboundInvocationChain> chains = new HashMap<Operation<?>, InboundInvocationChain>(); + private Map<Object, Map<Operation<?>, OutboundInvocationChain>> callbackSourceChainMaps = + new HashMap<Object, Map<Operation<?>, OutboundInvocationChain>>(); + private SCAObject container; + private Map<Object, Object> msgIdsToAddrs = new ConcurrentHashMap<Object, Object>(); + + public Object getTargetService() throws TargetException { + if (targetWire != null) { + // optimized, no interceptors or handlers on either end + return targetWire.getTargetService(); + } + throw new TargetException("Target wire not optimized"); + } + + public ServiceContract getServiceContract() { + return serviceContract; + } + + public void setServiceContract(ServiceContract serviceContract) { + this.serviceContract = serviceContract; + } + + public void addInterface(Class claz) { + throw new UnsupportedOperationException("Additional proxy interfaces not yet supported"); + } + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public Map<Operation<?>, InboundInvocationChain> getInvocationChains() { + return chains; + } + + public void addInvocationChains(Map<Operation<?>, InboundInvocationChain> chains) { + this.chains.putAll(chains); + } + + public void addInvocationChain(Operation<?> operation, InboundInvocationChain chain) { + chains.put(operation, chain); + } + + public Map<Operation<?>, OutboundInvocationChain> getSourceCallbackInvocationChains(Object targetAddr) { + return callbackSourceChainMaps.get(targetAddr); + } + + public void addSourceCallbackInvocationChains(Object targetAddr, + Map<Operation<?>, OutboundInvocationChain> chains) { + callbackSourceChainMaps.put(targetAddr, chains); + } + + public void addSourceCallbackInvocationChain(Object targetAddr, Operation operation, + OutboundInvocationChain chain) { + Map<Operation<?>, OutboundInvocationChain> chains = callbackSourceChainMaps.get(targetAddr); + if (chains == null) { + chains = new HashMap<Operation<?>, OutboundInvocationChain>(); + callbackSourceChainMaps.put(targetAddr, chains); + } + chains.put(operation, chain); + } + + public void setTargetWire(OutboundWire wire) { + targetWire = wire; + } + + public String getCallbackReferenceName() { + return callbackReferenceName; + } + + public void setCallbackReferenceName(String callbackReferenceName) { + this.callbackReferenceName = callbackReferenceName; + } + + public boolean isOptimizable() { + for (InboundInvocationChain chain : chains.values()) { + if (chain.getTargetInvoker() != null && !chain.getTargetInvoker().isOptimizable()) { + return false; + } + if (chain.getHeadInterceptor() != null) { + Interceptor current = chain.getHeadInterceptor(); + while (current != null) { + if (!current.isOptimizable()) { + return false; + } + current = current.getNext(); + } + } + } + return true; + } + + public SCAObject getContainer() { + return container; + } + + public void setContainer(SCAObject container) { + this.container = container; + } + + public void addMapping(Object messageId, Object fromAddress) { + this.msgIdsToAddrs.put(messageId, fromAddress); + } + + public Object retrieveMapping(Object messageId) { + return this.msgIdsToAddrs.get(messageId); + } + + public void removeMapping(Object messageId) { + this.msgIdsToAddrs.remove(messageId); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvocationChainImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvocationChainImpl.java new file mode 100644 index 0000000000..d93426af4c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvocationChainImpl.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.InvocationChain; +import org.apache.tuscany.spi.wire.TargetInvoker; + +/** + * Contains functionality common to source- and target- side invocation chains + * + * @version $Rev$ $Date$ + */ +public abstract class InvocationChainImpl implements InvocationChain { + protected Operation operation; + protected TargetInvoker targetInvoker; + protected Interceptor interceptorChainHead; + protected Interceptor interceptorChainTail; + + + // the pointer to a bridged target head interceptor or null if the target has no interceptors + protected Interceptor targetInterceptorChainHead; + + public InvocationChainImpl(Operation operation) { + assert operation != null : "No operation type specified"; + this.operation = operation; + } + + public Operation getOperation() { + return operation; + } + + public void setTargetInvoker(TargetInvoker invoker) { + this.targetInvoker = invoker; + } + + public TargetInvoker getTargetInvoker() { + return targetInvoker; + } + + public void addInterceptor(Interceptor interceptor) { + if (interceptorChainHead == null) { + interceptorChainHead = interceptor; + } else { + interceptorChainTail.setNext(interceptor); + } + interceptorChainTail = interceptor; + } + + public void addInterceptor(int index, Interceptor interceptor) { + int i = 0; + Interceptor next = interceptorChainHead; + Interceptor prev = null; + while (next != null && i < index) { + prev = next; + next = next.getNext(); + i++; + } + if (i == index) { + if (prev != null) { + prev.setNext(interceptor); + } else { + interceptorChainHead = interceptor; + } + interceptor.setNext(next); + if (next == null) { + interceptorChainTail = interceptor; + } + } else { + throw new ArrayIndexOutOfBoundsException(index); + } + } + + public Interceptor getHeadInterceptor() { + return interceptorChainHead; + } + + public Interceptor getTailInterceptor() { + return interceptorChainTail; + } + + public void setTargetInterceptor(Interceptor interceptor) { + targetInterceptorChainHead = interceptor; + } + + public Interceptor getTargetInterceptor() { + return targetInterceptorChainHead; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvokerInterceptor.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvokerInterceptor.java new file mode 100644 index 0000000000..90b17a930c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/InvokerInterceptor.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.InvocationRuntimeException; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.TargetInvoker; + +/** + * Serves as a tail interceptor on a target wire chain. This implementation dispatches to the target invoker passed + * inside the wire message. Target invokers are passed from the source in order to allow for caching of target + * instances. + * + * @version $Rev$ $Date$ + * @see org.apache.tuscany.spi.wire.TargetInvoker + */ +public class InvokerInterceptor implements Interceptor { + + public InvokerInterceptor() { + } + + public Message invoke(Message msg) throws InvocationRuntimeException { + TargetInvoker invoker = msg.getTargetInvoker(); + if (invoker == null) { + throw new InvocationRuntimeException("No target invoker specified on message"); + } + return invoker.invoke(msg); + } + + public void setNext(Interceptor next) { + throw new IllegalStateException("This interceptor must be the last one in an target interceptor chain"); + } + + public Interceptor getNext() { + return null; + } + + public boolean isOptimizable() { + return true; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/NonBlockingBridgingInterceptor.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/NonBlockingBridgingInterceptor.java new file mode 100644 index 0000000000..fcc57174ab --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/NonBlockingBridgingInterceptor.java @@ -0,0 +1,171 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import org.osoa.sca.CompositeContext; +import org.osoa.sca.CurrentCompositeContext; +import org.osoa.sca.SCA; +import org.osoa.sca.ServiceRuntimeException; + +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.services.work.WorkScheduler; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.TargetInvoker; + +/** + * Bridges interceptors in a non-blocking fashion between an {@link org.apache.tuscany.spi.wire.InboundInvocationChain} + * and an {@link org.apache.tuscany.spi.wire.OutboundInvocationChain} by using a {@link + * org.apache.tuscany.spi.component.WorkContext}. + * + * @version $$Rev$$ $$Date$$ + */ +public class NonBlockingBridgingInterceptor implements BridgingInterceptor { + + private static final ContextBinder BINDER = new ContextBinder(); + private static final Message RESPONSE = new ImmutableMessage(); + + private WorkScheduler workScheduler; + private WorkContext workContext; + private Interceptor next; + + public NonBlockingBridgingInterceptor(WorkScheduler workScheduler, WorkContext workContext) { + this.workScheduler = workScheduler; + this.workContext = workContext; + } + + public NonBlockingBridgingInterceptor(WorkScheduler workScheduler, WorkContext workContext, Interceptor next) { + this.workScheduler = workScheduler; + this.workContext = workContext; + this.next = next; + } + + public Message invoke(final Message msg) { + final CompositeContext currentContext = CurrentCompositeContext.getContext(); + // Schedule the invocation of the next interceptor in a new Work instance + try { + workScheduler.scheduleWork(new Runnable() { + public void run() { + workContext.setCurrentMessageId(null); + workContext.setCurrentCorrelationId(null); + CompositeContext oldContext = CurrentCompositeContext.getContext(); + try { + BINDER.setContext(currentContext); + next.invoke(msg); + } catch (Exception e) { + // REVIEW uncomment when it is available + // monitor.executionError(e); + e.printStackTrace(); + } finally { + BINDER.setContext(oldContext); + } + } + }); + } catch (Exception e) { + throw new ServiceRuntimeException(e); + } + return RESPONSE; + } + + public Interceptor getNext() { + return next; + } + + public void setNext(Interceptor next) { + this.next = next; + } + + public boolean isOptimizable() { + return true; + } + + private static class ContextBinder extends SCA { + public void setContext(CompositeContext context) { + setCompositeContext(context); + } + + public void start() { + throw new AssertionError(); + } + + public void stop() { + throw new AssertionError(); + } + } + + /** + * A dummy message passed back on an invocation + */ + private static class ImmutableMessage implements Message { + + public Object getBody() { + return null; + } + + public void setBody(Object body) { + throw new UnsupportedOperationException(); + } + + public void setTargetInvoker(TargetInvoker invoker) { + throw new UnsupportedOperationException(); + } + + public TargetInvoker getTargetInvoker() { + return null; + } + + public Message getRelatedCallbackMessage() { + return null; + } + + public Object getFromAddress() { + return null; + } + + public void setFromAddress(Object fromAddress) { + throw new UnsupportedOperationException(); + } + + public Object getMessageId() { + return null; + } + + public void setMessageId(Object messageId) { + throw new UnsupportedOperationException(); + } + + public Object getCorrelationId() { + return null; + } + + public void setCorrelationId(Object correlationId) { + throw new UnsupportedOperationException(); + } + + public boolean isFault() { + return false; + } + + public void setBodyWithFault(Object fault) { + throw new UnsupportedOperationException(); + } + + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundAutowire.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundAutowire.java new file mode 100644 index 0000000000..c2824b3c88 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundAutowire.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import org.apache.tuscany.spi.wire.OutboundWire; + +/** + * A specialized outbound wire that uses an autowire algorithm to return reference to the target. + * + * @version $$Rev$$ $$Date$$ + */ +public interface OutboundAutowire extends OutboundWire { +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundInvocationChainImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundInvocationChainImpl.java new file mode 100644 index 0000000000..a9d83cb7a0 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundInvocationChainImpl.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; + +/** + * Contains a outgoing invocation pipeline for a service operation. + * + * @version $Rev$ $Date$ + */ +public class OutboundInvocationChainImpl extends InvocationChainImpl implements OutboundInvocationChain { + + /** + * Creates an new outbound chain + */ + public OutboundInvocationChainImpl(Operation operation) { + super(operation); + } + + public void prepare() { + if (interceptorChainHead != null) { + if (targetInterceptorChainHead != null) { + // Connect source interceptor chain directly to target interceptor chain + interceptorChainTail.setNext(targetInterceptorChainHead); + } + } else { + // no source interceptor chain or source handlers, connect to target interceptor chain or channel + if (targetInterceptorChainHead != null) { + interceptorChainHead = targetInterceptorChainHead; + interceptorChainTail = targetInterceptorChainHead; + } + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundWireImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundWireImpl.java new file mode 100644 index 0000000000..4dc5241171 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/OutboundWireImpl.java @@ -0,0 +1,170 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.QualifiedName; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; + +/** + * Default implementation of an outbound wire + * + * @version $Rev$ $Date$ + */ +public class OutboundWireImpl implements OutboundWire { + + private ServiceContract serviceContract; + private Class<?>[] callbackInterfaces; + private Map<Operation<?>, OutboundInvocationChain> chains = new HashMap<Operation<?>, OutboundInvocationChain>(); + private Map<Operation<?>, InboundInvocationChain> callbackTargetChains = + new HashMap<Operation<?>, InboundInvocationChain>(); + private String referenceName; + private QualifiedName targetName; + private InboundWire targetWire; + private SCAObject container; + + public Object getTargetService() throws TargetException { + if (targetWire != null) { + // optimized, no interceptors or handlers on either end + return targetWire.getTargetService(); + } + throw new TargetException("Target wire not optimized"); + } + + public ServiceContract getServiceContract() { + return serviceContract; + } + + public void setServiceContract(ServiceContract serviceContract) { + this.serviceContract = serviceContract; + } + + public void addInterface(Class<?> claz) { + throw new UnsupportedOperationException("Additional proxy interfaces not yet supported"); + } + + public void setCallbackInterface(Class<?> interfaze) { + callbackInterfaces = new Class[]{interfaze}; + } + + public Class<?> getCallbackInterface() { + return callbackInterfaces[0]; + } + + public void addCallbackInterface(Class<?> claz) { + throw new UnsupportedOperationException("Additional callback interfaces not yet supported"); + } + + public Class[] getImplementedCallbackInterfaces() { + return callbackInterfaces; + } + + public void setTargetWire(InboundWire wire) { + this.targetWire = wire; + } + + public Map<Operation<?>, OutboundInvocationChain> getInvocationChains() { + return chains; + } + + public void addInvocationChains(Map<Operation<?>, OutboundInvocationChain> chains) { + this.chains.putAll(chains); + } + + public void addInvocationChain(Operation<?> operation, OutboundInvocationChain chain) { + chains.put(operation, chain); + } + + public Map<Operation<?>, InboundInvocationChain> getTargetCallbackInvocationChains() { + return callbackTargetChains; + } + + public void addTargetCallbackInvocationChains(Map<Operation<?>, InboundInvocationChain> chains) { + callbackTargetChains.putAll(chains); + } + + public void addTargetCallbackInvocationChain(Operation operation, InboundInvocationChain chain) { + callbackTargetChains.put(operation, chain); + } + + public String getReferenceName() { + return referenceName; + } + + public void setReferenceName(String referenceName) { + this.referenceName = referenceName; + } + + public QualifiedName getTargetName() { + return targetName; + } + + public void setTargetName(QualifiedName targetName) { + this.targetName = targetName; + } + + public boolean isOptimizable() { + for (OutboundInvocationChain chain : chains.values()) { + if (chain.getHeadInterceptor() != null) { + Interceptor current = chain.getHeadInterceptor(); + while (current != null && current != chain.getTargetInterceptor()) { + if (!current.isOptimizable()) { + return false; + } + current = current.getNext(); + } + } + } + + for (InboundInvocationChain chain : callbackTargetChains.values()) { + if (chain.getTargetInvoker() != null && !chain.getTargetInvoker().isOptimizable()) { + return false; + } + if (chain.getHeadInterceptor() != null) { + Interceptor current = chain.getHeadInterceptor(); + while (current != null) { + if (!current.isOptimizable()) { + return false; + } + current = current.getNext(); + } + } + } + + return true; + } + + public SCAObject getContainer() { + return container; + } + + public void setContainer(SCAObject container) { + this.container = container; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/PojoTargetInvoker.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/PojoTargetInvoker.java new file mode 100644 index 0000000000..4c967e6c3f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/PojoTargetInvoker.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Set; + +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.wire.InvocationRuntimeException; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.TargetInvoker; + +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.findClosestMatchingMethod; +import static org.apache.tuscany.core.util.JavaIntrospectionHelper.getAllUniquePublicProtectedMethods; + +/** + * Base class for dispatching to a Java based component implementation. Subclasses implement a strategy for resolving + * implementation instances. + * + * @version $Rev$ $Date$ + */ +public abstract class PojoTargetInvoker implements TargetInvoker { + + protected Method operation; + protected boolean cacheable; + + public PojoTargetInvoker(Method operation) { + assert operation != null : "Operation method cannot be null"; + this.operation = operation; + } + + public Object invokeTarget(final Object payload) throws InvocationTargetException { + try { + Object instance = getInstance(); + if (!operation.getDeclaringClass().isInstance(instance)) { + Set<Method> methods = getAllUniquePublicProtectedMethods(instance.getClass()); + Method newOperation = findClosestMatchingMethod(operation.getName(), + operation.getParameterTypes(), methods); + if (newOperation != null) { + operation = newOperation; + } + } + if (payload != null && !payload.getClass().isArray()) { + return operation.invoke(instance, payload); + } else { + return operation.invoke(instance, (Object[]) payload); + } + } catch (IllegalAccessException e) { + throw new InvocationRuntimeException(e); + } + } + + public Message invoke(Message msg) throws InvocationRuntimeException { + try { + Object resp = invokeTarget(msg.getBody()); + msg.setBody(resp); + } catch (InvocationTargetException e) { + msg.setBodyWithFault(e.getCause()); + } catch (Throwable e) { + msg.setBodyWithFault(e); + } + return msg; + } + + public boolean isCacheable() { + return cacheable; + } + + public void setCacheable(boolean cacheable) { + this.cacheable = cacheable; + } + + public boolean isOptimizable() { + return isCacheable(); // we only need to check if the scopes are correct + } + + @Override + public PojoTargetInvoker clone() throws CloneNotSupportedException { + try { + PojoTargetInvoker clone = (PojoTargetInvoker) super.clone(); + clone.operation = this.operation; + return clone; + } catch (CloneNotSupportedException e) { + return null; // will not happen + } + } + + protected abstract Object getInstance() throws TargetException; + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/StaticPojoTargetInvoker.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/StaticPojoTargetInvoker.java new file mode 100644 index 0000000000..d836661ceb --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/StaticPojoTargetInvoker.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.core.wire; + +import java.lang.reflect.Method; + +/** + * Caches component instances that do not need to be resolved for every wire, e.g. an wire originating from a lesser + * scope intended for a target with a wider scope + * + * @version $Rev$ $Date$ + */ +public class StaticPojoTargetInvoker extends PojoTargetInvoker { + + private Object instance; + + public StaticPojoTargetInvoker(Method operation, Object instance) { + super(operation); + assert instance != null : "Instance cannot be null"; + this.instance = instance; + } + + protected Object getInstance() { + return instance; + } + + public StaticPojoTargetInvoker clone() throws CloneNotSupportedException { + StaticPojoTargetInvoker invoker = (StaticPojoTargetInvoker) super.clone(); + invoker.instance = null; + return invoker; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/SynchronousBridgingInterceptor.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/SynchronousBridgingInterceptor.java new file mode 100644 index 0000000000..f09bda400a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/SynchronousBridgingInterceptor.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.Message; + +/** + * Synchronously bridges interceptors between an {@link org.apache.tuscany.spi.wire.InboundInvocationChain} and an + * {@link org.apache.tuscany.spi.wire.OutboundInvocationChain}. + * + * @version $$Rev$$ $$Date$$ + */ +public class SynchronousBridgingInterceptor implements BridgingInterceptor { + private Interceptor next; + + public SynchronousBridgingInterceptor() { + } + + public SynchronousBridgingInterceptor(Interceptor next) { + this.next = next; + } + + public Message invoke(Message msg) { + return next.invoke(msg); + } + + public Interceptor getNext() { + return next; + } + + public void setNext(Interceptor next) { + this.next = next; + } + + public boolean isOptimizable() { + return true; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKCallbackInvocationHandler.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKCallbackInvocationHandler.java new file mode 100644 index 0000000000..d146da6283 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKCallbackInvocationHandler.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire.jdk; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.Map; + +import org.apache.tuscany.spi.component.WorkContext; +import static org.apache.tuscany.spi.idl.java.JavaIDLUtils.findOperation; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.AbstractOutboundInvocationHandler; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.TargetInvoker; +import org.apache.tuscany.spi.wire.WireInvocationHandler; + + +/** + * Responsible for invoking on an outbound wire associated with a callback. The handler retrieves the correct outbound + * callback wire from the work context. + * <p/> + * TODO cache target invoker + * + * @version $Rev$ $Date$ + */ +public class JDKCallbackInvocationHandler extends AbstractOutboundInvocationHandler + implements WireInvocationHandler, InvocationHandler { + + private WorkContext context; + private InboundWire inboundWire; + private Object messageId; + private Object correlationId; + + public JDKCallbackInvocationHandler(WorkContext context, InboundWire inboundWire) { + this.context = context; + this.inboundWire = inboundWire; + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + messageId = context.getCurrentMessageId(); + context.setCurrentMessageId(null); + correlationId = context.getCurrentCorrelationId(); + context.setCurrentCorrelationId(null); + Object targetAddress = inboundWire.retrieveMapping(correlationId); + if (targetAddress == null) { + throw new AssertionError("No from address associated with message id [" + correlationId + "]"); + } + //TODO optimize as this is slow in local invocations + Map<Operation<?>, OutboundInvocationChain> sourceCallbackInvocationChains = + inboundWire.getSourceCallbackInvocationChains(targetAddress); + Operation operation = findOperation(method, sourceCallbackInvocationChains.keySet()); + OutboundInvocationChain chain = sourceCallbackInvocationChains.get(operation); + TargetInvoker invoker = chain.getTargetInvoker(); + return invoke(chain, invoker, args); + } + + + public Object invoke(Method method, Object[] args) throws Throwable { + return invoke(null, method, args); + } + + protected Object getFromAddress() { + return (inboundWire.getContainer() == null) ? null : inboundWire.getContainer().getName(); + } + + protected Object getMessageId() { + return messageId; + } + + protected Object getCorrelationId() { + return correlationId; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKInboundInvocationHandler.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKInboundInvocationHandler.java new file mode 100644 index 0000000000..43cbe4be88 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKInboundInvocationHandler.java @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire.jdk; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.wire.AbstractInboundInvocationHandler; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.TargetInvoker; +import org.apache.tuscany.spi.wire.WireInvocationHandler; + + +/** + * Receives a request from a proxy and performs an invocation on an {@link org.apache.tuscany.spi.wire.InboundWire} via + * an {@link InboundInvocationChain} + * + * @version $Rev$ $Date$ + */ +public class JDKInboundInvocationHandler extends AbstractInboundInvocationHandler + implements WireInvocationHandler, InvocationHandler { + + /* + * an association of an operation to chain holder. The holder contains the invocation chain + * and a local clone of the master TargetInvoker. TargetInvokers will be cloned by the handler and placed in the + * holder if they are cacheable. This allows optimizations such as avoiding target resolution when a source refers + * to a target of greater scope since the target reference can be maintained by the invoker. When a target invoker + * is not cacheable, the master associated with the wire chains will be used. + */ + private Map<Method, ChainHolder> chains; + private WorkContext context; + private Object messageId; + private Object correlationId; + + public JDKInboundInvocationHandler(Map<Method, InboundInvocationChain> invocationChains, WorkContext context) { + this.chains = new HashMap<Method, ChainHolder>(invocationChains.size()); + for (Map.Entry<Method, InboundInvocationChain> entry : invocationChains.entrySet()) { + this.chains.put(entry.getKey(), new ChainHolder(entry.getValue())); + } + this.context = context; + } + + /** + * Dispatches a client request made on a proxy + */ + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + ChainHolder holder = chains.get(method); + if (holder == null) { + if (method.getParameterTypes().length == 0 && "toString".equals(method.getName())) { + return "[Proxy - " + Integer.toHexString(hashCode()) + "]"; + } else if (method.getDeclaringClass().equals(Object.class) + && "equals".equals(method.getName())) { + // TODO implement + throw new UnsupportedOperationException(); + } else if (Object.class.equals(method.getDeclaringClass()) + && "hashCode".equals(method.getName())) { + return hashCode(); + // TODO beter hash algorithm + } + TargetException e = new TargetException("Operation not configured"); + e.setIdentifier(method.getName()); + throw e; + } + InboundInvocationChain chain = holder.chain; + TargetInvoker invoker; + if (holder.cachedInvoker == null) { + assert chain != null; + if (chain.getTargetInvoker() == null) { + TargetException e = new TargetException("No target invoker configured for operation"); + e.setIdentifier(chain.getOperation().getName()); + throw e; + } + if (chain.getTargetInvoker().isCacheable()) { + // clone and store the invoker locally + holder.cachedInvoker = (TargetInvoker) chain.getTargetInvoker().clone(); + invoker = holder.cachedInvoker; + } else { + invoker = chain.getTargetInvoker(); + } + } else { + assert chain != null; + invoker = chain.getTargetInvoker(); + } + messageId = context.getCurrentMessageId(); + context.setCurrentMessageId(null); + correlationId = context.getCurrentCorrelationId(); + context.setCurrentCorrelationId(null); + return invoke(chain, invoker, args); + } + + + public Object invoke(Method method, Object[] args) throws Throwable { + return invoke(null, method, args); + } + + /** + * A holder used to associate an wire chain with a local copy of a target invoker that was previously cloned from + * the chain master + */ + private class ChainHolder { + + InboundInvocationChain chain; + TargetInvoker cachedInvoker; + + public ChainHolder(InboundInvocationChain config) { + this.chain = config; + } + + } + + protected Object getMessageId() { + return messageId; + } + + protected Object getCorrelationId() { + return correlationId; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKOutboundInvocationHandler.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKOutboundInvocationHandler.java new file mode 100644 index 0000000000..a2ca344624 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKOutboundInvocationHandler.java @@ -0,0 +1,155 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire.jdk; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.component.TargetException; +import org.apache.tuscany.spi.component.WorkContext; +import static org.apache.tuscany.spi.idl.java.JavaIDLUtils.findMethod; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.AbstractOutboundInvocationHandler; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.TargetInvoker; +import org.apache.tuscany.spi.wire.WireInvocationHandler; + + +/** + * Receives a request from a proxy and performs an invocation on an {@link org.apache.tuscany.spi.wire.OutboundWire} via + * an {@link org.apache.tuscany.spi.wire.OutboundInvocationChain} + * + * @version $Rev$ $Date$ + */ +public class JDKOutboundInvocationHandler extends AbstractOutboundInvocationHandler + implements WireInvocationHandler, InvocationHandler { + + /* + * an association of an operation to chain holder. The holder contains an invocation chain + * and a local clone of the master TargetInvoker. TargetInvokers will be cloned by the handler and placed in the + * holder if they are cacheable. This allows optimizations such as avoiding target resolution when a source refers + * to a target of greater scope since the target reference can be maintained by the invoker. When a target invoker + * is not cacheable, the master associated with the wire chains will be used. + */ + private Map<Method, ChainHolder> chains; + private WorkContext context; + private Object fromAddress; + private Object messageId; + private Object correlationId; + + public JDKOutboundInvocationHandler(OutboundWire wire, WorkContext context) + throws NoMethodForOperationException { + Map<Operation<?>, OutboundInvocationChain> invocationChains = wire.getInvocationChains(); + this.chains = new HashMap<Method, ChainHolder>(invocationChains.size()); + this.fromAddress = (wire.getContainer() == null) ? null : wire.getContainer().getName(); + Method[] methods = wire.getServiceContract().getInterfaceClass().getMethods(); + // TODO optimize this + for (Map.Entry<Operation<?>, OutboundInvocationChain> entry : invocationChains.entrySet()) { + Operation operation = entry.getKey(); + Method method = findMethod(operation, methods); + if (method == null) { + throw new NoMethodForOperationException(operation.getName()); + } + this.chains.put(method, new ChainHolder(entry.getValue())); + } + + this.context = context; + } + + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + ChainHolder holder = chains.get(method); + if (holder == null) { + if (method.getParameterTypes().length == 0 && "toString".equals(method.getName())) { + return "[Proxy - " + Integer.toHexString(hashCode()) + "]"; + } else if (method.getDeclaringClass().equals(Object.class) + && "equals".equals(method.getName())) { + // TODO implement + throw new UnsupportedOperationException(); + } else if (Object.class.equals(method.getDeclaringClass()) + && "hashCode".equals(method.getName())) { + return hashCode(); + // TODO beter hash algorithm + } + TargetException e = new TargetException("Operation not configured"); + e.setIdentifier(method.getName()); + throw e; + } + OutboundInvocationChain chain = holder.chain; + TargetInvoker invoker; + + if (holder.cachedInvoker == null) { + assert chain != null; + if (chain.getTargetInvoker() == null) { + TargetException e = new TargetException("No target invoker configured for operation"); + e.setIdentifier(chain.getOperation().getName()); + throw e; + } + if (chain.getTargetInvoker().isCacheable()) { + // clone and store the invoker locally + holder.cachedInvoker = (TargetInvoker) chain.getTargetInvoker().clone(); + invoker = holder.cachedInvoker; + } else { + invoker = chain.getTargetInvoker(); + } + } else { + assert chain != null; + invoker = chain.getTargetInvoker(); + } + messageId = context.getCurrentMessageId(); + context.setCurrentMessageId(null); + correlationId = context.getCurrentCorrelationId(); + context.setCurrentCorrelationId(null); + return invoke(chain, invoker, args); + } + + public Object invoke(Method method, Object[] args) throws Throwable { + return invoke(null, method, args); + } + + protected Object getFromAddress() { + return fromAddress; + } + + protected Object getMessageId() { + return messageId; + } + + protected Object getCorrelationId() { + return correlationId; + } + + /** + * A holder used to associate an wire chain with a local copy of a target invoker that was previously cloned from + * the chain master + */ + private class ChainHolder { + + OutboundInvocationChain chain; + TargetInvoker cachedInvoker; + + public ChainHolder(OutboundInvocationChain config) { + this.chain = config; + } + + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKWireService.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKWireService.java new file mode 100644 index 0000000000..7c7693ca3e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/JDKWireService.java @@ -0,0 +1,341 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire.jdk; + +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.HashMap; +import java.util.Map; + +import org.osoa.sca.annotations.Constructor; +import org.osoa.sca.annotations.Init; +import org.osoa.sca.annotations.Scope; + +import org.apache.tuscany.spi.QualifiedName; +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.Reference; +import org.apache.tuscany.spi.component.ReferenceNotFoundException; +import org.apache.tuscany.spi.component.Service; +import org.apache.tuscany.spi.component.WorkContext; +import static org.apache.tuscany.spi.idl.java.JavaIDLUtils.findMethod; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.ComponentType; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.Implementation; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ReferenceDefinition; +import org.apache.tuscany.spi.model.ReferenceTarget; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.model.ServiceDefinition; +import org.apache.tuscany.spi.policy.PolicyBuilderRegistry; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.ProxyCreationException; +import org.apache.tuscany.spi.wire.RuntimeWire; +import org.apache.tuscany.spi.wire.WireInvocationHandler; +import org.apache.tuscany.spi.wire.WireServiceExtension; + +import org.apache.tuscany.core.implementation.composite.CompositeReference; +import org.apache.tuscany.core.implementation.composite.CompositeService; +import org.apache.tuscany.core.wire.InboundInvocationChainImpl; +import org.apache.tuscany.core.wire.InboundWireImpl; +import org.apache.tuscany.core.wire.InvokerInterceptor; +import org.apache.tuscany.core.wire.OutboundInvocationChainImpl; +import org.apache.tuscany.core.wire.OutboundWireImpl; + +/** + * the default implementation of a wire service that uses JDK dynamic proxies + * + * @version $$Rev$$ $$Date$$ + */ +@Scope("MODULE") +public class JDKWireService extends WireServiceExtension { + + public JDKWireService() { + super(null, null); + } + + @Constructor({"workContext", "policyregisty"}) + public JDKWireService(@Autowire WorkContext context, @Autowire PolicyBuilderRegistry policyRegistry) { + super(context, policyRegistry); + } + + @Init(eager = true) + public void init() { + } + + public Object createProxy(RuntimeWire wire) throws ProxyCreationException { + assert wire != null : "Wire was null"; + if (wire instanceof InboundWire) { + InboundWire inbound = (InboundWire) wire; + Class<?> interfaze = wire.getServiceContract().getInterfaceClass(); + Method[] methods = interfaze.getMethods(); + Map<Method, InboundInvocationChain> chains = createInboundMapping(inbound, methods); + JDKInboundInvocationHandler handler = new JDKInboundInvocationHandler(chains, context); + ClassLoader cl = interfaze.getClassLoader(); + //FIXME + return Proxy.newProxyInstance(cl, new Class[]{interfaze}, handler); + } else if (wire instanceof OutboundWire) { + OutboundWire outbound = (OutboundWire) wire; + JDKOutboundInvocationHandler handler = new JDKOutboundInvocationHandler(outbound, context); + Class<?> interfaze = outbound.getServiceContract().getInterfaceClass(); + ClassLoader cl = interfaze.getClassLoader(); + return Proxy.newProxyInstance(cl, new Class[]{interfaze}, handler); + } else { + ProxyCreationException e = new ProxyCreationException("Invalid wire type"); + e.setIdentifier(wire.getClass().getName()); + throw e; + } + } + + public Object createCallbackProxy(ServiceContract<?> contract, InboundWire wire) throws ProxyCreationException { + Class<?> interfaze = contract.getCallbackClass(); + ClassLoader cl = interfaze.getClassLoader(); + JDKCallbackInvocationHandler handler = new JDKCallbackInvocationHandler(context, wire); + return interfaze.cast(Proxy.newProxyInstance(cl, new Class[]{interfaze}, handler)); + } + + public WireInvocationHandler createHandler(RuntimeWire wire) { + assert wire != null : "Wire was null"; + if (wire instanceof InboundWire) { + InboundWire inbound = (InboundWire) wire; + Method[] methods = inbound.getServiceContract().getInterfaceClass().getMethods(); + Map<Method, InboundInvocationChain> chains = createInboundMapping(inbound, methods); + return new JDKInboundInvocationHandler(chains, context); + } else if (wire instanceof OutboundWire) { + OutboundWire outbound = (OutboundWire) wire; + return new JDKOutboundInvocationHandler(outbound, context); + } else { + ProxyCreationException e = new ProxyCreationException("Invalid wire type"); + e.setIdentifier(wire.getClass().getName()); + throw e; + } + } + + public WireInvocationHandler createCallbackHandler(InboundWire wire) { + return new JDKCallbackInvocationHandler(context, wire); + } + + public OutboundInvocationChain createOutboundChain(Operation<?> operation) { + return new OutboundInvocationChainImpl(operation); + } + + public InboundInvocationChain createInboundChain(Operation<?> operation) { + return new InboundInvocationChainImpl(operation); + } + + public void createWires(Component component, ComponentDefinition<?> definition) { + Implementation<?> implementation = definition.getImplementation(); + ComponentType<?, ?, ?> componentType = implementation.getComponentType(); + for (ServiceDefinition service : componentType.getServices().values()) { + InboundWire inboundWire = createWire(service); + inboundWire.setContainer(component); + if (componentType instanceof CompositeComponentType<?, ?, ?>) { + // If this is the case, then it means that component has already been returned + // by CompositeBuilder and thus its children, in particular composite services, + // have been registered + CompositeComponent compositeComponent = (CompositeComponent) component; + Service serviceChild = (Service) compositeComponent.getChild(service.getName()); + assert serviceChild != null; + if (serviceChild instanceof CompositeService) { + serviceChild.setInboundWire(inboundWire); + // Notice that now the more immediate container of the wire is the composite service + inboundWire.setContainer(serviceChild); + } + } + component.addInboundWire(inboundWire); + } + + for (ReferenceTarget referenceTarget : definition.getReferenceTargets().values()) { + Map<String, ? extends ReferenceDefinition> references = componentType.getReferences(); + ReferenceDefinition mappedReference = references.get(referenceTarget.getReferenceName()); + if (mappedReference == null) { + String refName = referenceTarget.getReferenceName(); + ReferenceNotFoundException e = new ReferenceNotFoundException(refName); + e.addContextName(refName); + e.addContextName(definition.getName()); + throw e; + } + OutboundWire wire = createWire(referenceTarget, mappedReference); + wire.setContainer(component); + component.addOutboundWire(wire); + if (componentType instanceof CompositeComponentType<?, ?, ?>) { + // If this is the case, then it means that component has already been returned + // by CompositeBuilder and thus its children, in particular composite references, + // have been registered + CompositeComponent compositeComponent = (CompositeComponent) component; + Reference reference = (Reference) compositeComponent.getChild(referenceTarget.getReferenceName()); + assert reference != null; + if (reference instanceof CompositeReference) { + reference.setOutboundWire(wire); + // Notice that now the more immediate container of the wire is the composite reference + wire.setContainer(reference); + } + } + } + } + + public void createWires(Reference reference, ServiceContract<?> contract) { + InboundWire inboundWire = new InboundWireImpl(); + inboundWire.setServiceContract(contract); + inboundWire.setContainer(reference); + for (Operation<?> operation : contract.getOperations().values()) { + InboundInvocationChain chain = createInboundChain(operation); + inboundWire.addInvocationChain(operation, chain); + } + OutboundWire outboundWire = new OutboundWireImpl(); + + // [rfeng] Check if the Reference has the binding contract + ServiceContract<?> bindingContract = reference.getBindingServiceContract(); + if (bindingContract == null) { + bindingContract = contract; + } + outboundWire.setServiceContract(bindingContract); + outboundWire.setContainer(reference); + for (Operation<?> operation : bindingContract.getOperations().values()) { + OutboundInvocationChain chain = createOutboundChain(operation); + chain.addInterceptor(new InvokerInterceptor()); + outboundWire.addInvocationChain(operation, chain); + } + + // Notice that we skip inboundWire.setCallbackReferenceName + // First, an inbound inboundWire's callbackReferenceName is only retrieved by JavaAtomicComponent + // to create a callback injector based on the callback reference member; a composite reference + // should not need to do that + // Second, a reference definition does not have a callback reference name like a service + // definition does + reference.setInboundWire(inboundWire); + reference.setOutboundWire(outboundWire); + } + + public OutboundWire createWire(ReferenceTarget reference, ReferenceDefinition def) { + //TODO multiplicity + if (reference.getTargets().size() != 1) { + throw new UnsupportedOperationException(); + } + ServiceContract<?> contract = def.getServiceContract(); + OutboundWire wire = new OutboundWireImpl(); + QualifiedName qName = new QualifiedName(reference.getTargets().get(0).toString()); + wire.setTargetName(qName); + wire.setServiceContract(contract); + wire.setReferenceName(reference.getReferenceName()); + for (Operation<?> operation : contract.getOperations().values()) { + //TODO handle policy + OutboundInvocationChain chain = createOutboundChain(operation); + wire.addInvocationChain(operation, chain); + + } + if (contract.getCallbackName() != null) { + wire.setCallbackInterface(contract.getCallbackClass()); + for (Operation<?> operation : contract.getCallbackOperations().values()) { + InboundInvocationChain callbackTargetChain = createInboundChain(operation); + // TODO handle policy + //TODO statement below could be cleaner + callbackTargetChain.addInterceptor(new InvokerInterceptor()); + wire.addTargetCallbackInvocationChain(operation, callbackTargetChain); + } + } + return wire; + } + + public InboundWire createWire(ServiceDefinition service) { + InboundWire wire = new InboundWireImpl(); + ServiceContract<?> contract = service.getServiceContract(); + wire.setServiceContract(contract); + wire.setServiceName(service.getName()); + for (Operation<?> operation : contract.getOperations().values()) { + InboundInvocationChain chain = createInboundChain(operation); + // TODO handle policy + //TODO statement below could be cleaner + chain.addInterceptor(new InvokerInterceptor()); + wire.addInvocationChain(operation, chain); + } + if (contract.getCallbackName() != null) { + wire.setCallbackReferenceName(service.getCallbackReferenceName()); + } + return wire; + } + + public void createWires(Service service, String targetName, ServiceContract<?> contract) { + InboundWire inboundWire = new InboundWireImpl(); + + // [rfeng] Check if the Reference has the binding contract + ServiceContract<?> bindingContract = service.getBindingServiceContract(); + if (bindingContract == null) { + bindingContract = contract; + } + inboundWire.setServiceContract(bindingContract); + inboundWire.setContainer(service); + for (Operation<?> operation : bindingContract.getOperations().values()) { + InboundInvocationChain inboundChain = createInboundChain(operation); + inboundWire.addInvocationChain(operation, inboundChain); + } + + OutboundWire outboundWire = new OutboundWireImpl(); + outboundWire.setServiceContract(contract); + outboundWire.setTargetName(new QualifiedName(targetName)); + outboundWire.setContainer(service); + + for (Operation<?> operation : contract.getOperations().values()) { + OutboundInvocationChain outboundChain = createOutboundChain(operation); + outboundWire.addInvocationChain(operation, outboundChain); + } + + // Add target callback chain to outbound wire, applicable to both bound and bindless services + if (contract.getCallbackName() != null) { + outboundWire.setCallbackInterface(contract.getCallbackClass()); + for (Operation<?> operation : contract.getCallbackOperations().values()) { + InboundInvocationChain callbackTargetChain = createInboundChain(operation); +// TODO handle policy +//TODO statement below could be cleaner + callbackTargetChain.addInterceptor(new InvokerInterceptor()); + outboundWire.addTargetCallbackInvocationChain(operation, callbackTargetChain); + } + } + + // Not clear in any case why this is done here and at the parent composite level as well + // But for a composite service, make sure that the inbound wire comes from the parent + if (!(service instanceof CompositeService)) { + service.setInboundWire(inboundWire); + } + service.setOutboundWire(outboundWire); + } + + + private Map<Method, InboundInvocationChain> createInboundMapping(InboundWire wire, Method[] methods) + throws NoMethodForOperationException { + Map<Method, InboundInvocationChain> chains = new HashMap<Method, InboundInvocationChain>(); + for (Map.Entry<Operation<?>, InboundInvocationChain> entry : wire.getInvocationChains().entrySet()) { + Operation<?> operation = entry.getKey(); + InboundInvocationChain chain = entry.getValue(); + Method method = findMethod(operation, methods); + if (method == null) { + NoMethodForOperationException e = new NoMethodForOperationException(); + e.setIdentifier(operation.getName()); + } + chains.put(method, chain); + } + return chains; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/NoMethodForOperationException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/NoMethodForOperationException.java new file mode 100644 index 0000000000..5a123ee814 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/java/org/apache/tuscany/core/wire/jdk/NoMethodForOperationException.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire.jdk; + +import org.apache.tuscany.spi.wire.ProxyCreationException; + +/** + * Thrown when an {@link org.apache.tuscany.spi.model.Operation} cannot be mapped to a method on an interface + * @version $Rev$ $Date$ + */ +public class NoMethodForOperationException extends ProxyCreationException { + public NoMethodForOperationException() { + } + + public NoMethodForOperationException(String message) { + super(message); + } + + public NoMethodForOperationException(String message, Throwable cause) { + super(message, cause); + } + + public NoMethodForOperationException(Throwable cause) { + super(cause); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/composite.scdl b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/composite.scdl new file mode 100644 index 0000000000..3531df98ad --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/composite.scdl @@ -0,0 +1,48 @@ +<?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. +--> +<!-- + Default system configuration for the launcher environment. + + $Rev$ $Date$ +--> +<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" + xmlns:system="http://incubator.apache.org/tuscany/xmlns/system/1.0-incubator-M2" + name="org.apache.tuscany.core.Composite"> + + <!-- Composite implementation type --> + <component name="composite.loader"> + <system:implementation.system class="org.apache.tuscany.core.implementation.composite.CompositeLoader"/> + </component> + <component name="composite.implementationLoader"> + <system:implementation.system class="org.apache.tuscany.core.implementation.composite.ImplementationCompositeLoader"/> + </component> + <component name="composite.dependencyLoader"> + <system:implementation.system class="org.apache.tuscany.core.implementation.composite.DependencyLoader"/> + </component> + <component name="composite.componentTypeLoader"> + <system:implementation.system class="org.apache.tuscany.core.implementation.composite.CompositeComponentTypeLoader"/> + </component> + <component name="composite.builder"> + <system:implementation.system class="org.apache.tuscany.core.implementation.composite.CompositeBuilder"/> + </component> + <component name="composite.bindlessbuilder"> + <system:implementation.system class="org.apache.tuscany.core.implementation.composite.CompositeBindlessBuilder"/> + </component> +</composite> diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/databinding.scdl b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/databinding.scdl new file mode 100644 index 0000000000..0ee347aa91 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/databinding.scdl @@ -0,0 +1,153 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+--> +<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" xmlns:system="http://incubator.apache.org/tuscany/xmlns/system/1.0-incubator-M2"
+ name="org.apache.tuscany.core.DataBinding">
+
+ <component name="databinding.wirePostProcessor">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.impl.DataBindingWirePostProcessor" />
+ </component>
+
+ <component name="databinding.javaInterfaceProcessor">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.impl.DataBindingJavaInterfaceProcessor" />
+ </component>
+
+ <!-- DataBinding registry -->
+ <component name="databinding.registry">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.impl.DataBindingRegistryImpl" />
+ </component>
+
+ <!-- DataBinding registry -->
+ <component name="databinding.mediator">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.impl.MediatorImpl" />
+ </component>
+
+ <!-- Transformer registry -->
+ <component name="databinding.transformerRegistry" initLevel="90">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.impl.TransformerRegistryImpl" />
+ </component>
+
+ <component name="dataType.loader">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.impl.DataTypeLoader" />
+ </component>
+
+ <!-- Simple databindings -->
+ <component name="databinding.dom">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.impl.SimpleDataBinding" />
+ <property name="className">org.w3c.dom.Node</property>
+ </component>
+
+ <!-- Transformers -->
+
+ <component name="transformer.Input2InputTransformer">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.impl.Input2InputTransformer" />
+ </component>
+
+ <component name="transformer.Output2OutputTransformer">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.impl.Output2OutputTransformer" />
+ </component>
+
+ <component name="transformer.InputSource2Node">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.InputSource2Node" />
+ </component>
+
+ <component name="transformer.InputSource2SAX">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.InputSource2SAX" />
+ </component>
+
+ <component name="transformer.InputStream2Node">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.InputStream2Node" />
+ </component>
+
+ <component name="transformer.InputStream2SAX">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.InputStream2SAX" />
+ </component>
+
+ <component name="transformer.Node2Object">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.Node2Object" />
+ </component>
+
+ <component name="transformer.Node2OutputStream">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.Node2OutputStream" />
+ </component>
+
+ <component name="transformer.Node2String">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.Node2String" />
+ </component>
+
+ <component name="transformer.Node2Writer">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.Node2Writer" />
+ </component>
+
+ <component name="transformer.Node2XMLStreamReader">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.Node2XMLStreamReader" />
+ </component>
+
+ <component name="transformer.Object2Node">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.Object2Node" />
+ </component>
+
+ <component name="transformer.Reader2Node">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.Reader2Node" />
+ </component>
+
+ <component name="transformer.Reader2SAX">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.Reader2SAX" />
+ </component>
+
+ <component name="transformer.SAX2DOMPipe">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.SAX2DOMPipe" />
+ </component>
+
+ <component name="transformer.Source2ResultTransformer">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.Source2ResultTransformer" />
+ </component>
+
+ <component name="transformer.StreamDataPipe">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.StreamDataPipe" />
+ </component>
+
+ <component name="transformer.String2Node">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.String2Node" />
+ </component>
+
+ <component name="transformer.String2SAX">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.String2SAX" />
+ </component>
+
+ <component name="transformer.String2XMLStreamReader">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.String2XMLStreamReader" />
+ </component>
+
+ <component name="transformer.Writer2ReaderDataPipe">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.Writer2ReaderDataPipe" />
+ </component>
+
+ <component name="transformer.XMLStreamReader2Node">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.XMLStreamReader2Node" />
+ </component>
+
+ <component name="transformer.XMLStreamReader2SAX">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.XMLStreamReader2SAX" />
+ </component>
+
+ <component name="transformer.XMLStreamReader2String">
+ <system:implementation.system class="org.apache.tuscany.core.databinding.xml.XMLStreamReader2String" />
+ </component>
+</composite>
\ No newline at end of file diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/implementation.scdl b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/implementation.scdl new file mode 100644 index 0000000000..7efa6997f2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/implementation.scdl @@ -0,0 +1,60 @@ +<?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. +--> +<!-- + Default system configuration for the launcher environment. + + $Rev$ $Date$ +--> +<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" + xmlns:system="http://incubator.apache.org/tuscany/xmlns/system/1.0-incubator-M2" + name="org.apache.tuscany.core.Implementation"> + + <!-- Foundation implementation processors --> + <component name="implementation.ImplementationProcessorService"> + <system:implementation.system class="org.apache.tuscany.core.implementation.processor.ImplementationProcessorServiceImpl"/> + </component> + <component name="implementation.Constructor"> + <system:implementation.system class="org.apache.tuscany.core.implementation.processor.ConstructorProcessor"/> + </component> + <component name="implementation.Destroy"> + <system:implementation.system class="org.apache.tuscany.core.implementation.processor.DestroyProcessor"/> + </component> + <component name="implementation.Init"> + <system:implementation.system class="org.apache.tuscany.core.implementation.processor.InitProcessor"/> + </component> + <component name="implementation.Scope"> + <system:implementation.system class="org.apache.tuscany.core.implementation.processor.ScopeProcessor"/> + </component> + <component name="implementation.Property"> + <system:implementation.system class="org.apache.tuscany.core.implementation.processor.PropertyProcessor"/> + </component> + <component name="implementation.Reference"> + <system:implementation.system class="org.apache.tuscany.core.implementation.processor.ReferenceProcessor"/> + </component> + <component name="implementation.Service"> + <system:implementation.system class="org.apache.tuscany.core.implementation.processor.ServiceProcessor"/> + </component> + <component name="implementation.HeuristicPojo"> + <system:implementation.system class="org.apache.tuscany.core.implementation.processor.HeuristicPojoProcessor"/> + </component> + <component name="implementation.Monitor"> + <system:implementation.system class="org.apache.tuscany.core.implementation.processor.MonitorProcessor"/> + </component> +</composite> diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/interfaceJava.scdl b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/interfaceJava.scdl new file mode 100644 index 0000000000..6f889cabb9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/interfaceJava.scdl @@ -0,0 +1,35 @@ +<?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. +--> +<!-- + Configuration for Java IDL support. + + $Rev$ $Date$ +--> +<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" + xmlns:system="http://incubator.apache.org/tuscany/xmlns/system/1.0-incubator-M2" + name="org.apache.tuscany.core.InterfaceJava"> + + <component name="interfaceJava.interfaceProcessorRegistry"> + <system:implementation.system class="org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl"/> + </component> + <component name="interfaceJava.loader"> + <system:implementation.system class="org.apache.tuscany.core.idl.java.InterfaceJavaLoader"/> + </component> +</composite> diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/javaImplementation.scdl b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/javaImplementation.scdl new file mode 100644 index 0000000000..29ef9200f7 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/javaImplementation.scdl @@ -0,0 +1,39 @@ +<?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. +--> +<!-- + Default system configuration for the launcher environment. + + $Rev$ $Date$ +--> +<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" + xmlns:system="http://incubator.apache.org/tuscany/xmlns/system/1.0-incubator-M2" + name="org.apache.tuscany.core.JavaImplementation"> + + <!-- Java implementation type --> + <component name="java.implementationLoader"> + <system:implementation.system class="org.apache.tuscany.core.implementation.java.JavaImplementationLoader"/> + </component> + <component name="java.componentTypeLoader"> + <system:implementation.system class="org.apache.tuscany.core.implementation.java.JavaComponentTypeLoader"/> + </component> + <component name="java.componentBuilder"> + <system:implementation.system class="org.apache.tuscany.core.implementation.java.JavaComponentBuilder"/> + </component> +</composite> diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/loader.scdl b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/loader.scdl new file mode 100644 index 0000000000..0b6917e181 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/loader.scdl @@ -0,0 +1,49 @@ +<?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. +--> +<!-- + Default loader configuration for the launcher environment. + + $Rev$ $Date$ +--> +<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" + xmlns:system="http://incubator.apache.org/tuscany/xmlns/system/1.0-incubator-M2" + name="org.apache.tuscany.core.Loader"> + + <!-- Foundation element loader implementations --> + <component name="elementLoader.component"> + <system:implementation.system class="org.apache.tuscany.core.loader.ComponentLoader"/> + </component> + <component name="elementLoader.componentType"> + <system:implementation.system class="org.apache.tuscany.core.loader.ComponentTypeElementLoader"/> + </component> + <component name="elementLoader.include"> + <system:implementation.system class="org.apache.tuscany.core.loader.IncludeLoader"/> + </component> + <component name="elementLoader.property"> + <system:implementation.system class="org.apache.tuscany.core.loader.PropertyLoader"/> + </component> + <component name="elementLoader.reference"> + <system:implementation.system class="org.apache.tuscany.core.loader.ReferenceLoader"/> + </component> + <component name="elementLoader.service"> + <system:implementation.system class="org.apache.tuscany.core.loader.ServiceLoader"/> + </component> + +</composite> diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/systemImplementation.scdl b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/systemImplementation.scdl new file mode 100644 index 0000000000..a624ac94c2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/main/resources/org/apache/tuscany/core/systemImplementation.scdl @@ -0,0 +1,50 @@ +<?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. +--> +<!-- + Default system configuration for the launcher environment. + + $Rev$ $Date$ +--> +<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" + xmlns:system="http://incubator.apache.org/tuscany/xmlns/system/1.0-incubator-M2" + name="org.apache.tuscany.core.SystemImplementation"> + + <!-- System implementation type --> + <component name="system.bindingLoader"> + <system:implementation.system class="org.apache.tuscany.core.implementation.system.loader.SystemBindingLoader"/> + </component> + + <component name="system.componentTypeLoader"> + <system:implementation.system class="org.apache.tuscany.core.implementation.system.loader.SystemComponentTypeLoader"/> + </component> + + <component name="system.compositeComponentTypeLoader"> + <system:implementation.system class="org.apache.tuscany.core.implementation.system.loader.SystemCompositeComponentTypeLoader"/> + </component> + <component name="system.implementationLoader"> + <system:implementation.system class="org.apache.tuscany.core.implementation.system.loader.SystemImplementationLoader"/> + </component> + <component name="system.componentBuilder"> + <system:implementation.system class="org.apache.tuscany.core.implementation.system.builder.SystemComponentBuilder"/> + </component> + <component name="system.compositeBuilder"> + <system:implementation.system class="org.apache.tuscany.core.implementation.system.builder.SystemCompositeBuilder"/> + </component> +</composite> diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/bootstrap/BootstrapperTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/bootstrap/BootstrapperTestCase.java new file mode 100644 index 0000000000..deb4ae3f62 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/bootstrap/BootstrapperTestCase.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.bootstrap; + +import junit.framework.TestCase; + +import org.apache.tuscany.core.deployer.DeployerImpl; +import org.apache.tuscany.core.monitor.NullMonitorFactory; + +/** + * Verifies the default bootstrapper can be instantiated + * + * @version $Rev$ $Date$ + */ +public class BootstrapperTestCase extends TestCase { + private Bootstrapper bootstrapper; + + public void testDeployerBootstrap() { + DeployerImpl deployer = (DeployerImpl) bootstrapper.createDeployer(); + } + + protected void setUp() throws Exception { + super.setUp(); + bootstrapper = new DefaultBootstrapper(new NullMonitorFactory(), null); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/builder/BuilderRegistryTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/builder/BuilderRegistryTestCase.java new file mode 100644 index 0000000000..5a33950cc4 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/builder/BuilderRegistryTestCase.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import org.apache.tuscany.spi.builder.BuilderConfigException; +import org.apache.tuscany.spi.builder.ComponentBuilder; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.CompositeImplementation; +import org.apache.tuscany.spi.wire.WireService; + +import junit.framework.TestCase; +import org.apache.tuscany.core.deployer.RootDeploymentContext; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class BuilderRegistryTestCase extends TestCase { + private DeploymentContext deploymentContext; + private BuilderRegistryImpl registry; + + public void testRegistrationWithoutGenerics() { + RawBuilder builder = new RawBuilder(); + registry.register(CompositeImplementation.class, builder); + CompositeImplementation implementation = new CompositeImplementation(); + ComponentDefinition<CompositeImplementation> componentDefinition = + new ComponentDefinition<CompositeImplementation>(implementation); + componentDefinition.getImplementation().setComponentType(new CompositeComponentType()); + registry.build(null, componentDefinition, deploymentContext); + } + + protected void setUp() throws Exception { + super.setUp(); + registry = new BuilderRegistryImpl(); + WireService service = EasyMock.createNiceMock(WireService.class); + registry.setWireService(service); + deploymentContext = new RootDeploymentContext(null, null, null, null); + } + + public static class GenerifiedBuilder implements ComponentBuilder<CompositeImplementation> { + public Component build(CompositeComponent parent, + ComponentDefinition<CompositeImplementation> componentDefinition, + DeploymentContext deploymentContext) { + return null; + } + } + + public static class RawBuilder implements ComponentBuilder<CompositeImplementation> { + public Component build(CompositeComponent parent, + ComponentDefinition componentDefinition, + DeploymentContext deploymentContext) throws BuilderConfigException { + return null; + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/builder/ConnectorImplTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/builder/ConnectorImplTestCase.java new file mode 100644 index 0000000000..967c17ece0 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/builder/ConnectorImplTestCase.java @@ -0,0 +1,416 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.spi.QualifiedName; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.Reference; +import org.apache.tuscany.spi.component.Service; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.TargetInvoker; + +import junit.framework.TestCase; +import org.apache.tuscany.core.wire.SynchronousBridgingInterceptor; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class ConnectorImplTestCase extends TestCase { + + private ConnectorImpl connector; + private ServiceContract contract; + private Operation<Type> operation; + private Interceptor headInterceptor; + private Interceptor tailInterceptor; + + public void testConnectReferenceWires() { + + // create the inbound wire and chain + InboundInvocationChain inboundChain = EasyMock.createMock(InboundInvocationChain.class); + EasyMock.expect(inboundChain.getOperation()).andReturn(operation).atLeastOnce(); + inboundChain.addInterceptor(EasyMock.isA(SynchronousBridgingInterceptor.class)); + inboundChain.setTargetInvoker(null); + inboundChain.prepare(); + EasyMock.replay(inboundChain); + Map<Operation<?>, InboundInvocationChain> inboundChains = new HashMap<Operation<?>, InboundInvocationChain>(); + inboundChains.put(operation, inboundChain); + InboundWire inboundWire = EasyMock.createMock(InboundWire.class); + EasyMock.expect(inboundWire.getServiceContract()).andReturn(contract).anyTimes(); + EasyMock.expect(inboundWire.getInvocationChains()).andReturn(inboundChains).atLeastOnce(); + EasyMock.replay(inboundWire); + + OutboundInvocationChain outboundChain = EasyMock.createMock(OutboundInvocationChain.class); + EasyMock.expect(outboundChain.getHeadInterceptor()).andReturn(headInterceptor); + EasyMock.replay(outboundChain); + Map<Operation<?>, OutboundInvocationChain> outboundChains = + new HashMap<Operation<?>, OutboundInvocationChain>(); + outboundChains.put(operation, outboundChain); + OutboundWire outboundWire = EasyMock.createMock(OutboundWire.class); + EasyMock.expect(outboundWire.getServiceContract()).andReturn(contract).anyTimes(); + EasyMock.expect(outboundWire.getTargetName()).andReturn(new QualifiedName("target/FooService")).anyTimes(); + EasyMock.expect(outboundWire.getInvocationChains()).andReturn(outboundChains).anyTimes(); + EasyMock.replay(outboundWire); + + Reference reference = EasyMock.createMock(Reference.class); + EasyMock.expect(reference.getParent()).andReturn(null); + EasyMock.expect(reference.createTargetInvoker(contract, operation)).andReturn(null); + EasyMock.expect(reference.getInboundWire()).andReturn(inboundWire); + EasyMock.expect(reference.getOutboundWire()).andReturn(outboundWire); + EasyMock.replay(reference); + + connector.connect(reference); + + EasyMock.verify(reference); + EasyMock.verify(inboundWire); + EasyMock.verify(outboundWire); + EasyMock.verify(inboundChain); + EasyMock.verify(outboundChain); + } + + public void testConnectServiceWires() { + // create the inbound wire and chain for the target + InboundInvocationChain targetChain = EasyMock.createMock(InboundInvocationChain.class); + EasyMock.expect(targetChain.getOperation()).andReturn(operation).atLeastOnce(); + EasyMock.expect(targetChain.getHeadInterceptor()).andReturn(headInterceptor); + targetChain.prepare(); + EasyMock.replay(targetChain); + Map<Operation<?>, InboundInvocationChain> targetChains = new HashMap<Operation<?>, InboundInvocationChain>(); + targetChains.put(operation, targetChain); + InboundWire targetWire = EasyMock.createMock(InboundWire.class); + EasyMock.expect(targetWire.getServiceContract()).andReturn(contract).anyTimes(); + EasyMock.expect(targetWire.getInvocationChains()).andReturn(targetChains); + targetWire.getSourceCallbackInvocationChains("source"); + EasyMock.expectLastCall().andReturn(Collections.emptyMap()); + + // create the target + AtomicComponent target = EasyMock.createMock(AtomicComponent.class); + EasyMock.expect(target.getScope()).andReturn(Scope.MODULE); + EasyMock.expect(target.isSystem()).andReturn(false).atLeastOnce(); + target.getInboundWire(EasyMock.eq("FooService")); + EasyMock.expectLastCall().andReturn(targetWire).atLeastOnce(); + target.createTargetInvoker(EasyMock.eq("FooService"), EasyMock.eq(operation)); + EasyMock.expectLastCall().andReturn(null); + EasyMock.replay(target); + + EasyMock.expect(targetWire.getContainer()).andReturn(target); + EasyMock.replay(targetWire); + + // create the parent composite + CompositeComponent parent = EasyMock.createMock(CompositeComponent.class); + EasyMock.expect(parent.getChild("target")).andReturn(target); + EasyMock.replay(parent); + + // create the inbound wire and chain for the source service + InboundInvocationChain inboundChain = EasyMock.createMock(InboundInvocationChain.class); + EasyMock.expect(inboundChain.getOperation()).andReturn(operation).atLeastOnce(); + inboundChain.addInterceptor(EasyMock.isA(SynchronousBridgingInterceptor.class)); + inboundChain.setTargetInvoker(null); + EasyMock.replay(inboundChain); + Map<Operation<?>, InboundInvocationChain> inboundChains = new HashMap<Operation<?>, InboundInvocationChain>(); + inboundChains.put(operation, inboundChain); + InboundWire inboundWire = EasyMock.createMock(InboundWire.class); + EasyMock.expect(inboundWire.getServiceContract()).andReturn(contract).anyTimes(); + EasyMock.expect(inboundWire.getInvocationChains()).andReturn(inboundChains).atLeastOnce(); + EasyMock.replay(inboundWire); + + // create the outbound wire and chain for the source service + OutboundInvocationChain outboundChain = EasyMock.createMock(OutboundInvocationChain.class); + EasyMock.expect(outboundChain.getHeadInterceptor()).andReturn(headInterceptor); + outboundChain.setTargetInterceptor(EasyMock.isA(SynchronousBridgingInterceptor.class)); + outboundChain.prepare(); + outboundChain.setTargetInvoker(null); + EasyMock.expect(outboundChain.getOperation()).andReturn(operation); + EasyMock.replay(outboundChain); + Map<Operation<?>, OutboundInvocationChain> outboundChains = + new HashMap<Operation<?>, OutboundInvocationChain>(); + outboundChains.put(operation, outboundChain); + OutboundWire outboundWire = EasyMock.createMock(OutboundWire.class); + outboundWire.getTargetCallbackInvocationChains(); + EasyMock.expectLastCall().andReturn(Collections.emptyMap()); + EasyMock.expect(outboundWire.getServiceContract()).andReturn(contract).anyTimes(); + EasyMock.expect(outboundWire.getTargetName()).andReturn(new QualifiedName("target/FooService")).anyTimes(); + EasyMock.expect(outboundWire.getInvocationChains()).andReturn(outboundChains).anyTimes(); + + // create the service + Service service = EasyMock.createMock(Service.class); + EasyMock.expect(service.getName()).andReturn("source"); + EasyMock.expect(service.isSystem()).andReturn(false).atLeastOnce(); + EasyMock.expect(service.getParent()).andReturn(parent).atLeastOnce(); + EasyMock.expect(service.getInboundWire()).andReturn(inboundWire).atLeastOnce(); + EasyMock.expect(service.getScope()).andReturn(Scope.COMPOSITE); + EasyMock.expect(service.getOutboundWire()).andReturn(outboundWire); + EasyMock.replay(service); + + EasyMock.expect(outboundWire.getContainer()).andReturn(service); + EasyMock.replay(outboundWire); + + connector.connect(service); + + EasyMock.verify(service); + EasyMock.verify(inboundWire); + EasyMock.verify(outboundWire); + EasyMock.verify(inboundChain); + EasyMock.verify(outboundChain); + } + + /** + * Verifies connecting a wire from an atomic component to a target atomic component with one synchronous operation + */ + public void testConnectAtomicComponentToAtomicComponentSyncWire() throws Exception { + + // create the inbound wire and chain + InboundInvocationChain inboundChain = EasyMock.createMock(InboundInvocationChain.class); + EasyMock.expect(inboundChain.getOperation()).andReturn(operation).atLeastOnce(); + EasyMock.expect(inboundChain.getHeadInterceptor()).andReturn(headInterceptor); + EasyMock.replay(inboundChain); + Map<Operation<?>, InboundInvocationChain> inboundChains = new HashMap<Operation<?>, InboundInvocationChain>(); + inboundChains.put(operation, inboundChain); + InboundWire targetWire = EasyMock.createMock(InboundWire.class); + EasyMock.expect(targetWire.getServiceContract()).andReturn(contract).anyTimes(); + EasyMock.expect(targetWire.getInvocationChains()).andReturn(inboundChains); + targetWire.getSourceCallbackInvocationChains("source"); + EasyMock.expectLastCall().andReturn(Collections.emptyMap()); + + // create the target + AtomicComponent target = EasyMock.createMock(AtomicComponent.class); + EasyMock.expect(target.getScope()).andReturn(Scope.MODULE); + target.getInboundWire(EasyMock.eq("FooService")); + EasyMock.expectLastCall().andReturn(targetWire); + target.createTargetInvoker(EasyMock.eq("FooService"), EasyMock.eq(operation)); + EasyMock.expectLastCall().andReturn(null); + EasyMock.replay(target); + + EasyMock.expect(targetWire.getContainer()).andReturn(target); + EasyMock.replay(targetWire); + + // create the parent composite + CompositeComponent parent = EasyMock.createMock(CompositeComponent.class); + EasyMock.expect(parent.getChild("target")).andReturn(target); + EasyMock.replay(parent); + + // create the outbound wire and chain from the source component + OutboundInvocationChain outboundChain = EasyMock.createMock(OutboundInvocationChain.class); + EasyMock.expect(outboundChain.getOperation()).andReturn(operation).atLeastOnce(); + outboundChain.setTargetInterceptor(EasyMock.isA(SynchronousBridgingInterceptor.class)); + outboundChain.setTargetInvoker(null); + outboundChain.prepare(); + EasyMock.replay(outboundChain); + Map<Operation<?>, OutboundInvocationChain> outboundChains = + new HashMap<Operation<?>, OutboundInvocationChain>(); + outboundChains.put(operation, outboundChain); + OutboundWire outboundWire = EasyMock.createMock(OutboundWire.class); + EasyMock.expect(outboundWire.getServiceContract()).andReturn(contract).anyTimes(); + EasyMock.expect(outboundWire.getTargetName()).andReturn(new QualifiedName("target/FooService")).anyTimes(); + EasyMock.expect(outboundWire.getInvocationChains()).andReturn(outboundChains).anyTimes(); + outboundWire.getTargetCallbackInvocationChains(); + EasyMock.expectLastCall().andReturn(Collections.emptyMap()); + + Map<String, List<OutboundWire>> outboundWires = new HashMap<String, List<OutboundWire>>(); + List<OutboundWire> list = new ArrayList<OutboundWire>(); + list.add(outboundWire); + outboundWires.put("fooService", list); + + // create the source + AtomicComponent source = EasyMock.createMock(AtomicComponent.class); + EasyMock.expect(source.isSystem()).andReturn(false).atLeastOnce(); + EasyMock.expect(source.getScope()).andReturn(Scope.MODULE); + EasyMock.expect(source.getParent()).andReturn(parent).atLeastOnce(); + EasyMock.expect(source.getOutboundWires()).andReturn(outboundWires); + EasyMock.expect(source.getName()).andReturn("source"); + source.getInboundWires(); + EasyMock.expectLastCall().andReturn(Collections.emptyMap()); + EasyMock.replay(source); + + EasyMock.expect(outboundWire.getContainer()).andReturn(source); + EasyMock.replay(outboundWire); + + connector.connect(source); + EasyMock.verify(outboundWire); + EasyMock.verify(targetWire); + EasyMock.verify(outboundChain); + EasyMock.verify(inboundChain); + EasyMock.verify(source); + EasyMock.verify(target); + } + + public void testConnectInboundAtomicComponentWires() { + // create the inbound wire and chain + InboundInvocationChain chain = EasyMock.createMock(InboundInvocationChain.class); + EasyMock.expect(chain.getOperation()).andReturn(operation).atLeastOnce(); + chain.setTargetInvoker(null); + chain.prepare(); + EasyMock.replay(chain); + Map<Operation<?>, InboundInvocationChain> inboundChains = new HashMap<Operation<?>, InboundInvocationChain>(); + inboundChains.put(operation, chain); + InboundWire wire = EasyMock.createMock(InboundWire.class); + EasyMock.expect(wire.getServiceName()).andReturn("FooService"); + EasyMock.expect(wire.getServiceContract()).andReturn(contract).anyTimes(); + EasyMock.expect(wire.getInvocationChains()).andReturn(inboundChains); + EasyMock.replay(wire); + + Map<String, InboundWire> wires = new HashMap<String, InboundWire>(); + wires.put("FooService", wire); + + AtomicComponent source = EasyMock.createMock(AtomicComponent.class); + EasyMock.expect(source.getParent()).andReturn(null); + source.getOutboundWires(); + EasyMock.expectLastCall().andReturn(Collections.emptyMap()); + source.getInboundWires(); + EasyMock.expectLastCall().andReturn(wires); + source.createTargetInvoker(EasyMock.eq("FooService"), EasyMock.eq(operation)); + EasyMock.expectLastCall().andReturn(null); + EasyMock.replay(source); + + connector.connect(source); + + EasyMock.verify(source); + EasyMock.verify(wire); + EasyMock.verify(chain); + } + + public void testOutboundToInboundOptimization() { + InboundWire inboundWire = EasyMock.createMock(InboundWire.class); + EasyMock.expect(inboundWire.getContainer()).andReturn(null); + inboundWire.getInvocationChains(); + EasyMock.expectLastCall().andReturn(Collections.emptyMap()); + EasyMock.replay(inboundWire); + + OutboundWire outboundWire = EasyMock.createMock(OutboundWire.class); + outboundWire.getInvocationChains(); + EasyMock.expectLastCall().andReturn(Collections.emptyMap()); + outboundWire.setTargetWire(inboundWire); + EasyMock.expect(outboundWire.getContainer()).andReturn(null); + EasyMock.expect(outboundWire.getServiceContract()).andReturn(null); + EasyMock.replay(outboundWire); + + connector.connect(outboundWire, inboundWire, true); + EasyMock.verify(inboundWire); + EasyMock.verify(outboundWire); + } + + public void testOutboundToInboundChainConnect() { + + TargetInvoker invoker = EasyMock.createMock(TargetInvoker.class); + EasyMock.replay(invoker); + + InboundInvocationChain inboundChain = EasyMock.createMock(InboundInvocationChain.class); + EasyMock.expect(inboundChain.getHeadInterceptor()).andReturn(headInterceptor); + EasyMock.replay(inboundChain); + + OutboundInvocationChain outboundChain = EasyMock.createMock(OutboundInvocationChain.class); + outboundChain.prepare(); + outboundChain.setTargetInterceptor(EasyMock.isA(SynchronousBridgingInterceptor.class)); + outboundChain.setTargetInvoker(invoker); + EasyMock.replay(outboundChain); + connector.connect(outboundChain, inboundChain, invoker, false); + EasyMock.verify(outboundChain); + } + + public void testInboundToOutboundChainConnect() { + InboundInvocationChain inboundChain = EasyMock.createMock(InboundInvocationChain.class); + inboundChain.addInterceptor(EasyMock.isA(SynchronousBridgingInterceptor.class)); + EasyMock.replay(inboundChain); + + OutboundInvocationChain outboundChain = EasyMock.createMock(OutboundInvocationChain.class); + EasyMock.expect(outboundChain.getHeadInterceptor()).andReturn(headInterceptor); + outboundChain.prepare(); + outboundChain.setTargetInterceptor(headInterceptor); + EasyMock.replay(outboundChain); + connector.connect(inboundChain, outboundChain); + EasyMock.verify(inboundChain); + } + + public void testOutboundWireToInboundReferenceTarget() { + AtomicComponent component = EasyMock.createMock(AtomicComponent.class); + EasyMock.expect(component.getName()).andReturn("foo"); + EasyMock.replay(component); + // create the inbound wire and chain + InboundInvocationChain inboundChain = EasyMock.createMock(InboundInvocationChain.class); + EasyMock.expect(inboundChain.getOperation()).andReturn(operation).atLeastOnce(); + EasyMock.expect(inboundChain.getHeadInterceptor()).andReturn(headInterceptor); + EasyMock.replay(inboundChain); + Map<Operation<?>, InboundInvocationChain> inboundChains = new HashMap<Operation<?>, InboundInvocationChain>(); + inboundChains.put(operation, inboundChain); + InboundWire targetWire = EasyMock.createMock(InboundWire.class); + EasyMock.expect(targetWire.getServiceContract()).andReturn(contract).anyTimes(); + EasyMock.expect(targetWire.getInvocationChains()).andReturn(inboundChains); + targetWire.getSourceCallbackInvocationChains("foo"); + EasyMock.expectLastCall().andReturn(Collections.emptyMap()); + Reference target = EasyMock.createMock(Reference.class); + EasyMock.expect(target.createTargetInvoker(EasyMock.isA(ServiceContract.class), EasyMock.isA(Operation.class))) + .andReturn(null); + EasyMock.replay(target); + + EasyMock.expect(targetWire.getContainer()).andReturn(target); + EasyMock.replay(targetWire); + + // create the outbound wire and chain from the source component + OutboundInvocationChain outboundChain = EasyMock.createMock(OutboundInvocationChain.class); + EasyMock.expect(outboundChain.getOperation()).andReturn(operation).atLeastOnce(); + outboundChain.setTargetInterceptor(EasyMock.isA(SynchronousBridgingInterceptor.class)); + outboundChain.setTargetInvoker(null); + outboundChain.prepare(); + EasyMock.replay(outboundChain); + Map<Operation<?>, OutboundInvocationChain> outboundChains = + new HashMap<Operation<?>, OutboundInvocationChain>(); + outboundChains.put(operation, outboundChain); + OutboundWire sourceWire = EasyMock.createMock(OutboundWire.class); + EasyMock.expect(sourceWire.getContainer()).andReturn(component); + EasyMock.expect(sourceWire.getServiceContract()).andReturn(contract).anyTimes(); + EasyMock.expect(sourceWire.getTargetName()).andReturn(new QualifiedName("target/FooService")).anyTimes(); + EasyMock.expect(sourceWire.getInvocationChains()).andReturn(outboundChains).anyTimes(); + sourceWire.getTargetCallbackInvocationChains(); + EasyMock.expectLastCall().andReturn(Collections.emptyMap()); + EasyMock.replay(sourceWire); + + connector.connect(sourceWire, targetWire, false); + EasyMock.verify(inboundChain); + EasyMock.verify(targetWire); + EasyMock.verify(target); + } + + protected void setUp() throws Exception { + super.setUp(); + connector = new ConnectorImpl(); + contract = new JavaServiceContract(String.class); + operation = new Operation<Type>("bar", null, null, null); + headInterceptor = EasyMock.createMock(Interceptor.class); + EasyMock.replay(headInterceptor); + tailInterceptor = EasyMock.createMock(Interceptor.class); + EasyMock.replay(tailInterceptor); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/builder/ConnectorPostProcessTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/builder/ConnectorPostProcessTestCase.java new file mode 100644 index 0000000000..366a4a57b2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/builder/ConnectorPostProcessTestCase.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.builder.WirePostProcessorRegistry; +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.WireService; + +import junit.framework.TestCase; +import org.easymock.EasyMock; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createNiceMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * @version $Rev$ $Date$ + */ +public class ConnectorPostProcessTestCase extends TestCase { + + public void testInboundToOutboundPostProcessCalled() throws Exception { + OutboundWire owire = createNiceMock(OutboundWire.class); + replay(owire); + InboundWire iwire = createNiceMock(InboundWire.class); + Map<Operation<?>, InboundInvocationChain> chains = new HashMap<Operation<?>, InboundInvocationChain>(); + expect(iwire.getInvocationChains()).andReturn(chains); + replay(iwire); + WirePostProcessorRegistry registry = createMock(WirePostProcessorRegistry.class); + registry.process(EasyMock.eq(iwire), EasyMock.eq(owire)); + replay(registry); + WireService wireService = createMock(WireService.class); + wireService.checkCompatibility((ServiceContract<?>) EasyMock.anyObject(), + (ServiceContract<?>) EasyMock.anyObject(), EasyMock.eq(false)); + expectLastCall().anyTimes(); + replay(wireService); + ConnectorImpl connector = new ConnectorImpl(wireService, registry, null, null); + connector.connect(iwire, owire, false); + verify(registry); + } + + public void testOutboundToInboundPostProcessCalled() throws Exception { + Component source = createNiceMock(Component.class); + expect(source.getName()).andReturn("Component"); + replay(source); + + OutboundWire owire = createNiceMock(OutboundWire.class); + EasyMock.expect(owire.getContainer()).andReturn(source); + + Map<Operation<?>, OutboundInvocationChain> chains = new HashMap<Operation<?>, OutboundInvocationChain>(); + expect(owire.getInvocationChains()).andReturn(chains); + Map<Operation<?>, InboundInvocationChain> ichains = new HashMap<Operation<?>, InboundInvocationChain>(); + expect(owire.getTargetCallbackInvocationChains()).andReturn(ichains); + replay(owire); + InboundWire iwire = createNiceMock(InboundWire.class); + expect(iwire.getSourceCallbackInvocationChains("Component")).andReturn(chains); + replay(iwire); + WirePostProcessorRegistry registry = createMock(WirePostProcessorRegistry.class); + registry.process(EasyMock.eq(owire), EasyMock.eq(iwire)); + replay(registry); + WireService wireService = createMock(WireService.class); + wireService.checkCompatibility((ServiceContract<?>) EasyMock.anyObject(), + (ServiceContract<?>) EasyMock.anyObject(), EasyMock.eq(false)); + expectLastCall().anyTimes(); + replay(wireService); + ConnectorImpl connector = new ConnectorImpl(wireService, registry, null, null); + + connector.connect(owire, iwire, false); + verify(registry); + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/builder/InboundtoOutboundConnectTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/builder/InboundtoOutboundConnectTestCase.java new file mode 100644 index 0000000000..c12bca58ea --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/builder/InboundtoOutboundConnectTestCase.java @@ -0,0 +1,187 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.MessageImpl; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.TargetInvoker; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.mock.component.SimpleTarget; +import org.apache.tuscany.core.mock.wire.MockSyncInterceptor; +import org.apache.tuscany.core.wire.InboundInvocationChainImpl; +import org.apache.tuscany.core.wire.InvokerInterceptor; +import org.apache.tuscany.core.wire.OutboundInvocationChainImpl; +import org.easymock.EasyMock; +import static org.easymock.EasyMock.createNiceMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Verifies connection strategies between {@link org.apache.tuscany.spi.wire.OutboundInvocationChain}s and {@link + * org.apache.tuscany.spi.wire.InboundInvocationChain}s + * + * @version $$Rev$$ $$Date$$ + */ +public class InboundtoOutboundConnectTestCase extends TestCase { + private Operation operation; + + public void testNoInterceptorsNoHandlers() throws Exception { + ConnectorImpl connector = new ConnectorImpl(); + InboundInvocationChain inboundChain = setupInbound(null); + OutboundInvocationChain outboundChain = setupOutbound(null); + String[] val = new String[]{"foo"}; + TargetInvoker invoker = createNiceMock(TargetInvoker.class); + expect(invoker.invokeTarget(EasyMock.eq(val))).andReturn(val); + replay(invoker); + connector.connect(inboundChain, outboundChain); + inboundChain.setTargetInvoker(invoker); + inboundChain.prepare(); + inboundChain.getTargetInvoker().invokeTarget(val); + verify(invoker); + } + + + /** + * Verifies an invocation with a single source interceptor + */ + public void testSourceInterceptor() throws Exception { + ConnectorImpl connector = new ConnectorImpl(); + MockSyncInterceptor interceptor = new MockSyncInterceptor(); + List<Interceptor> interceptors = new ArrayList<Interceptor>(); + interceptors.add(interceptor); + + InboundInvocationChain inboundChain = setupInbound(interceptors); + OutboundInvocationChain outboundChain = setupOutbound(null); + Message msg = new MessageImpl(); + TargetInvoker invoker = createNiceMock(TargetInvoker.class); + expect(invoker.invoke(EasyMock.eq(msg))).andReturn(msg); + replay(invoker); + assertEquals(0, interceptor.getCount()); + connector.connect(inboundChain, outboundChain); + inboundChain.setTargetInvoker(invoker); + inboundChain.prepare(); + msg.setTargetInvoker(inboundChain.getTargetInvoker()); + assertEquals(msg, inboundChain.getHeadInterceptor().invoke(msg)); + assertEquals(1, interceptor.getCount()); + verify(invoker); + } + + /** + * Verifies an invocation with a single target interceptor + */ + public void testTargetInterceptor() throws Exception { + ConnectorImpl connector = new ConnectorImpl(); + MockSyncInterceptor interceptor = new MockSyncInterceptor(); + List<Interceptor> interceptors = new ArrayList<Interceptor>(); + interceptors.add(interceptor); + + InboundInvocationChain inboundChain = setupInbound(interceptors); + OutboundInvocationChain outboundChain = setupOutbound(null); + Message msg = new MessageImpl(); + TargetInvoker invoker = createNiceMock(TargetInvoker.class); + expect(invoker.invoke(EasyMock.eq(msg))).andReturn(msg); + replay(invoker); + assertEquals(0, interceptor.getCount()); + connector.connect(inboundChain, outboundChain); + inboundChain.setTargetInvoker(invoker); + inboundChain.prepare(); + msg.setTargetInvoker(inboundChain.getTargetInvoker()); + assertEquals(msg, inboundChain.getHeadInterceptor().invoke(msg)); + assertEquals(1, interceptor.getCount()); + verify(invoker); + } + + /** + * Verifies an invocation with a source and target interceptor + */ + public void testSourceTargetInterceptor() throws Exception { + ConnectorImpl connector = new ConnectorImpl(); + MockSyncInterceptor sourceInterceptor = new MockSyncInterceptor(); + List<Interceptor> sourceInterceptors = new ArrayList<Interceptor>(); + sourceInterceptors.add(sourceInterceptor); + MockSyncInterceptor targetInterceptor = new MockSyncInterceptor(); + List<Interceptor> targetInterceptors = new ArrayList<Interceptor>(); + targetInterceptors.add(targetInterceptor); + + OutboundInvocationChain outboundChain = setupOutbound(sourceInterceptors); + InboundInvocationChain inboundChain = setupInbound(targetInterceptors); + Message msg = new MessageImpl(); + TargetInvoker invoker = createNiceMock(TargetInvoker.class); + expect(invoker.invoke(EasyMock.eq(msg))).andReturn(msg); + replay(invoker); + assertEquals(0, sourceInterceptor.getCount()); + assertEquals(0, targetInterceptor.getCount()); + connector.connect(inboundChain, outboundChain); + inboundChain.setTargetInvoker(invoker); + inboundChain.prepare(); + msg.setTargetInvoker(inboundChain.getTargetInvoker()); + assertEquals(msg, inboundChain.getHeadInterceptor().invoke(msg)); + assertEquals(1, sourceInterceptor.getCount()); + assertEquals(1, targetInterceptor.getCount()); + verify(invoker); + } + + public InboundInvocationChain setupInbound(List<Interceptor> interceptors) { + + InboundInvocationChainImpl chain = new InboundInvocationChainImpl(operation); + if (interceptors != null) { + for (Interceptor interceptor : interceptors) { + chain.addInterceptor(interceptor); + } + } + return chain; + } + + public OutboundInvocationChain setupOutbound(List<Interceptor> interceptors) { + + OutboundInvocationChainImpl chain = new OutboundInvocationChainImpl(operation); + if (interceptors != null) { + for (Interceptor interceptor : interceptors) { + chain.addInterceptor(interceptor); + } + } + chain.addInterceptor(new InvokerInterceptor()); // add tail interceptor + return chain; + } + + protected void setUp() throws Exception { + super.setUp(); + JavaInterfaceProcessorRegistry registry = new JavaInterfaceProcessorRegistryImpl(); + ServiceContract<?> contract; + try { + contract = registry.introspect(SimpleTarget.class); + } catch (InvalidServiceContractException e) { + throw new AssertionError(); + } + operation = contract.getOperations().get("echo"); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/builder/OutboundToInboundConnectTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/builder/OutboundToInboundConnectTestCase.java new file mode 100644 index 0000000000..009eba0fbd --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/builder/OutboundToInboundConnectTestCase.java @@ -0,0 +1,183 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.MessageImpl; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.TargetInvoker; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.mock.component.SimpleTarget; +import org.apache.tuscany.core.mock.wire.MockSyncInterceptor; +import org.apache.tuscany.core.wire.InboundInvocationChainImpl; +import org.apache.tuscany.core.wire.InvokerInterceptor; +import org.apache.tuscany.core.wire.OutboundInvocationChainImpl; +import org.easymock.EasyMock; +import static org.easymock.EasyMock.createNiceMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Verifies connection strategies between {@link org.apache.tuscany.spi.wire.OutboundInvocationChain}s and {@link + * org.apache.tuscany.spi.wire.InboundInvocationChain}s + * + * @version $$Rev$$ $$Date$$ + */ +public class OutboundToInboundConnectTestCase extends TestCase { + + public void testNoInterceptorsNoHandlers() throws Exception { + ConnectorImpl connector = new ConnectorImpl(); + InboundInvocationChain inboundChain = setupTarget(null); + OutboundInvocationChain outboundChain = setupSource(null); + String[] val = new String[]{"foo"}; + TargetInvoker invoker = createNiceMock(TargetInvoker.class); + expect(invoker.invokeTarget(EasyMock.eq(val))).andReturn(val); + replay(invoker); + connector.connect(outboundChain, inboundChain, invoker, false); + inboundChain.prepare(); + assertEquals(val, outboundChain.getTargetInvoker().invokeTarget(val)); + verify(invoker); + } + + + /** + * Verifies an invocation with a single source interceptor + */ + public void testSourceInterceptor() throws Exception { + ConnectorImpl connector = new ConnectorImpl(); + MockSyncInterceptor interceptor = new MockSyncInterceptor(); + List<Interceptor> interceptors = new ArrayList<Interceptor>(); + interceptors.add(interceptor); + OutboundInvocationChain outboundChain = setupSource(interceptors); + InboundInvocationChain inboundChain = setupTarget(null); + Message msg = new MessageImpl(); + TargetInvoker invoker = createNiceMock(TargetInvoker.class); + expect(invoker.invoke(EasyMock.eq(msg))).andReturn(msg); + replay(invoker); + assertEquals(0, interceptor.getCount()); + connector.connect(outboundChain, inboundChain, invoker, false); + inboundChain.prepare(); + msg.setTargetInvoker(outboundChain.getTargetInvoker()); + assertEquals(msg, outboundChain.getHeadInterceptor().invoke(msg)); + assertEquals(1, interceptor.getCount()); + verify(invoker); + } + + /** + * Verifies an invocation with a single target interceptor + */ + public void testTargetInterceptor() throws Exception { + ConnectorImpl connector = new ConnectorImpl(); + MockSyncInterceptor interceptor = new MockSyncInterceptor(); + List<Interceptor> interceptors = new ArrayList<Interceptor>(); + interceptors.add(interceptor); + OutboundInvocationChain outboundChain = setupSource(null); + InboundInvocationChain inboundChain = setupTarget(interceptors); + Message msg = new MessageImpl(); + TargetInvoker invoker = createNiceMock(TargetInvoker.class); + expect(invoker.invoke(EasyMock.eq(msg))).andReturn(msg); + replay(invoker); + assertEquals(0, interceptor.getCount()); + connector.connect(outboundChain, inboundChain, invoker, false); + inboundChain.prepare(); + msg.setTargetInvoker(outboundChain.getTargetInvoker()); + assertEquals(msg, outboundChain.getHeadInterceptor().invoke(msg)); + assertEquals(1, interceptor.getCount()); + verify(invoker); + } + + /** + * Verifies an invocation with a source and target interceptor + */ + public void testSourceTargetInterceptor() throws Exception { + ConnectorImpl connector = new ConnectorImpl(); + MockSyncInterceptor sourceInterceptor = new MockSyncInterceptor(); + List<Interceptor> sourceInterceptors = new ArrayList<Interceptor>(); + sourceInterceptors.add(sourceInterceptor); + MockSyncInterceptor targetInterceptor = new MockSyncInterceptor(); + List<Interceptor> targetInterceptors = new ArrayList<Interceptor>(); + targetInterceptors.add(targetInterceptor); + OutboundInvocationChain outboundChain = setupSource(sourceInterceptors); + InboundInvocationChain inboundChain = setupTarget(targetInterceptors); + Message msg = new MessageImpl(); + TargetInvoker invoker = createNiceMock(TargetInvoker.class); + expect(invoker.invoke(EasyMock.eq(msg))).andReturn(msg); + replay(invoker); + assertEquals(0, sourceInterceptor.getCount()); + assertEquals(0, targetInterceptor.getCount()); + connector.connect(outboundChain, inboundChain, invoker, false); + inboundChain.prepare(); + msg.setTargetInvoker(outboundChain.getTargetInvoker()); + assertEquals(msg, outboundChain.getHeadInterceptor().invoke(msg)); + assertEquals(1, sourceInterceptor.getCount()); + assertEquals(1, targetInterceptor.getCount()); + verify(invoker); + } + + + public InboundInvocationChain setupTarget(List<Interceptor> interceptors) { + JavaInterfaceProcessorRegistry registry = new JavaInterfaceProcessorRegistryImpl(); + ServiceContract<?> contract; + try { + contract = registry.introspect(SimpleTarget.class); + } catch (InvalidServiceContractException e) { + throw new AssertionError(); + } + Operation operation = contract.getOperations().get("echo"); + InboundInvocationChainImpl chain = new InboundInvocationChainImpl(operation); + if (interceptors != null) { + for (Interceptor interceptor : interceptors) { + chain.addInterceptor(interceptor); + } + } + chain.addInterceptor(new InvokerInterceptor()); // add tail interceptor + return chain; + } + + public OutboundInvocationChain setupSource(List<Interceptor> interceptors) { + JavaInterfaceProcessorRegistry registry = new JavaInterfaceProcessorRegistryImpl(); + ServiceContract<?> contract; + try { + contract = registry.introspect(SimpleTarget.class); + } catch (InvalidServiceContractException e) { + throw new AssertionError(); + } + Operation operation = contract.getOperations().get("echo"); + OutboundInvocationChainImpl chain = new OutboundInvocationChainImpl(operation); + if (interceptors != null) { + for (Interceptor interceptor : interceptors) { + chain.addInterceptor(interceptor); + } + } + return chain; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/builder/WirePostProcessorRegistryImplTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/builder/WirePostProcessorRegistryImplTestCase.java new file mode 100644 index 0000000000..3e0e5c7bce --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/builder/WirePostProcessorRegistryImplTestCase.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.builder; + +import org.apache.tuscany.spi.builder.WirePostProcessor; +import org.apache.tuscany.spi.builder.WirePostProcessorRegistry; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundWire; + +import junit.framework.TestCase; +import org.easymock.EasyMock; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.verify; + +/** + * @version $Rev$ $Date$ + */ +public class WirePostProcessorRegistryImplTestCase extends TestCase { + + public void testRegisterUnregister() throws Exception { + WirePostProcessorRegistry registry = new WirePostProcessorRegistryImpl(); + OutboundWire owire = EasyMock.createMock(OutboundWire.class); + InboundWire iwire = EasyMock.createMock(InboundWire.class); + WirePostProcessor processor = createMock(WirePostProcessor.class); + processor.process(EasyMock.eq(owire), EasyMock.eq(iwire)); + EasyMock.replay(processor); + registry.register(processor); + registry.process(owire, iwire); + registry.unregister(processor); + registry.process(owire, iwire); + verify(processor); + } + + public void testProcessInboundToOutbound() throws Exception { + WirePostProcessorRegistry registry = new WirePostProcessorRegistryImpl(); + OutboundWire owire = EasyMock.createMock(OutboundWire.class); + InboundWire iwire = EasyMock.createMock(InboundWire.class); + WirePostProcessor processor = createMock(WirePostProcessor.class); + processor.process(EasyMock.eq(iwire), EasyMock.eq(owire)); + EasyMock.replay(processor); + registry.register(processor); + registry.process(iwire, owire); + verify(processor); + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/event/EventTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/event/EventTestCase.java new file mode 100644 index 0000000000..79b9757c2c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/event/EventTestCase.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.core.component.event; + +import org.apache.tuscany.spi.component.CompositeComponent; + +import junit.framework.TestCase; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class EventTestCase extends TestCase { + + private CompositeComponent component; + + public void testCompositeStart() { + CompositeStart event = new CompositeStart(this, component); + assertEquals(component, event.getComposite()); + } + + public void testCompositeStop() { + CompositeStop event = new CompositeStop(this, component); + assertEquals(component, event.getComposite()); + } + + public void testHttpSessionStart() { + Object id = new Object(); + HttpSessionEvent event = new HttpSessionStart(this, id); + assertEquals(this, event.getSource()); + assertEquals(id, event.getId()); + } + + public void testHttpSessionEnd() { + Object id = new Object(); + HttpSessionEvent event = new HttpSessionEnd(this, id); + assertEquals(this, event.getSource()); + assertEquals(id, event.getId()); + } + + public void testRequestStart() { + RequestStart event = new RequestStart(this); + assertEquals(this, event.getSource()); + } + + public void testReequestEnd() { + RequestEnd event = new RequestEnd(this); + assertEquals(this, event.getSource()); + } + + + protected void setUp() throws Exception { + super.setUp(); + component = EasyMock.createNiceMock(CompositeComponent.class); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/AbstractScopeContainerTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/AbstractScopeContainerTestCase.java new file mode 100644 index 0000000000..a99dbf072a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/AbstractScopeContainerTestCase.java @@ -0,0 +1,141 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.event.Event; +import org.apache.tuscany.spi.event.EventFilter; +import org.apache.tuscany.spi.event.RuntimeEventListener; +import org.apache.tuscany.spi.event.TrueFilter; +import org.apache.tuscany.spi.model.Scope; + +import junit.framework.TestCase; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class AbstractScopeContainerTestCase extends TestCase { + + public void testSetWorkContext() { + TestContainer container = new TestContainer("foo"); + WorkContext ctx = new WorkContextImpl(); + container.setWorkContext(ctx); + assertEquals(ctx, container.getWorkContext()); + + } + + public void testFireListener() { + TestContainer container = new TestContainer("foo"); + RuntimeEventListener listener = EasyMock.createMock(RuntimeEventListener.class); + Event event = new TestEvent(); + listener.onEvent(EasyMock.eq(event)); + EasyMock.replay(listener); + container.addListener(listener); + container.publish(event); + EasyMock.verify(listener); + } + + public void testRemoveListener() { + TestContainer container = new TestContainer("foo"); + RuntimeEventListener listener = EasyMock.createMock(RuntimeEventListener.class); + EasyMock.replay(listener); + Event event = new TestEvent(); + container.addListener(listener); + container.removeListener(listener); + container.publish(event); + EasyMock.verify(listener); + } + + public void testFalseFilterListener() { + TestContainer container = new TestContainer("foo"); + RuntimeEventListener listener = EasyMock.createMock(RuntimeEventListener.class); + Event event = new TestEvent(); + EasyMock.replay(listener); + container.addListener(new FalseFilter(), listener); + container.publish(event); + EasyMock.verify(listener); + } + + public void testTrueFilterListener() { + TestContainer container = new TestContainer("foo"); + RuntimeEventListener listener = EasyMock.createMock(RuntimeEventListener.class); + Event event = new TestEvent(); + listener.onEvent(EasyMock.eq(event)); + EasyMock.replay(listener); + container.addListener(new TrueFilter(), listener); + container.publish(event); + EasyMock.verify(listener); + } + + public void testToString() { + TestContainer container = new TestContainer("foo"); + assertNotNull(container.toString()); + } + + public void testGetName() { + TestContainer container = new TestContainer("foo"); + assertEquals("foo", container.getName()); + } + + + private class TestContainer extends AbstractScopeContainer { + + public TestContainer(String name) { + super(name, null); + } + + protected InstanceWrapper getInstanceWrapper(AtomicComponent component) { + return null; + } + + public Scope getScope() { + return null; + } + + public void register(AtomicComponent component) { + + } + + public void onEvent(Event event) { + + } + + public WorkContext getWorkContext() { + return super.getWorkContext(); + } + } + + private class TestEvent implements Event { + public Object getSource() { + return null; + } + } + + private class FalseFilter implements EventFilter { + + public boolean match(Event event) { + return false; + } + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/BasicHttpSessionScopeTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/BasicHttpSessionScopeTestCase.java new file mode 100644 index 0000000000..dc8da77490 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/BasicHttpSessionScopeTestCase.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.component.WorkContext; + +import junit.framework.TestCase; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.component.event.HttpSessionEnd; +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.spi.component.SystemAtomicComponent; +import org.apache.tuscany.core.implementation.system.component.SystemAtomicComponentImpl; +import org.apache.tuscany.core.injection.EventInvoker; +import org.apache.tuscany.core.injection.MethodEventInvoker; +import org.apache.tuscany.core.injection.PojoObjectFactory; +import org.apache.tuscany.core.mock.component.SessionScopeInitDestroyComponent; + +/** + * @version $$Rev$$ $$Date$$ + */ +public class BasicHttpSessionScopeTestCase extends TestCase { + + private EventInvoker<Object> initInvoker; + private EventInvoker<Object> destroyInvoker; + private PojoObjectFactory<?> factory; + + public void testLifecycleManagement() throws Exception { + WorkContext workContext = new WorkContextImpl(); + HttpSessionScopeContainer scopeContext = new HttpSessionScopeContainer(workContext); + scopeContext.start(); + SystemAtomicComponent atomicContext = createContext(scopeContext); + // start the request + Object session = new Object(); + workContext.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session); + SessionScopeInitDestroyComponent o1 = + (SessionScopeInitDestroyComponent) scopeContext.getInstance(atomicContext); + assertTrue(o1.isInitialized()); + assertFalse(o1.isDestroyed()); + SessionScopeInitDestroyComponent o2 = + (SessionScopeInitDestroyComponent) scopeContext.getInstance(atomicContext); + assertSame(o1, o2); + scopeContext.onEvent(new HttpSessionEnd(this, session)); + assertTrue(o1.isDestroyed()); + scopeContext.stop(); + } + + public void testSessionIsolation() throws Exception { + WorkContext workContext = new WorkContextImpl(); + HttpSessionScopeContainer scopeContext = new HttpSessionScopeContainer(workContext); + scopeContext.start(); + + SystemAtomicComponent atomicContext = createContext(scopeContext); + + Object session1 = new Object(); + workContext.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session1); + SessionScopeInitDestroyComponent o1 = + (SessionScopeInitDestroyComponent) scopeContext.getInstance(atomicContext); + assertTrue(o1.isInitialized()); + + Object session2 = new Object(); + workContext.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session2); + SessionScopeInitDestroyComponent o2 = + (SessionScopeInitDestroyComponent) scopeContext.getInstance(atomicContext); + assertNotSame(o1, o2); + + scopeContext.onEvent(new HttpSessionEnd(this, session1)); + assertTrue(o1.isDestroyed()); + assertFalse(o2.isDestroyed()); + scopeContext.onEvent(new HttpSessionEnd(this, session2)); + assertTrue(o2.isDestroyed()); + scopeContext.stop(); + } + + protected void setUp() throws Exception { + super.setUp(); + factory = new PojoObjectFactory<SessionScopeInitDestroyComponent>( + SessionScopeInitDestroyComponent.class.getConstructor((Class[]) null)); + initInvoker = new MethodEventInvoker<Object>( + SessionScopeInitDestroyComponent.class.getMethod("init", (Class[]) null)); + destroyInvoker = new MethodEventInvoker<Object>( + SessionScopeInitDestroyComponent.class.getMethod("destroy", (Class[]) null)); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + private SystemAtomicComponent createContext(ScopeContainer scopeContainer) { + PojoConfiguration configuration = new PojoConfiguration(); + configuration.setScopeContainer(scopeContainer); + configuration.addServiceInterface(SessionScopeInitDestroyComponent.class); + configuration.setInstanceFactory(factory); + configuration.setInitInvoker(initInvoker); + configuration.setDestroyInvoker(destroyInvoker); + SystemAtomicComponentImpl context = new SystemAtomicComponentImpl("foo", configuration); + context.start(); + return context; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/BasicModuleScopeTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/BasicModuleScopeTestCase.java new file mode 100644 index 0000000000..a4db2aef85 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/BasicModuleScopeTestCase.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.component.SystemAtomicComponent; + +import junit.framework.TestCase; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.component.event.CompositeStop; +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.core.implementation.system.component.SystemAtomicComponentImpl; +import org.apache.tuscany.core.injection.EventInvoker; +import org.apache.tuscany.core.injection.MethodEventInvoker; +import org.apache.tuscany.core.injection.PojoObjectFactory; +import org.apache.tuscany.core.mock.component.ModuleScopeInitDestroyComponent; + +/** + * @version $$Rev$$ $$Date$$ + */ +public class BasicModuleScopeTestCase extends TestCase { + + private EventInvoker<Object> initInvoker; + private EventInvoker<Object> destroyInvoker; + private PojoObjectFactory<?> factory; + + public void testLifecycleManagement() throws Exception { + WorkContext workContext = new WorkContextImpl(); + ModuleScopeContainer scopeContext = new ModuleScopeContainer(workContext); + scopeContext.start(); + SystemAtomicComponent atomicContext = createContext(scopeContext); + // start the request + ModuleScopeInitDestroyComponent o1 = + (ModuleScopeInitDestroyComponent) scopeContext.getInstance(atomicContext); + assertTrue(o1.isInitialized()); + assertFalse(o1.isDestroyed()); + ModuleScopeInitDestroyComponent o2 = + (ModuleScopeInitDestroyComponent) scopeContext.getInstance(atomicContext); + assertEquals(o1, o2); + scopeContext.onEvent(new CompositeStop(this, null)); + assertTrue(o1.isDestroyed()); + scopeContext.stop(); + } + + public void testModuleIsolation() throws Exception { + WorkContext workContext = new WorkContextImpl(); + ModuleScopeContainer scopeContext = new ModuleScopeContainer(workContext); + scopeContext.start(); + + SystemAtomicComponent atomicContext = createContext(scopeContext); + + ModuleScopeInitDestroyComponent o1 = + (ModuleScopeInitDestroyComponent) scopeContext.getInstance(atomicContext); + assertTrue(o1.isInitialized()); + assertFalse(o1.isDestroyed()); + + ModuleScopeInitDestroyComponent o2 = + (ModuleScopeInitDestroyComponent) scopeContext.getInstance(atomicContext); + assertSame(o1, o2); + scopeContext.onEvent(new CompositeStop(this, null)); + assertTrue(o1.isDestroyed()); + scopeContext.stop(); + } + + protected void setUp() throws Exception { + super.setUp(); + factory = new PojoObjectFactory<ModuleScopeInitDestroyComponent>( + ModuleScopeInitDestroyComponent.class.getConstructor((Class[]) null)); + initInvoker = new MethodEventInvoker<Object>(ModuleScopeInitDestroyComponent.class.getMethod( + "init", (Class[]) null)); + destroyInvoker = new MethodEventInvoker<Object>(ModuleScopeInitDestroyComponent.class.getMethod( + "destroy", (Class[]) null)); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + private SystemAtomicComponent createContext(ScopeContainer scopeContainer) { + PojoConfiguration configuration = new PojoConfiguration(); + configuration.setScopeContainer(scopeContainer); + configuration.addServiceInterface(ModuleScopeInitDestroyComponent.class); + configuration.setInstanceFactory(factory); + configuration.setInitInvoker(initInvoker); + configuration.setDestroyInvoker(destroyInvoker); + SystemAtomicComponentImpl context = new SystemAtomicComponentImpl("foo", configuration); + context.start(); + return context; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/BasicRequestScopeTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/BasicRequestScopeTestCase.java new file mode 100644 index 0000000000..cb6a7c1673 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/BasicRequestScopeTestCase.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.component.SystemAtomicComponent; + +import junit.framework.TestCase; +import org.apache.tuscany.core.component.event.RequestEnd; +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.core.implementation.system.component.SystemAtomicComponentImpl; +import org.apache.tuscany.core.injection.EventInvoker; +import org.apache.tuscany.core.injection.MethodEventInvoker; +import org.apache.tuscany.core.injection.PojoObjectFactory; +import org.apache.tuscany.core.mock.component.RequestScopeInitDestroyComponent; + +/** + * @version $$Rev$$ $$Date$$ + */ +public class BasicRequestScopeTestCase extends TestCase { + + private EventInvoker<Object> initInvoker; + private EventInvoker<Object> destroyInvoker; + private PojoObjectFactory<?> factory; + + public void testLifecycleManagement() throws Exception { + RequestScopeContainer scopeContext = new RequestScopeContainer(null); + scopeContext.start(); + SystemAtomicComponent atomicContext = createContext(scopeContext); + // start the request + RequestScopeInitDestroyComponent o1 = + (RequestScopeInitDestroyComponent) scopeContext.getInstance(atomicContext); + assertTrue(o1.isInitialized()); + assertFalse(o1.isDestroyed()); + RequestScopeInitDestroyComponent o2 = + (RequestScopeInitDestroyComponent) scopeContext.getInstance(atomicContext); + assertSame(o1, o2); + scopeContext.onEvent(new RequestEnd(this)); + assertTrue(o1.isDestroyed()); + scopeContext.stop(); + } + + public void testRequestIsolation() throws Exception { + RequestScopeContainer scopeContext = new RequestScopeContainer(null); + scopeContext.start(); + + SystemAtomicComponent atomicContext = createContext(scopeContext); + + RequestScopeInitDestroyComponent o1 = + (RequestScopeInitDestroyComponent) scopeContext.getInstance(atomicContext); + assertTrue(o1.isInitialized()); + scopeContext.onEvent(new RequestEnd(this)); + assertTrue(o1.isDestroyed()); + + RequestScopeInitDestroyComponent o2 = + (RequestScopeInitDestroyComponent) scopeContext.getInstance(atomicContext); + assertNotSame(o1, o2); + scopeContext.onEvent(new RequestEnd(this)); + assertTrue(o2.isDestroyed()); + scopeContext.stop(); + } + + protected void setUp() throws Exception { + super.setUp(); + factory = new PojoObjectFactory<RequestScopeInitDestroyComponent>( + RequestScopeInitDestroyComponent.class.getConstructor((Class[]) null)); + initInvoker = new MethodEventInvoker<Object>( + RequestScopeInitDestroyComponent.class.getMethod("init", (Class[]) null)); + destroyInvoker = new MethodEventInvoker<Object>( + RequestScopeInitDestroyComponent.class.getMethod("destroy", (Class[]) null)); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + private SystemAtomicComponent createContext(ScopeContainer scopeContainer) { + PojoConfiguration configuration = new PojoConfiguration(); + configuration.setScopeContainer(scopeContainer); + configuration.addServiceInterface(RequestScopeInitDestroyComponent.class); + configuration.setInstanceFactory(factory); + configuration.setInitInvoker(initInvoker); + configuration.setDestroyInvoker(destroyInvoker); + SystemAtomicComponentImpl component = new SystemAtomicComponentImpl("foo", configuration); + scopeContainer.register(component); + return component; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/BasicStatelessScopeTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/BasicStatelessScopeTestCase.java new file mode 100644 index 0000000000..a38abdc390 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/BasicStatelessScopeTestCase.java @@ -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.core.component.scope; + +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.component.SystemAtomicComponent; + +import junit.framework.Assert; +import junit.framework.TestCase; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.mock.component.StatelessComponent; +import org.apache.tuscany.core.mock.component.StatelessComponentImpl; +import org.apache.tuscany.core.mock.factories.MockFactory; + +/** + * Unit tests for the module scope container + * + * @version $Rev$ $Date$ + */ +public class BasicStatelessScopeTestCase extends TestCase { + + /** + * Tests instance identity is properly maintained + */ + public void testInstanceManagement() throws Exception { + WorkContext ctx = new WorkContextImpl(); + StatelessScopeContainer scope = new StatelessScopeContainer(ctx); + scope.start(); + SystemAtomicComponent context1 = + MockFactory.createAtomicComponent("comp1", scope, StatelessComponentImpl.class); + scope.register(context1); + SystemAtomicComponent context2 = + MockFactory.createAtomicComponent("comp2", scope, StatelessComponentImpl.class); + scope.register(context2); + StatelessComponentImpl comp1 = (StatelessComponentImpl) scope.getInstance(context1); + Assert.assertNotNull(comp1); + StatelessComponentImpl comp2 = (StatelessComponentImpl) scope.getInstance(context2); + Assert.assertNotNull(comp2); + Assert.assertNotSame(comp1, comp2); + scope.stop(); + } + + public void testRegisterContextAfterRequest() throws Exception { + WorkContext ctx = new WorkContextImpl(); + StatelessScopeContainer scope = new StatelessScopeContainer(ctx); + + scope.start(); + SystemAtomicComponent context1 = + MockFactory.createAtomicComponent("comp1", scope, StatelessComponentImpl.class); + scope.register(context1); + StatelessComponent comp1 = (StatelessComponentImpl) scope.getInstance(context1); + Assert.assertNotNull(comp1); + SystemAtomicComponent context2 = + MockFactory.createAtomicComponent("comp2", scope, StatelessComponentImpl.class); + scope.register(context2); + StatelessComponentImpl comp2 = (StatelessComponentImpl) scope.getInstance(context2); + Assert.assertNotNull(comp2); + scope.stop(); + } + + + /** + * Tests setting no components in the scope + */ + public void testSetNullComponents() throws Exception { + WorkContext ctx = new WorkContextImpl(); + StatelessScopeContainer scope = new StatelessScopeContainer(ctx); + scope.start(); + scope.stop(); + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/DependencyLifecycleTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/DependencyLifecycleTestCase.java new file mode 100644 index 0000000000..ec23914acc --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/DependencyLifecycleTestCase.java @@ -0,0 +1,172 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import java.util.Map; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.WorkContext; + +import junit.framework.TestCase; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.component.event.CompositeStart; +import org.apache.tuscany.core.component.event.CompositeStop; +import org.apache.tuscany.core.component.event.HttpSessionEnd; +import org.apache.tuscany.core.component.event.RequestEnd; +import org.apache.tuscany.core.component.event.RequestStart; +import org.apache.tuscany.core.mock.component.OrderedDependentPojo; +import org.apache.tuscany.core.mock.component.OrderedDependentPojoImpl; +import org.apache.tuscany.core.mock.component.OrderedInitPojo; +import org.apache.tuscany.core.mock.component.OrderedInitPojoImpl; +import org.apache.tuscany.core.mock.factories.MockFactory; + +/** + * Tests dependencies are initalized and destroyed in the proper order (i.e. LIFO) + * + * @version $Rev$ $Date$ + */ +public class DependencyLifecycleTestCase extends TestCase { + + public void testInitDestroyOrderModuleScope() throws Exception { + WorkContext ctx = new WorkContextImpl(); + ModuleScopeContainer scopeCtx = new ModuleScopeContainer(ctx); + scopeCtx.start(); + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", + OrderedDependentPojoImpl.class, + scopeCtx, + "target", + OrderedInitPojoImpl.class, + scopeCtx); + for (AtomicComponent component : contexts.values()) { + scopeCtx.register(component); + } + AtomicComponent sourceComponent = contexts.get("source"); + AtomicComponent targetComponent = contexts.get("target"); + scopeCtx.register(sourceComponent); + scopeCtx.register(targetComponent); + scopeCtx.onEvent(new CompositeStart(this, null)); + OrderedDependentPojo source = (OrderedDependentPojo) scopeCtx.getInstance(sourceComponent); + OrderedInitPojo target = (OrderedInitPojo) scopeCtx.getInstance(targetComponent); + assertNotNull(source.getPojo()); + assertNotNull(target); + assertEquals(2, source.getNumberInstantiated()); + scopeCtx.onEvent(new CompositeStop(this, null)); + assertEquals(0, source.getNumberInstantiated()); + scopeCtx.stop(); + } + + public void testInitDestroyOrderAfterStartModuleScope() throws Exception { + WorkContext ctx = new WorkContextImpl(); + ModuleScopeContainer scopeCtx = new ModuleScopeContainer(ctx); + scopeCtx.start(); + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", + OrderedDependentPojoImpl.class, + scopeCtx, + "target", + OrderedInitPojoImpl.class, + scopeCtx); + AtomicComponent sourceComponent = contexts.get("source"); + AtomicComponent targetComponent = contexts.get("target"); + scopeCtx.onEvent(new CompositeStart(this, null)); + scopeCtx.register(sourceComponent); + scopeCtx.register(targetComponent); + OrderedDependentPojo source = (OrderedDependentPojo) scopeCtx.getInstance(sourceComponent); + OrderedInitPojo target = (OrderedInitPojo) scopeCtx.getInstance(targetComponent); + assertNotNull(source.getPojo()); + assertNotNull(target); + assertEquals(2, source.getNumberInstantiated()); + scopeCtx.onEvent(new CompositeStop(this, null)); + assertEquals(0, source.getNumberInstantiated()); + scopeCtx.stop(); + } + + + public void testInitDestroyOrderSessionScope() throws Exception { + WorkContext ctx = new WorkContextImpl(); + HttpSessionScopeContainer scopeCtx = new HttpSessionScopeContainer(ctx); + scopeCtx.start(); + Object session = new Object(); + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", + OrderedDependentPojoImpl.class, + scopeCtx, + "target", + OrderedInitPojoImpl.class, + scopeCtx); + AtomicComponent sourceComponent = contexts.get("source"); + AtomicComponent targetComponent = contexts.get("target"); + scopeCtx.register(sourceComponent); + scopeCtx.register(targetComponent); + ctx.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session); + OrderedDependentPojo source = (OrderedDependentPojo) scopeCtx.getInstance(sourceComponent); + assertNotNull(source.getPojo()); + assertEquals(2, source.getNumberInstantiated()); + scopeCtx.onEvent(new HttpSessionEnd(this, session)); + assertEquals(0, source.getNumberInstantiated()); + scopeCtx.stop(); + } + + + public void testInitDestroyOrderAfterStartSessionScope() throws Exception { + WorkContext ctx = new WorkContextImpl(); + HttpSessionScopeContainer scopeCtx = new HttpSessionScopeContainer(ctx); + scopeCtx.start(); + Object session = new Object(); + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", + OrderedDependentPojoImpl.class, + scopeCtx, + "target", + OrderedInitPojoImpl.class, + scopeCtx); + AtomicComponent sourceComponent = contexts.get("source"); + AtomicComponent targetComponent = contexts.get("target"); + ctx.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session); + scopeCtx.register(sourceComponent); + scopeCtx.register(targetComponent); + OrderedDependentPojo source = (OrderedDependentPojo) scopeCtx.getInstance(sourceComponent); + assertNotNull(source.getPojo()); + assertEquals(2, source.getNumberInstantiated()); + scopeCtx.onEvent(new HttpSessionEnd(this, session)); + assertEquals(0, source.getNumberInstantiated()); + scopeCtx.stop(); + } + + public void testInitDestroyOrderRequestScope() throws Exception { + WorkContext ctx = new WorkContextImpl(); + RequestScopeContainer scopeCtx = new RequestScopeContainer(ctx); + scopeCtx.start(); + scopeCtx.onEvent(new RequestStart(this)); + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", + OrderedDependentPojoImpl.class, + scopeCtx, + "target", + OrderedInitPojoImpl.class, + scopeCtx); + AtomicComponent sourceComponent = contexts.get("source"); + AtomicComponent targetComponent = contexts.get("target"); + scopeCtx.register(sourceComponent); + scopeCtx.register(targetComponent); + OrderedDependentPojo source = (OrderedDependentPojo) scopeCtx.getInstance(sourceComponent); + assertNotNull(source.getPojo()); + assertEquals(2, source.getNumberInstantiated()); + scopeCtx.onEvent(new RequestEnd(this)); + assertEquals(0, source.getNumberInstantiated()); + scopeCtx.stop(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/HttpSessionScopeInstanceLifecycleTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/HttpSessionScopeInstanceLifecycleTestCase.java new file mode 100644 index 0000000000..4fe99e841c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/HttpSessionScopeInstanceLifecycleTestCase.java @@ -0,0 +1,165 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.component.SystemAtomicComponent; + +import junit.framework.Assert; +import junit.framework.TestCase; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.component.event.HttpSessionEnd; +import org.apache.tuscany.core.component.event.HttpSessionStart; +import org.apache.tuscany.core.mock.component.OrderedEagerInitPojo; +import org.apache.tuscany.core.mock.component.OrderedInitPojo; +import org.apache.tuscany.core.mock.component.OrderedInitPojoImpl; +import org.apache.tuscany.core.mock.component.RequestScopeDestroyOnlyComponent; +import org.apache.tuscany.core.mock.component.RequestScopeInitDestroyComponent; +import org.apache.tuscany.core.mock.component.RequestScopeInitOnlyComponent; +import org.apache.tuscany.core.mock.factories.MockFactory; + +/** + * Lifecycle unit tests for the module scope container + * + * @version $Rev$ $Date$ + */ +public class HttpSessionScopeInstanceLifecycleTestCase extends TestCase { + + public void testInitDestroy() throws Exception { + WorkContext ctx = new WorkContextImpl(); + HttpSessionScopeContainer scope = new HttpSessionScopeContainer(ctx); + scope.start(); + + SystemAtomicComponent initDestroyContext = MockFactory.createAtomicComponent("InitDestroy", + scope, + RequestScopeInitDestroyComponent.class); + initDestroyContext.start(); + + SystemAtomicComponent initOnlyContext = MockFactory.createAtomicComponent("InitOnly", + scope, + RequestScopeInitOnlyComponent.class); + initOnlyContext.start(); + + SystemAtomicComponent destroyOnlyContext = MockFactory.createAtomicComponent("DestroyOnly", + scope, + RequestScopeDestroyOnlyComponent.class); + destroyOnlyContext.start(); + + Object session = new Object(); + ctx.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session); + scope.onEvent(new HttpSessionStart(this, session)); + RequestScopeInitDestroyComponent initDestroy = + (RequestScopeInitDestroyComponent) scope.getInstance(initDestroyContext); + Assert.assertNotNull(initDestroy); + + RequestScopeInitOnlyComponent initOnly = + (RequestScopeInitOnlyComponent) scope.getInstance(initOnlyContext); + Assert.assertNotNull(initOnly); + + RequestScopeDestroyOnlyComponent destroyOnly = + (RequestScopeDestroyOnlyComponent) scope.getInstance(destroyOnlyContext); + Assert.assertNotNull(destroyOnly); + + Assert.assertTrue(initDestroy.isInitialized()); + Assert.assertTrue(initOnly.isInitialized()); + Assert.assertFalse(initDestroy.isDestroyed()); + Assert.assertFalse(destroyOnly.isDestroyed()); + + // expire module + scope.onEvent(new HttpSessionEnd(this, session)); + + Assert.assertTrue(initDestroy.isDestroyed()); + Assert.assertTrue(destroyOnly.isDestroyed()); + + scope.stop(); + } + + public void testDestroyOrder() throws Exception { + WorkContext ctx = new WorkContextImpl(); + HttpSessionScopeContainer scope = new HttpSessionScopeContainer(ctx); + scope.start(); + + SystemAtomicComponent oneCtx = + MockFactory.createAtomicComponent("one", scope, OrderedInitPojoImpl.class); + scope.register(oneCtx); + SystemAtomicComponent twoCtx = + MockFactory.createAtomicComponent("two", scope, OrderedInitPojoImpl.class); + scope.register(twoCtx); + SystemAtomicComponent threeCtx = + MockFactory.createAtomicComponent("three", scope, OrderedInitPojoImpl.class); + scope.register(threeCtx); + + Object session = new Object(); + ctx.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session); + scope.onEvent(new HttpSessionStart(this, session)); + OrderedInitPojo one = (OrderedInitPojo) scope.getInstance(oneCtx); + Assert.assertNotNull(one); + Assert.assertEquals(1, one.getNumberInstantiated()); + Assert.assertEquals(1, one.getInitOrder()); + + OrderedInitPojo two = (OrderedInitPojo) scope.getInstance(twoCtx); + Assert.assertNotNull(two); + Assert.assertEquals(2, two.getNumberInstantiated()); + Assert.assertEquals(2, two.getInitOrder()); + + OrderedInitPojo three = (OrderedInitPojo) scope.getInstance(threeCtx); + Assert.assertNotNull(three); + Assert.assertEquals(3, three.getNumberInstantiated()); + Assert.assertEquals(3, three.getInitOrder()); + + // expire module + scope.onEvent(new HttpSessionEnd(this, session)); + Assert.assertEquals(0, one.getNumberInstantiated()); + scope.stop(); + } + + public void testEagerInitDestroyOrder() throws Exception { + WorkContext ctx = new WorkContextImpl(); + HttpSessionScopeContainer scope = new HttpSessionScopeContainer(ctx); + scope.start(); + + SystemAtomicComponent oneCtx = + MockFactory.createAtomicComponent("one", scope, OrderedEagerInitPojo.class); + scope.register(oneCtx); + SystemAtomicComponent twoCtx = + MockFactory.createAtomicComponent("two", scope, OrderedEagerInitPojo.class); + scope.register(twoCtx); + SystemAtomicComponent threeCtx = + MockFactory.createAtomicComponent("three", scope, OrderedEagerInitPojo.class); + scope.register(threeCtx); + + Object session = new Object(); + ctx.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session); + scope.onEvent(new HttpSessionStart(this, session)); + OrderedEagerInitPojo one = (OrderedEagerInitPojo) scope.getInstance(oneCtx); + Assert.assertNotNull(one); + + OrderedEagerInitPojo two = (OrderedEagerInitPojo) scope.getInstance(twoCtx); + Assert.assertNotNull(two); + + OrderedEagerInitPojo three = (OrderedEagerInitPojo) scope.getInstance(threeCtx); + Assert.assertNotNull(three); + + // expire module + scope.onEvent(new HttpSessionEnd(this, session)); + Assert.assertEquals(0, one.getNumberInstantiated()); + scope.stop(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/HttpSessionScopeRestartTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/HttpSessionScopeRestartTestCase.java new file mode 100644 index 0000000000..0c781cac85 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/HttpSessionScopeRestartTestCase.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import java.lang.reflect.Constructor; + +import org.apache.tuscany.spi.component.WorkContext; + +import junit.framework.TestCase; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.component.event.HttpSessionEnd; +import org.apache.tuscany.core.component.event.HttpSessionStart; +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.spi.component.SystemAtomicComponent; +import org.apache.tuscany.core.implementation.system.component.SystemAtomicComponentImpl; +import org.apache.tuscany.core.injection.MethodEventInvoker; +import org.apache.tuscany.core.injection.PojoObjectFactory; + +/** + * Verifies the scope container properly disposes resources and canbe restarted + * + * @version $$Rev$$ $$Date$$ + */ +public class HttpSessionScopeRestartTestCase extends TestCase { + + public void testRestart() throws Exception { + WorkContext ctx = new WorkContextImpl(); + HttpSessionScopeContainer scope = new HttpSessionScopeContainer(ctx); + scope.start(); + MethodEventInvoker<Object> initInvoker = new MethodEventInvoker<Object>( + HttpSessionScopeRestartTestCase.InitDestroyOnce.class.getMethod("init")); + MethodEventInvoker<Object> destroyInvoker = + new MethodEventInvoker<Object>(InitDestroyOnce.class.getMethod("destroy")); + PojoConfiguration configuration = new PojoConfiguration(); + configuration.setScopeContainer(scope); + configuration.addServiceInterface(HttpSessionScopeRestartTestCase.InitDestroyOnce.class); + configuration.setInitInvoker(initInvoker); + configuration.setDestroyInvoker(destroyInvoker); + Constructor<InitDestroyOnce> ctr = InitDestroyOnce.class.getConstructor((Class<?>[]) null); + configuration.setInstanceFactory(new PojoObjectFactory<InitDestroyOnce>(ctr)); + SystemAtomicComponent context = new SystemAtomicComponentImpl("InitDestroy", configuration); + context.start(); + + Object session = new Object(); + ctx.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session); + scope.onEvent(new HttpSessionStart(this, session)); + Object instance = context.getServiceInstance(); + assertSame(instance, context.getServiceInstance()); + + scope.onEvent(new HttpSessionEnd(this, session)); + scope.stop(); + context.stop(); + + scope.start(); + scope.onEvent(new HttpSessionStart(this, session)); + context.start(); + assertNotSame(instance, context.getServiceInstance()); + scope.onEvent(new HttpSessionEnd(this, session)); + scope.stop(); + context.stop(); + } + + public static class InitDestroyOnce { + + private boolean initialized; + private boolean destroyed; + + public InitDestroyOnce() { + } + + public void init() { + if (!initialized) { + initialized = true; + } else { + fail("Scope did not clean up properly - Init called more than once"); + } + } + + public void destroy() { + if (!destroyed) { + destroyed = true; + } else { + fail("Scope did not clean up properly - Destroyed called more than once"); + } + } + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/InstanceWrapperTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/InstanceWrapperTestCase.java new file mode 100644 index 0000000000..5071196d5e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/InstanceWrapperTestCase.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.apache.tuscany.spi.Lifecycle; +import org.apache.tuscany.spi.component.AtomicComponent; + +import junit.framework.TestCase; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class InstanceWrapperTestCase extends TestCase { + + + public void testExceptionInit() throws Exception { + AtomicComponent component = getComponent(); + InstanceWrapper wrapper = new InstanceWrapperImpl(component, new Object()); + try { + wrapper.start(); + fail(); + } catch (SomeException e) { + // expected + } + assertEquals(Lifecycle.ERROR, wrapper.getLifecycleState()); + EasyMock.verify(component); + } + + public void testNonStart() throws Exception { + AtomicComponent comp = EasyMock.createNiceMock(AtomicComponent.class); // class-level one has an expects + InstanceWrapper wrapper = new InstanceWrapperImpl(comp, new Object()); + try { + wrapper.getInstance(); + fail(); + } catch (IllegalStateException e) { + // expected + } + } + + private AtomicComponent getComponent() throws Exception { + // do not use setUp() since we do not need this in all testcases + AtomicComponent comp = EasyMock.createMock(AtomicComponent.class); + comp.init(EasyMock.isA(Object.class)); + EasyMock.expectLastCall().andThrow(new SomeException()); + EasyMock.replay(comp); + return comp; + } + + private class SomeException extends RuntimeException { + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/ModuleScopeInstanceLifecycleTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/ModuleScopeInstanceLifecycleTestCase.java new file mode 100644 index 0000000000..fce04967fc --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/ModuleScopeInstanceLifecycleTestCase.java @@ -0,0 +1,165 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + + +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.component.SystemAtomicComponent; + +import junit.framework.Assert; +import junit.framework.TestCase; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.component.event.CompositeStart; +import org.apache.tuscany.core.component.event.CompositeStop; +import org.apache.tuscany.core.mock.component.ModuleScopeDestroyOnlyComponent; +import org.apache.tuscany.core.mock.component.ModuleScopeInitDestroyComponent; +import org.apache.tuscany.core.mock.component.ModuleScopeInitOnlyComponent; +import org.apache.tuscany.core.mock.component.OrderedEagerInitPojo; +import org.apache.tuscany.core.mock.component.OrderedInitPojo; +import org.apache.tuscany.core.mock.component.OrderedInitPojoImpl; +import org.apache.tuscany.core.mock.factories.MockFactory; + +/** + * Lifecycle unit tests for the module scope container + * + * @version $Rev$ $Date$ + */ +public class ModuleScopeInstanceLifecycleTestCase extends TestCase { + + public void testInitDestroy() throws Exception { + WorkContext ctx = new WorkContextImpl(); + ModuleScopeContainer scope = new ModuleScopeContainer(ctx); + scope.start(); + + SystemAtomicComponent initDestroyContext = MockFactory.createAtomicComponent("InitDestroy", + scope, + ModuleScopeInitDestroyComponent.class); + initDestroyContext.start(); + + SystemAtomicComponent initOnlyContext = MockFactory.createAtomicComponent("InitOnly", + scope, + ModuleScopeInitOnlyComponent.class); + initOnlyContext.start(); + + SystemAtomicComponent destroyOnlyContext = MockFactory.createAtomicComponent("DestroyOnly", + scope, + ModuleScopeDestroyOnlyComponent.class); + destroyOnlyContext.start(); + + scope.onEvent(new CompositeStart(this, null)); + ModuleScopeInitDestroyComponent initDestroy = + (ModuleScopeInitDestroyComponent) scope.getInstance(initDestroyContext); + Assert.assertNotNull(initDestroy); + + ModuleScopeInitOnlyComponent initOnly = (ModuleScopeInitOnlyComponent) scope.getInstance(initOnlyContext); + Assert.assertNotNull(initOnly); + + ModuleScopeDestroyOnlyComponent destroyOnly = + (ModuleScopeDestroyOnlyComponent) scope.getInstance(destroyOnlyContext); + Assert.assertNotNull(destroyOnly); + + Assert.assertTrue(initDestroy.isInitialized()); + Assert.assertTrue(initOnly.isInitialized()); + Assert.assertFalse(initDestroy.isDestroyed()); + Assert.assertFalse(destroyOnly.isDestroyed()); + + // expire module + scope.onEvent(new CompositeStop(this, null)); + + Assert.assertTrue(initDestroy.isDestroyed()); + Assert.assertTrue(destroyOnly.isDestroyed()); + + scope.stop(); + } + + public void testDestroyOrder() throws Exception { + WorkContext ctx = new WorkContextImpl(); + ModuleScopeContainer scope = new ModuleScopeContainer(ctx); + scope.start(); + + SystemAtomicComponent oneCtx = MockFactory.createAtomicComponent("one", + scope, + OrderedInitPojoImpl.class); + scope.register(oneCtx); + SystemAtomicComponent twoCtx = MockFactory.createAtomicComponent("two", + scope, + OrderedInitPojoImpl.class); + scope.register(twoCtx); + SystemAtomicComponent threeCtx = MockFactory.createAtomicComponent("three", + scope, + OrderedInitPojoImpl.class); + scope.register(threeCtx); + + scope.onEvent(new CompositeStart(this, null)); + OrderedInitPojo one = (OrderedInitPojo) scope.getInstance(oneCtx); + Assert.assertNotNull(one); + Assert.assertEquals(1, one.getNumberInstantiated()); + Assert.assertEquals(1, one.getInitOrder()); + + OrderedInitPojo two = (OrderedInitPojo) scope.getInstance(twoCtx); + Assert.assertNotNull(two); + Assert.assertEquals(2, two.getNumberInstantiated()); + Assert.assertEquals(2, two.getInitOrder()); + + OrderedInitPojo three = (OrderedInitPojo) scope.getInstance(threeCtx); + Assert.assertNotNull(three); + Assert.assertEquals(3, three.getNumberInstantiated()); + Assert.assertEquals(3, three.getInitOrder()); + + // expire module + scope.onEvent(new CompositeStop(this, null)); + Assert.assertEquals(0, one.getNumberInstantiated()); + scope.stop(); + } + + public void testEagerInitDestroyOrder() throws Exception { + WorkContext ctx = new WorkContextImpl(); + ModuleScopeContainer scope = new ModuleScopeContainer(ctx); + scope.start(); + + SystemAtomicComponent oneCtx = MockFactory.createAtomicComponent("one", + scope, + OrderedEagerInitPojo.class); + scope.register(oneCtx); + SystemAtomicComponent twoCtx = MockFactory.createAtomicComponent("two", + scope, + OrderedEagerInitPojo.class); + scope.register(twoCtx); + SystemAtomicComponent threeCtx = MockFactory.createAtomicComponent("three", + scope, + OrderedEagerInitPojo.class); + scope.register(threeCtx); + + scope.onEvent(new CompositeStart(this, null)); + OrderedEagerInitPojo one = (OrderedEagerInitPojo) scope.getInstance(oneCtx); + Assert.assertNotNull(one); + + OrderedEagerInitPojo two = (OrderedEagerInitPojo) scope.getInstance(twoCtx); + Assert.assertNotNull(two); + + OrderedEagerInitPojo three = (OrderedEagerInitPojo) scope.getInstance(threeCtx); + Assert.assertNotNull(three); + + // expire module + scope.onEvent(new CompositeStop(this, null)); + Assert.assertEquals(0, one.getNumberInstantiated()); + scope.stop(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/ModuleScopeObjectFactoryTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/ModuleScopeObjectFactoryTestCase.java new file mode 100644 index 0000000000..69ebc96d95 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/ModuleScopeObjectFactoryTestCase.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.apache.tuscany.spi.component.ScopeRegistry; +import org.apache.tuscany.spi.model.Scope; + +import junit.framework.TestCase; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class ModuleScopeObjectFactoryTestCase extends TestCase { + + public void testCreation() { + ScopeRegistry registry = EasyMock.createMock(ScopeRegistry.class); + registry.registerFactory(EasyMock.isA(Scope.class), EasyMock.isA(ModuleScopeObjectFactory.class)); + + assertNotNull(new ModuleScopeObjectFactory(registry).getInstance()); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/ModuleScopeRestartTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/ModuleScopeRestartTestCase.java new file mode 100644 index 0000000000..4c57b81953 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/ModuleScopeRestartTestCase.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import java.lang.reflect.Constructor; + +import org.apache.tuscany.spi.component.WorkContext; + +import junit.framework.TestCase; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.component.event.CompositeStart; +import org.apache.tuscany.core.component.event.CompositeStop; +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.spi.component.SystemAtomicComponent; +import org.apache.tuscany.core.implementation.system.component.SystemAtomicComponentImpl; +import org.apache.tuscany.core.injection.MethodEventInvoker; +import org.apache.tuscany.core.injection.PojoObjectFactory; + +/** + * Verifies the scope container properly disposes resources and canbe restarted + * + * @version $$Rev$$ $$Date$$ + */ +public class ModuleScopeRestartTestCase extends TestCase { + + public void testRestart() throws Exception { + WorkContext ctx = new WorkContextImpl(); + ModuleScopeContainer scope = new ModuleScopeContainer(ctx); + scope.start(); + MethodEventInvoker<Object> initInvoker = + new MethodEventInvoker<Object>(InitDestroyOnce.class.getMethod("init")); + MethodEventInvoker<Object> destroyInvoker = + new MethodEventInvoker<Object>(InitDestroyOnce.class.getMethod("destroy")); + PojoConfiguration configuration = new PojoConfiguration(); + configuration.setScopeContainer(scope); + configuration.addServiceInterface(InitDestroyOnce.class); + configuration.setInitInvoker(initInvoker); + configuration.setDestroyInvoker(destroyInvoker); + Constructor<InitDestroyOnce> ctr = InitDestroyOnce.class.getConstructor((Class<?>[]) null); + configuration.setInstanceFactory(new PojoObjectFactory<InitDestroyOnce>(ctr)); + SystemAtomicComponent context = new SystemAtomicComponentImpl("InitDestroy", configuration); + context.start(); + + scope.onEvent(new CompositeStart(this, null)); + Object instance = context.getServiceInstance(); + assertSame(instance, context.getServiceInstance()); + + scope.onEvent(new CompositeStop(this, null)); + scope.stop(); + context.stop(); + + scope.start(); + scope.onEvent(new CompositeStart(this, null)); + context.start(); + assertNotSame(instance, context.getServiceInstance()); + scope.onEvent(new CompositeStop(this, null)); + scope.stop(); + context.stop(); + } + + public static class InitDestroyOnce { + + private boolean initialized; + private boolean destroyed; + + public InitDestroyOnce() { + } + + public void init() { + if (!initialized) { + initialized = true; + } else { + fail("Scope did not clean up properly - Init called more than once"); + } + } + + public void destroy() { + if (!destroyed) { + destroyed = true; + } else { + fail("Scope did not clean up properly - Destroyed called more than once"); + } + } + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/RequestScopeInstanceLifecycleTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/RequestScopeInstanceLifecycleTestCase.java new file mode 100644 index 0000000000..52f27ee869 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/RequestScopeInstanceLifecycleTestCase.java @@ -0,0 +1,155 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.component.SystemAtomicComponent; + +import junit.framework.Assert; +import junit.framework.TestCase; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.component.event.RequestEnd; +import org.apache.tuscany.core.component.event.RequestStart; +import org.apache.tuscany.core.mock.component.OrderedEagerInitPojo; +import org.apache.tuscany.core.mock.component.OrderedInitPojo; +import org.apache.tuscany.core.mock.component.OrderedInitPojoImpl; +import org.apache.tuscany.core.mock.component.RequestScopeDestroyOnlyComponent; +import org.apache.tuscany.core.mock.component.RequestScopeInitDestroyComponent; +import org.apache.tuscany.core.mock.component.RequestScopeInitOnlyComponent; +import org.apache.tuscany.core.mock.factories.MockFactory; + +/** + * Lifecycle unit tests for the module scope container + * + * @version $Rev$ $Date$ + */ +public class RequestScopeInstanceLifecycleTestCase extends TestCase { + + public void testInitDestroy() throws Exception { + WorkContext ctx = new WorkContextImpl(); + RequestScopeContainer scope = new RequestScopeContainer(ctx); + scope.start(); + + SystemAtomicComponent initDestroyContext = MockFactory + .createAtomicComponent("InitDestroy", scope, RequestScopeInitDestroyComponent.class); + initDestroyContext.start(); + + SystemAtomicComponent initOnlyContext = + MockFactory.createAtomicComponent("InitOnly", scope, RequestScopeInitOnlyComponent.class); + initOnlyContext.start(); + + SystemAtomicComponent destroyOnlyContext = MockFactory + .createAtomicComponent("DestroyOnly", scope, RequestScopeDestroyOnlyComponent.class); + destroyOnlyContext.start(); + + scope.onEvent(new RequestStart(this)); + RequestScopeInitDestroyComponent initDestroy = + (RequestScopeInitDestroyComponent) scope.getInstance(initDestroyContext); + Assert.assertNotNull(initDestroy); + + RequestScopeInitOnlyComponent initOnly = (RequestScopeInitOnlyComponent) scope.getInstance(initOnlyContext); + Assert.assertNotNull(initOnly); + + RequestScopeDestroyOnlyComponent destroyOnly = + (RequestScopeDestroyOnlyComponent) scope.getInstance(destroyOnlyContext); + Assert.assertNotNull(destroyOnly); + + Assert.assertTrue(initDestroy.isInitialized()); + Assert.assertTrue(initOnly.isInitialized()); + Assert.assertFalse(initDestroy.isDestroyed()); + Assert.assertFalse(destroyOnly.isDestroyed()); + + // expire module + scope.onEvent(new RequestEnd(this)); + + Assert.assertTrue(initDestroy.isDestroyed()); + Assert.assertTrue(destroyOnly.isDestroyed()); + + scope.stop(); + } + + public void testDestroyOrder() throws Exception { + WorkContext ctx = new WorkContextImpl(); + RequestScopeContainer scope = new RequestScopeContainer(ctx); + scope.start(); + + SystemAtomicComponent oneCtx = + MockFactory.createAtomicComponent("one", scope, OrderedInitPojoImpl.class); + scope.register(oneCtx); + SystemAtomicComponent twoCtx = + MockFactory.createAtomicComponent("two", scope, OrderedInitPojoImpl.class); + scope.register(twoCtx); + SystemAtomicComponent threeCtx = + MockFactory.createAtomicComponent("three", scope, OrderedInitPojoImpl.class); + scope.register(threeCtx); + + scope.onEvent(new RequestStart(this)); + OrderedInitPojo one = (OrderedInitPojo) scope.getInstance(oneCtx); + Assert.assertNotNull(one); + Assert.assertEquals(1, one.getNumberInstantiated()); + Assert.assertEquals(1, one.getInitOrder()); + + OrderedInitPojo two = (OrderedInitPojo) scope.getInstance(twoCtx); + Assert.assertNotNull(two); + Assert.assertEquals(2, two.getNumberInstantiated()); + Assert.assertEquals(2, two.getInitOrder()); + + OrderedInitPojo three = (OrderedInitPojo) scope.getInstance(threeCtx); + Assert.assertNotNull(three); + Assert.assertEquals(3, three.getNumberInstantiated()); + Assert.assertEquals(3, three.getInitOrder()); + + // expire module + scope.onEvent(new RequestEnd(this)); + Assert.assertEquals(0, one.getNumberInstantiated()); + scope.stop(); + } + + public void testEagerInitDestroyOrder() throws Exception { + WorkContext ctx = new WorkContextImpl(); + RequestScopeContainer scope = new RequestScopeContainer(ctx); + scope.start(); + + SystemAtomicComponent oneCtx = + MockFactory.createAtomicComponent("one", scope, OrderedEagerInitPojo.class); + scope.register(oneCtx); + SystemAtomicComponent twoCtx = + MockFactory.createAtomicComponent("two", scope, OrderedEagerInitPojo.class); + scope.register(twoCtx); + SystemAtomicComponent threeCtx = + MockFactory.createAtomicComponent("three", scope, OrderedEagerInitPojo.class); + scope.register(threeCtx); + + scope.onEvent(new RequestStart(this)); + OrderedEagerInitPojo one = (OrderedEagerInitPojo) scope.getInstance(oneCtx); + Assert.assertNotNull(one); + + OrderedEagerInitPojo two = (OrderedEagerInitPojo) scope.getInstance(twoCtx); + Assert.assertNotNull(two); + + OrderedEagerInitPojo three = (OrderedEagerInitPojo) scope.getInstance(threeCtx); + Assert.assertNotNull(three); + + // expire module + scope.onEvent(new RequestEnd(this)); + Assert.assertEquals(0, one.getNumberInstantiated()); + scope.stop(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/RequestScopeRestartTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/RequestScopeRestartTestCase.java new file mode 100644 index 0000000000..b4b835e742 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/RequestScopeRestartTestCase.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import java.lang.reflect.Constructor; + +import org.apache.tuscany.spi.component.WorkContext; + +import junit.framework.TestCase; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.component.event.RequestEnd; +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.spi.component.SystemAtomicComponent; +import org.apache.tuscany.core.implementation.system.component.SystemAtomicComponentImpl; +import org.apache.tuscany.core.injection.MethodEventInvoker; +import org.apache.tuscany.core.injection.PojoObjectFactory; + +/** + * Verifies the scope container properly disposes resources and canbe restarted + * + * @version $$Rev$$ $$Date$$ + */ +public class RequestScopeRestartTestCase extends TestCase { + + public void testRestart() throws Exception { + WorkContext ctx = new WorkContextImpl(); + RequestScopeContainer scope = new RequestScopeContainer(ctx); + scope.start(); + MethodEventInvoker<Object> initInvoker = + new MethodEventInvoker<Object>(InitDestroyOnce.class.getMethod("init")); + MethodEventInvoker<Object> destroyInvoker = + new MethodEventInvoker<Object>(InitDestroyOnce.class.getMethod("destroy")); + PojoConfiguration configuration = new PojoConfiguration(); + configuration.setScopeContainer(scope); + configuration.addServiceInterface(InitDestroyOnce.class); + configuration.setInitInvoker(initInvoker); + configuration.setDestroyInvoker(destroyInvoker); + Constructor<InitDestroyOnce> ctr = InitDestroyOnce.class.getConstructor((Class<?>[]) null); + configuration.setInstanceFactory(new PojoObjectFactory<InitDestroyOnce>(ctr)); + SystemAtomicComponent context = new SystemAtomicComponentImpl("InitDestroy", configuration); + context.start(); + + Object instance = context.getServiceInstance(); + assertSame(instance, context.getServiceInstance()); + + scope.onEvent(new RequestEnd(this)); + scope.stop(); + context.stop(); + + scope.start(); + context.start(); + assertNotSame(instance, context.getServiceInstance()); + scope.onEvent(new RequestEnd(this)); + scope.stop(); + context.stop(); + } + + public static class InitDestroyOnce { + + private boolean initialized; + private boolean destroyed; + + public InitDestroyOnce() { + } + + public void init() { + if (!initialized) { + initialized = true; + } else { + fail("Scope did not clean up properly - Init called more than once"); + } + } + + public void destroy() { + if (!destroyed) { + destroyed = true; + } else { + fail("Scope did not clean up properly - Destroyed called more than once"); + } + } + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/ScopeRegistryTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/ScopeRegistryTestCase.java new file mode 100644 index 0000000000..d6000dd8c4 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/ScopeRegistryTestCase.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.component.ScopeNotFoundException; +import org.apache.tuscany.spi.component.ScopeRegistry; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.model.Scope; + +import junit.framework.TestCase; +import org.apache.tuscany.core.component.WorkContextImpl; + +/** + * Verifies retrieval of standard scope contexts from the default scope registry + * + * @version $$Rev$$ $$Date$$ + */ +public class ScopeRegistryTestCase extends TestCase { + public void testScopeContextCreation() throws Exception { + WorkContext workContext = new WorkContextImpl(); + ScopeRegistry scopeRegistry = new ScopeRegistryImpl(workContext); + scopeRegistry.registerFactory(Scope.REQUEST, new RequestScopeObjectFactory()); + scopeRegistry.registerFactory(Scope.SESSION, new HttpSessionScopeObjectFactory(scopeRegistry)); + ScopeContainer request = scopeRegistry.getScopeContainer(Scope.REQUEST); + assertTrue(request instanceof RequestScopeContainer); + assertSame(request, scopeRegistry.getScopeContainer(Scope.REQUEST)); + ScopeContainer session = scopeRegistry.getScopeContainer(Scope.SESSION); + assertTrue(session instanceof HttpSessionScopeContainer); + assertSame(session, scopeRegistry.getScopeContainer(Scope.SESSION)); + assertNotSame(request, session); + } + + public void testDeregisterFactory() throws Exception { + WorkContext workContext = new WorkContextImpl(); + ScopeRegistry scopeRegistry = new ScopeRegistryImpl(workContext); + RequestScopeObjectFactory factory = new RequestScopeObjectFactory(); + scopeRegistry.registerFactory(Scope.REQUEST, factory); + scopeRegistry.deregisterFactory(Scope.REQUEST); + try { + scopeRegistry.getScopeContainer(Scope.REQUEST); + fail(); + } catch (ScopeNotFoundException e) { + // expected + } + } + + public void testScopeNotRegistered() throws Exception { + WorkContext workContext = new WorkContextImpl(); + ScopeRegistry scopeRegistry = new ScopeRegistryImpl(workContext); + try { + scopeRegistry.getScopeContainer(Scope.REQUEST); + fail(); + } catch (ScopeNotFoundException e) { + // expected + } + try { + scopeRegistry.getScopeContainer(Scope.SESSION); + fail(); + } catch (ScopeNotFoundException e) { + // expected + } + try { + scopeRegistry.getScopeContainer(Scope.STATELESS); + fail(); + } catch (ScopeNotFoundException e) { + // expected + } + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/StatelessScopeContainerTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/StatelessScopeContainerTestCase.java new file mode 100644 index 0000000000..c69ce63b8b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/StatelessScopeContainerTestCase.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.core.component.scope; + +import junit.framework.TestCase; + +/** + * @version $Rev$ $Date$ + */ +public class StatelessScopeContainerTestCase extends TestCase { + + public void testBadStopWithoutStart() throws Exception { + StatelessScopeContainer container = new StatelessScopeContainer(); + try { + container.stop(); + fail(); + } catch (IllegalStateException e) { + //expected + } + } + + public void testBadDoubleStart() throws Exception { + StatelessScopeContainer container = new StatelessScopeContainer(); + try { + container.start(); + container.start(); + fail(); + } catch (IllegalStateException e) { + //expected + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/StatelessScopeObjectFactoryTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/StatelessScopeObjectFactoryTestCase.java new file mode 100644 index 0000000000..75f1682713 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/StatelessScopeObjectFactoryTestCase.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.apache.tuscany.spi.component.ScopeRegistry; +import org.apache.tuscany.spi.model.Scope; + +import junit.framework.TestCase; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class StatelessScopeObjectFactoryTestCase extends TestCase { + + public void testCreation() { + ScopeRegistry registry = EasyMock.createMock(ScopeRegistry.class); + registry.registerFactory(EasyMock.isA(Scope.class), EasyMock.isA(StatelessScopeObjectFactory.class)); + assertNotNull(new StatelessScopeObjectFactory(registry).getInstance()); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/WorkContextTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/WorkContextTestCase.java new file mode 100644 index 0000000000..456bb5be78 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/component/scope/WorkContextTestCase.java @@ -0,0 +1,142 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.component.scope; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.WorkContext; + +import junit.framework.TestCase; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class WorkContextTestCase extends TestCase { + + public void testRemoteComponent() throws Exception { + WorkContext ctx = new WorkContextImpl(); + CompositeComponent component = EasyMock.createNiceMock(CompositeComponent.class); + CompositeComponent component2 = EasyMock.createNiceMock(CompositeComponent.class); + ctx.setRemoteComponent(component); + assertEquals(component, ctx.getRemoteComponent()); + ctx.setRemoteComponent(component2); + assertEquals(component2, ctx.getRemoteComponent()); + } + + public void testNonSetRemoteComponent() throws Exception { + WorkContext ctx = new WorkContextImpl(); + assertNull(ctx.getRemoteComponent()); + } + + public void testIndentifier() throws Exception { + WorkContext ctx = new WorkContextImpl(); + Object id = new Object(); + ctx.setIdentifier(this, id); + assertEquals(id, ctx.getIdentifier(this)); + } + + public void testClearIndentifier() throws Exception { + WorkContext ctx = new WorkContextImpl(); + Object id = new Object(); + ctx.setIdentifier(this, id); + ctx.clearIdentifier(this); + assertNull(ctx.getIdentifier(this)); + } + + public void testClearIndentifiers() throws Exception { + WorkContext ctx = new WorkContextImpl(); + Object id = new Object(); + Object id2 = new Object(); + ctx.setIdentifier(id, id); + ctx.setIdentifier(id2, id2); + ctx.clearIdentifiers(); + assertNull(ctx.getIdentifier(id)); + assertNull(ctx.getIdentifier(id2)); + } + + public void testClearNonExistentIndentifier() throws Exception { + WorkContext ctx = new WorkContextImpl(); + ctx.clearIdentifier(this); + } + + public void testNullIndentifier() throws Exception { + WorkContext ctx = new WorkContextImpl(); + Object id = new Object(); + ctx.setIdentifier(this, id); + ctx.clearIdentifier(null); + assertEquals(id, ctx.getIdentifier(this)); + } + + public void testNoIndentifier() throws Exception { + WorkContext ctx = new WorkContextImpl(); + assertNull(ctx.getIdentifier(this)); + } + + public void testSetGetMessageIds() { + WorkContext context = new WorkContextImpl(); + context.setCurrentMessageId("msg-009"); + context.setCurrentCorrelationId("msg-005"); + assertEquals(context.getCurrentMessageId(), "msg-009"); + assertEquals(context.getCurrentCorrelationId(), "msg-005"); + context.setCurrentMessageId(null); + context.setCurrentCorrelationId(null); + assertNull(context.getCurrentMessageId()); + assertNull(context.getCurrentCorrelationId()); + } + + public void testSetGetMessageIdsInNewThread() throws InterruptedException { + WorkContext context = new WorkContextImpl(); + context.setCurrentMessageId("msg-009"); + context.setCurrentCorrelationId("msg-005"); + assertEquals(context.getCurrentMessageId(), "msg-009"); + assertEquals(context.getCurrentCorrelationId(), "msg-005"); + context.setIdentifier("TX", "002"); + ChildThread t = new ChildThread(context); + t.start(); + t.join(); + assertTrue(t.passed); + context.setCurrentMessageId(null); + context.setCurrentCorrelationId(null); + assertNull(context.getCurrentMessageId()); + assertNull(context.getCurrentCorrelationId()); + } + + private static class ChildThread extends Thread { + private WorkContext context; + private boolean passed = true; + + private ChildThread(WorkContext context) { + this.context = context; + } + + @Override + public void run() { + try { + assertNull(context.getCurrentMessageId()); + assertNull(context.getCurrentCorrelationId()); + assertEquals("002", context.getIdentifier("TX")); + } catch (AssertionError e) { + passed = false; + } + } + + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DataBindingInterceptorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DataBindingInterceptorTestCase.java new file mode 100644 index 0000000000..720a3ef61e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DataBindingInterceptorTestCase.java @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.databinding.Mediator; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.easymock.EasyMock; + +/** + * + */ +public class DataBindingInterceptorTestCase extends TestCase { + private DataBindingInteceptor interceptor; + + /** + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + } + + @SuppressWarnings("unchecked") + public final void testInvoke() { + DataType<Class> type1 = new DataType<Class>("xml:string", String.class, String.class); + List<DataType<Class>> types1 = new ArrayList<DataType<Class>>(); + types1.add(type1); + DataType<List<DataType<Class>>> inputType1 = + new DataType<List<DataType<Class>>>("xml:string", Object[].class, types1); + + DataType<Class> type2 = new DataType<Class>("foo", Foo.class, Foo.class); + List<DataType<Class>> types2 = new ArrayList<DataType<Class>>(); + types2.add(type2); + DataType<List<DataType<Class>>> inputType2 = + new DataType<List<DataType<Class>>>("foo", Object[].class, types2); + + Operation<Class> operation1 = + new Operation<Class>("call", inputType1, type1, null, false, "xml:string"); + Operation<Class> operation2 = + new Operation<Class>("call", inputType2, type2, null, false, "org.w3c.dom.Node"); + + DataType<DataType> outputType1 = + new DataType<DataType>("idl:output", Object.class, operation1.getOutputType()); + DataType<DataType> outputType2 = + new DataType<DataType>("idl:output", Object.class, operation2.getOutputType()); + + OutboundWire outboundWire = EasyMock.createMock(OutboundWire.class); + InboundWire inboundWire = EasyMock.createMock(InboundWire.class); + CompositeComponent composite = EasyMock.createMock(CompositeComponent.class); + Component component = EasyMock.createMock(Component.class); + EasyMock.expect(component.getParent()).andReturn(composite).once(); + EasyMock.expect(outboundWire.getContainer()).andReturn(component); + EasyMock.replay(outboundWire, inboundWire, composite, component); + + interceptor = new DataBindingInteceptor(outboundWire, operation1, inboundWire, operation2); + Mediator mediator = createMock(Mediator.class); + Object[] source = new Object[] {"<foo>bar</foo>"}; + Foo foo = new Foo(); + foo.bar = "bar"; + Object[] target = new Object[] {foo}; + expect(mediator.mediate(EasyMock.same(source), + EasyMock.same(inputType1), + EasyMock.same(inputType2), + EasyMock.isA(Map.class))).andReturn(target); + // expect(mediator.mediate(target[0], type2, + // type1)).andReturn(source[0]); + expect(mediator.mediate(EasyMock.same(target[0]), + EasyMock.eq(outputType2), + EasyMock.eq(outputType1), + EasyMock.isA(Map.class))).andReturn(source[0]); + replay(mediator); + interceptor.setMediator(mediator); + Message msg = createMock(Message.class); + msg.setBody(EasyMock.anyObject()); + expectLastCall().anyTimes(); + expect(msg.getBody()).andReturn(source).once().andReturn(target[0]).once().andReturn(source[0]); + expect(msg.isFault()).andReturn(false).once(); + replay(msg); + Interceptor next = createMock(Interceptor.class); + expect(next.invoke(msg)).andReturn(msg); + replay(next); + interceptor.setNext(next); + interceptor.invoke(msg); + String result = (String)msg.getBody(); + Assert.assertEquals(source[0], result); + EasyMock.verify(mediator, msg, next); + } + + private static class Foo { + private String bar; + + public String getBar() { + return bar; + } + + public void setBar(String bar) { + this.bar = bar; + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DataBindingJavaInterfaceProcessorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DataBindingJavaInterfaceProcessorTestCase.java new file mode 100644 index 0000000000..6cbc8f01c2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DataBindingJavaInterfaceProcessorTestCase.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.api.annotation.DataContext; +import org.apache.tuscany.api.annotation.DataType; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.model.Operation; +import org.osoa.sca.annotations.Remotable; +import org.w3c.dom.Node; + +/** + * + */ +public class DataBindingJavaInterfaceProcessorTestCase extends TestCase { + + /** + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + } + + /** + * @throws InvalidServiceContractException + */ + public final void testVisitInterface() throws InvalidServiceContractException { + DataBindingJavaInterfaceProcessor processor = new DataBindingJavaInterfaceProcessor(); + JavaServiceContract contract = new JavaServiceContract(MockInterface.class); + Map<String, Operation<Type>> operations = new HashMap<String, Operation<Type>>(); + Operation<Type> operation = new Operation<Type>("call", null, null, null, false, null); + Operation<Type> operation1 = new Operation<Type>("call1", null, null, null, false, null); + operations.put("call", operation); + operations.put("call1", operation1); + contract.setOperations(operations); + processor.visitInterface(MockInterface.class, null, contract); + Assert.assertEquals("org.w3c.dom.Node", contract.getDataBinding()); + Assert.assertEquals("element", (String)contract.getMetaData().get("nodeType")); + Assert.assertEquals("org.w3c.dom.Node", contract.getOperations().get("call").getDataBinding()); + Assert.assertEquals("xml:string", contract.getOperations().get("call1").getDataBinding()); + } + + @DataType(name = "org.w3c.dom.Node", context = {@DataContext(key = "nodeType", value = "element")}) + @Remotable + public static interface MockInterface { + Node call(Node msg); + + @DataType(name = "xml:string") + String call1(String msg); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DataBindingLoaderTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DataBindingLoaderTestCase.java new file mode 100644 index 0000000000..6941e10a0c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DataBindingLoaderTestCase.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.core.databinding.impl; + +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.spi.loader.InvalidValueException; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.ModelObject; +import org.easymock.EasyMock; + +/** + * Testcase for DataBindingLoader + */ +public class DataBindingLoaderTestCase extends TestCase { + private XMLStreamReader reader; + + /** + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + } + + public final void testLoad() throws LoaderException, XMLStreamException { + reader = EasyMock.createMock(XMLStreamReader.class); + // EasyMock.expect(reader.getEventType()).andReturn(XMLStreamConstants.START_ELEMENT); + EasyMock.expect(reader.hasNext()).andReturn(true).anyTimes(); + EasyMock.expect(reader.getName()).andReturn(DataTypeLoader.DATA_BINDING); + EasyMock.expect(reader.getAttributeValue(null, "name")).andReturn("ABC"); + EasyMock.expect(reader.next()).andReturn(XMLStreamConstants.END_ELEMENT); + EasyMock.replay(reader); + + ModelObject mo = new DataTypeLoader(null).load(null, reader, null); + Assert.assertTrue(mo instanceof DataType); + Assert.assertEquals("ABC", ((DataType<?>)mo).getDataBinding()); + EasyMock.verify(reader); + + EasyMock.reset(reader); + + // EasyMock.expect(reader.getEventType()).andReturn(XMLStreamConstants.START_ELEMENT); + EasyMock.expect(reader.hasNext()).andReturn(true).anyTimes(); + EasyMock.expect(reader.getName()).andReturn(DataTypeLoader.DATA_BINDING); + EasyMock.expect(reader.getAttributeValue(null, "name")).andReturn(null); + EasyMock.expect(reader.next()).andReturn(XMLStreamConstants.END_ELEMENT); + EasyMock.replay(reader); + try { + mo = new DataTypeLoader(null).load(null, reader, null); + Assert.fail("InvalidValueException should have been thrown"); + } catch (InvalidValueException e) { + Assert.assertTrue(true); + } + EasyMock.verify(reader); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DataBindingRegistryImplTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DataBindingRegistryImplTestCase.java new file mode 100644 index 0000000000..30af31b1cb --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DataBindingRegistryImplTestCase.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.core.databinding.impl; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; + +import javax.xml.stream.XMLStreamReader; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.spi.databinding.DataBinding; +import org.apache.tuscany.spi.databinding.DataBindingRegistry; +import org.apache.tuscany.spi.model.DataType; +import org.easymock.EasyMock; +import org.xml.sax.ContentHandler; + +/** + * + */ +public class DataBindingRegistryImplTestCase extends TestCase { + private DataBindingRegistry registry; + + /** + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + registry = new DataBindingRegistryImpl(); + } + + public void testRegistry() { + DataBinding db1 = createMock(DataBinding.class); + expect(db1.getName()).andReturn(ContentHandler.class.getName()).anyTimes(); + DataType<Class> dataType1 = new DataType<Class>(ContentHandler.class, ContentHandler.class); + expect(db1.introspect(ContentHandler.class)).andReturn(dataType1); + expect(db1.introspect((Class)EasyMock.anyObject())).andReturn(null).anyTimes(); + replay(db1); + + registry.register(db1); + + DataBinding db2 = createMock(DataBinding.class); + expect(db2.getName()).andReturn(XMLStreamReader.class.getName()).anyTimes(); + DataType<Class> dataType2 = new DataType<Class>(XMLStreamReader.class, XMLStreamReader.class); + expect(db2.introspect(XMLStreamReader.class)).andReturn(dataType2); + expect(db2.introspect((Class)EasyMock.anyObject())).andReturn(null).anyTimes(); + replay(db2); + + registry.register(db2); + + String name = db1.getName(); + DataBinding db3 = registry.getDataBinding(name); + Assert.assertTrue(db1 == db3); + + DataType<?> dt = registry.introspectType(ContentHandler.class); + Assert.assertEquals(dataType1, dt); + Assert.assertTrue(dt.getDataBinding().equalsIgnoreCase(name)); + + registry.unregister(name); + DataBinding db4 = registry.getDataBinding(name); + Assert.assertNull(db4); + + dt = registry.introspectType(ContentHandler.class); + Assert.assertNull(dt); + + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DataBindingTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DataBindingTestCase.java new file mode 100644 index 0000000000..de5c537274 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DataBindingTestCase.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.core.databinding.impl; + +import java.lang.reflect.Method; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.api.annotation.DataContext; +import org.apache.tuscany.api.annotation.DataType; + +public class DataBindingTestCase extends TestCase { + @SuppressWarnings("unused") + public void testDataType() throws Exception { + Class<Test> testClass = Test.class; + DataType d = testClass.getAnnotation(DataType.class); + Assert.assertEquals(d.name(), "sdo"); + Assert.assertEquals(d.context().length, 0); + + Method method = testClass.getMethod("test", new Class[] {Object.class}); + DataType d2 = method.getAnnotation(DataType.class); + Assert.assertEquals(d2.name(), "jaxb"); + Assert.assertEquals(d2.context()[0].key(), "contextPath"); + Assert.assertEquals(d2.context()[0].value(), "com.example.ipo.jaxb"); + } + + @DataType(name = "sdo") + private static interface Test { + @DataType(name = "jaxb", context = {@DataContext(key = "contextPath", value = "com.example.ipo.jaxb")}) + Object test(Object object); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DataBindingWirePostProcessorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DataBindingWirePostProcessorTestCase.java new file mode 100644 index 0000000000..44ae07034f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DataBindingWirePostProcessorTestCase.java @@ -0,0 +1,231 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.Reference; +import org.apache.tuscany.spi.component.Service; +import org.apache.tuscany.spi.databinding.Mediator; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.easymock.EasyMock; +import org.w3c.dom.Node; + +/** + * + */ +public class DataBindingWirePostProcessorTestCase extends TestCase { + private DataBindingWirePostProcessor processor; + + /** + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + Mediator mediator = new MediatorImpl(); + this.processor = new DataBindingWirePostProcessor(mediator); + } + + public void testProcess1() { + InboundWire inboundWire = createMock(InboundWire.class); + OutboundWire outboundWire = createMock(OutboundWire.class); + + Component component = createMock(Component.class); + CompositeComponent composite = createMock(CompositeComponent.class); + expect(component.getParent()).andReturn(composite); + expect(inboundWire.getContainer()).andReturn(component); + expect(outboundWire.getContainer()).andReturn(component); + + Map<Operation<?>, OutboundInvocationChain> outboundChains = + new HashMap<Operation<?>, OutboundInvocationChain>(); + DataType<Type> type1 = new DataType<Type>(String.class, String.class); + List<DataType<Type>> types = new ArrayList<DataType<Type>>(); + types.add(type1); + DataType<List<DataType<Type>>> inputType1 = new DataType<List<DataType<Type>>>(Object[].class, types); + DataType<Type> outputType1 = new DataType<Type>(String.class, String.class); + Operation<Type> op1 = new Operation<Type>("test", inputType1, outputType1, null); + ServiceContract<Type> outboundContract = new JavaServiceContract(null); + outboundContract.setDataBinding(String.class.getName()); + op1.setServiceContract(outboundContract); + + OutboundInvocationChain outboundChain = createMock(OutboundInvocationChain.class); + outboundChains.put(op1, outboundChain); + expect(outboundWire.getInvocationChains()).andReturn(outboundChains); + outboundChain.addInterceptor(EasyMock.anyInt(), (Interceptor)EasyMock.anyObject()); + + Map<Operation<?>, InboundInvocationChain> inboundChains = + new HashMap<Operation<?>, InboundInvocationChain>(); + DataType<Type> type2 = new DataType<Type>(Node.class, Node.class); + List<DataType<Type>> types2 = new ArrayList<DataType<Type>>(); + types2.add(type2); + DataType<List<DataType<Type>>> inputType2 = + new DataType<List<DataType<Type>>>(Object[].class, types2); + DataType<Type> outputType2 = new DataType<Type>(String.class, String.class); + Operation<Type> op2 = new Operation<Type>("test", inputType2, outputType2, null); + ServiceContract<Type> inboundContract = new JavaServiceContract(null); + inboundContract.setDataBinding(Node.class.getName()); + op2.setServiceContract(inboundContract); + + InboundInvocationChain inboundChain = createMock(InboundInvocationChain.class); + inboundChains.put(op2, inboundChain); + expect(inboundWire.getInvocationChains()).andReturn(inboundChains); + + ServiceContract<Type> contract = new JavaServiceContract(); + Map<String, Operation<Type>> operations = Collections.emptyMap(); + contract.setCallbackOperations(operations); + expect(outboundWire.getServiceContract()).andReturn(contract); + + EasyMock.replay(composite, component, inboundWire, outboundWire, inboundChain, outboundChain); + + processor.process(outboundWire, inboundWire); + } + + public void testProcess2() { + InboundWire inboundWire = createMock(InboundWire.class); + OutboundWire outboundWire = createMock(OutboundWire.class); + + Reference reference = createMock(Reference.class); + CompositeComponent composite = createMock(CompositeComponent.class); + expect(reference.getParent()).andReturn(composite); + expect(inboundWire.getContainer()).andReturn(reference).anyTimes(); + expect(outboundWire.getContainer()).andReturn(reference).anyTimes(); + + Map<Operation<?>, OutboundInvocationChain> outboundChains = + new HashMap<Operation<?>, OutboundInvocationChain>(); + DataType<Type> type1 = new DataType<Type>(String.class, String.class); + List<DataType<Type>> types = new ArrayList<DataType<Type>>(); + types.add(type1); + DataType<List<DataType<Type>>> inputType1 = new DataType<List<DataType<Type>>>(Object[].class, types); + DataType<Type> outputType1 = new DataType<Type>(String.class, String.class); + Operation<Type> op1 = new Operation<Type>("test", inputType1, outputType1, null); + ServiceContract<Type> outboundContract = new JavaServiceContract(null); + outboundContract.setDataBinding(String.class.getName()); + op1.setServiceContract(outboundContract); + + OutboundInvocationChain outboundChain = createMock(OutboundInvocationChain.class); + outboundChains.put(op1, outboundChain); + expect(outboundWire.getInvocationChains()).andReturn(outboundChains).anyTimes(); + outboundChain.addInterceptor(EasyMock.anyInt(), (Interceptor)EasyMock.anyObject()); + + Map<Operation<?>, InboundInvocationChain> inboundChains = + new HashMap<Operation<?>, InboundInvocationChain>(); + DataType<Type> type2 = new DataType<Type>(Node.class, Node.class); + List<DataType<Type>> types2 = new ArrayList<DataType<Type>>(); + types2.add(type2); + DataType<List<DataType<Type>>> inputType2 = + new DataType<List<DataType<Type>>>(Object[].class, types2); + DataType<Type> outputType2 = new DataType<Type>(String.class, String.class); + Operation<Type> op2 = new Operation<Type>("test", inputType2, outputType2, null); + ServiceContract<Type> inboundContract = new JavaServiceContract(null); + inboundContract.setDataBinding(Node.class.getName()); + op2.setServiceContract(inboundContract); + + InboundInvocationChain inboundChain = createMock(InboundInvocationChain.class); + inboundChains.put(op2, inboundChain); + expect(inboundWire.getInvocationChains()).andReturn(inboundChains).anyTimes(); + + ServiceContract<Type> contract = new JavaServiceContract(); + Map<String, Operation<Type>> operations = Collections.emptyMap(); + contract.setCallbackOperations(operations); + expect(inboundWire.getServiceContract()).andReturn(contract); + expect(inboundChain.getTailInterceptor()).andReturn(null); + + EasyMock.replay(composite, reference, inboundWire, outboundWire, inboundChain, outboundChain); + + processor.process(inboundWire, outboundWire); + } + + public void testProcess3() { + InboundWire inboundWire = createMock(InboundWire.class); + OutboundWire outboundWire = createMock(OutboundWire.class); + + Service service = createMock(Service.class); + CompositeComponent composite = createMock(CompositeComponent.class); + expect(service.getParent()).andReturn(composite); + expect(inboundWire.getContainer()).andReturn(service).anyTimes(); + expect(outboundWire.getContainer()).andReturn(service).anyTimes(); + + Map<Operation<?>, OutboundInvocationChain> outboundChains = + new HashMap<Operation<?>, OutboundInvocationChain>(); + DataType<Type> type1 = new DataType<Type>(String.class, String.class); + List<DataType<Type>> types = new ArrayList<DataType<Type>>(); + types.add(type1); + DataType<List<DataType<Type>>> inputType1 = new DataType<List<DataType<Type>>>(Object[].class, types); + DataType<Type> outputType1 = new DataType<Type>(String.class, String.class); + Operation<Type> op1 = new Operation<Type>("test", inputType1, outputType1, null); + ServiceContract<Type> outboundContract = new JavaServiceContract(null); + outboundContract.setDataBinding(String.class.getName()); + op1.setServiceContract(outboundContract); + + OutboundInvocationChain outboundChain = createMock(OutboundInvocationChain.class); + outboundChains.put(op1, outboundChain); + expect(outboundWire.getInvocationChains()).andReturn(outboundChains).anyTimes(); + // outboundChain.addInterceptor(EasyMock.anyInt(), (Interceptor) + // EasyMock.anyObject()); + + Map<Operation<?>, InboundInvocationChain> inboundChains = + new HashMap<Operation<?>, InboundInvocationChain>(); + DataType<Type> type2 = new DataType<Type>(Node.class, Node.class); + List<DataType<Type>> types2 = new ArrayList<DataType<Type>>(); + types2.add(type2); + DataType<List<DataType<Type>>> inputType2 = + new DataType<List<DataType<Type>>>(Object[].class, types2); + DataType<Type> outputType2 = new DataType<Type>(String.class, String.class); + Operation<Type> op2 = new Operation<Type>("test", inputType2, outputType2, null); + ServiceContract<Type> inboundContract = new JavaServiceContract(null); + inboundContract.setDataBinding(Node.class.getName()); + op2.setServiceContract(inboundContract); + + InboundInvocationChain inboundChain = createMock(InboundInvocationChain.class); + inboundChains.put(op2, inboundChain); + expect(inboundWire.getInvocationChains()).andReturn(inboundChains).anyTimes(); + inboundChain.addInterceptor(EasyMock.anyInt(), (Interceptor)EasyMock.anyObject()); + + ServiceContract<Type> contract = new JavaServiceContract(); + Map<String, Operation<Type>> operations = Collections.emptyMap(); + contract.setCallbackOperations(operations); + expect(inboundWire.getServiceContract()).andReturn(contract); + + EasyMock.replay(composite, service, inboundWire, outboundWire, inboundChain, outboundChain); + + processor.process(inboundWire, outboundWire); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DirectedGraphTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DirectedGraphTestCase.java new file mode 100755 index 0000000000..70244df8e2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/DirectedGraphTestCase.java @@ -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.core.databinding.impl; + +import java.util.List; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.core.databinding.impl.DirectedGraph.Edge; +import org.apache.tuscany.core.databinding.impl.DirectedGraph.Vertex; + +public class DirectedGraphTestCase extends TestCase { + private DirectedGraph<String, Object> graph; + + protected void setUp() throws Exception { + super.setUp(); + graph = new DirectedGraph<String, Object>(); + graph.addEdge("a", "b", null, 3); + graph.addEdge("b", "c", null, 1); + graph.addEdge("a", "c", null, 8); + graph.addEdge("a", "d", null, 3); + graph.addEdge("b", "d", null, 2); + graph.addEdge("c", "b", null, 1); + graph.addEdge("c", "d", null, 2); + graph.addEdge("d", "b", null, 1); + graph.addEdge("a", "e", null, 8); + graph.addEdge("c", "c", null, 2); + } + + public void testGraph() { + // System.out.println(graph); + + Vertex vertex = graph.getVertex("a"); + Assert.assertNotNull(vertex); + Assert.assertEquals(vertex.getValue(), "a"); + + Assert.assertNull(graph.getVertex("1")); + + Edge edge = graph.getEdge("a", "b"); + Assert.assertNotNull(edge); + Assert.assertEquals(edge.getWeight(), 3); + + edge = graph.getEdge("b", "a"); + Assert.assertNull(edge); + + DirectedGraph<String, Object>.Path path = graph.getShortestPath("a", "c"); + + List<DirectedGraph<String, Object>.Edge> edges = path.getEdges(); + Assert.assertEquals(edges.size(), 2); + Assert.assertEquals(edges.get(0), graph.getEdge("a", "b")); + Assert.assertEquals(edges.get(1), graph.getEdge("b", "c")); + + Assert.assertEquals(path.getWeight(), 4); + + DirectedGraph<String, Object>.Path path2 = graph.getShortestPath("b", "e"); + Assert.assertNull(path2); + + DirectedGraph<String, Object>.Path path3 = graph.getShortestPath("a", "a"); + Assert.assertTrue(path3.getWeight() == 0 && path3.getEdges().isEmpty()); + + DirectedGraph<String, Object>.Path path4 = graph.getShortestPath("c", "c"); + Assert.assertTrue(path4.getWeight() == 2 && path4.getEdges().size() == 1); + + // System.out.println(path); + + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/IDLTransformerTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/IDLTransformerTestCase.java new file mode 100644 index 0000000000..abd15a1947 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/IDLTransformerTestCase.java @@ -0,0 +1,221 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.impl; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.namespace.QName; + +import junit.framework.TestCase; + +import org.apache.tuscany.core.databinding.xml.DOMDataBinding; +import org.apache.tuscany.core.databinding.xml.Node2Object; +import org.apache.tuscany.core.databinding.xml.Node2String; +import org.apache.tuscany.core.databinding.xml.Object2Node; +import org.apache.tuscany.core.databinding.xml.String2Node; +import org.apache.tuscany.spi.databinding.DataBindingRegistry; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.extension.DOMHelper; +import org.apache.tuscany.spi.databinding.extension.SimpleTypeMapperExtension; +import org.apache.tuscany.spi.idl.ElementInfo; +import org.apache.tuscany.spi.idl.TypeInfo; +import org.apache.tuscany.spi.idl.WrapperInfo; +import org.apache.tuscany.spi.model.DataType; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class IDLTransformerTestCase extends TestCase { + private static final String IPO_XML = + "<?xml version=\"1.0\"?>" + "<order1" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + + " xmlns:ipo=\"http://www.example.com/IPO\"" + + " xsi:schemaLocation=\"http://www.example.com/IPO ipo.xsd\"" + + " orderDate=\"1999-12-01\">" + + " <shipTo exportCode=\"1\" xsi:type=\"ipo:UKAddress\">" + + " <name>Helen Zoe</name>" + + " <street>47 Eden Street</street>" + + " <city>Cambridge</city>" + + " <postcode>CB1 1JR</postcode>" + + " </shipTo>" + + " <billTo xsi:type=\"ipo:USAddress\">" + + " <name>Robert Smith</name>" + + " <street>8 Oak Avenue</street>" + + " <city>Old Town</city>" + + " <state>PA</state>" + + " <zip>95819</zip>" + + " </billTo>" + + " <items>" + + " <item partNum=\"833-AA\">" + + " <productName>Lapis necklace</productName>" + + " <quantity>1</quantity>" + + " <USPrice>99.95</USPrice>" + + " <ipo:comment>Want this for the holidays</ipo:comment>" + + " <shipDate>1999-12-05</shipDate>" + + " </item>" + + " </items>" + + "</order1>"; + + private static final String OPERATION_KEY = org.apache.tuscany.spi.model.Operation.class.getName(); + + private static final String URI_ORDER_XSD = "http://example.com/order.xsd"; + + /** + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + } + + public void testTransform() throws Exception { + List<DataType<QName>> types0 = new ArrayList<DataType<QName>>(); + DataType<QName> wrapperType = + new DataType<QName>(null, Object.class, new QName(URI_ORDER_XSD, "checkOrderStatus")); + types0.add(wrapperType); + DataType<List<DataType<QName>>> inputType0 = + new DataType<List<DataType<QName>>>("idl:input", Object[].class, types0); + + List<DataType<QName>> types1 = new ArrayList<DataType<QName>>(); + DataType<QName> customerIdType = + new DataType<QName>(null, Object.class, new QName(URI_ORDER_XSD, "customerId")); + DataType<QName> orderType = + new DataType<QName>(null, Object.class, new QName(URI_ORDER_XSD, "order")); + DataType<QName> flagType = new DataType<QName>(null, Object.class, new QName(URI_ORDER_XSD, "flag")); + types1.add(customerIdType); + types1.add(orderType); + types1.add(flagType); + DataType<List<DataType<QName>>> inputType = + new DataType<List<DataType<QName>>>("idl:input", Object[].class, types1); + + DataType<QName> statusType = + new DataType<QName>(null, Object.class, new QName(URI_ORDER_XSD, "status")); + DataType<QName> responseType = + new DataType<QName>(null, Object.class, new QName(URI_ORDER_XSD, "checkOrderStatusResponse")); + + org.apache.tuscany.spi.model.Operation<QName> op = + new org.apache.tuscany.spi.model.Operation<QName>("checkOrderStatus", inputType0, responseType, + null); + op.setDataBinding(DOMDataBinding.NAME); + + inputType0.setMetadata(OPERATION_KEY, op); + op.setWrapperStyle(true); + ElementInfo inputElement = + new ElementInfo(new QName(URI_ORDER_XSD, "checkOrderStatus"), new TypeInfo(null, false, null)); + wrapperType.setMetadata(ElementInfo.class.getName(), inputElement); + + ElementInfo customerId = + new ElementInfo(new QName("", "customerId"), SimpleTypeMapperExtension.XSD_SIMPLE_TYPES + .get("string")); + ElementInfo order = + new ElementInfo(new QName("", "order"), new TypeInfo(new QName(URI_ORDER_XSD), false, null)); + ElementInfo flag = + new ElementInfo(new QName("", "flag"), SimpleTypeMapperExtension.XSD_SIMPLE_TYPES.get("int")); + + customerIdType.setMetadata(ElementInfo.class.getName(), customerId); + orderType.setMetadata(ElementInfo.class.getName(), order); + flagType.setMetadata(ElementInfo.class.getName(), flag); + + customerIdType.setMetadata(OPERATION_KEY, op); + orderType.setMetadata(OPERATION_KEY, op); + flagType.setMetadata(OPERATION_KEY, op); + + List<ElementInfo> inputElements = new ArrayList<ElementInfo>(); + inputElements.add(customerId); + inputElements.add(order); + inputElements.add(flag); + + ElementInfo statusElement = + new ElementInfo(new QName("", "status"), SimpleTypeMapperExtension.XSD_SIMPLE_TYPES.get("string")); + + statusType.setMetadata(ElementInfo.class.getName(), statusElement); + statusType.setMetadata(OPERATION_KEY, op); + + List<ElementInfo> outputElements = new ArrayList<ElementInfo>(); + outputElements.add(statusElement); + + ElementInfo outputElement = + new ElementInfo(new QName(URI_ORDER_XSD, "checkOrderStatusResponse"), new TypeInfo(null, false, + null)); + + responseType.setMetadata(ElementInfo.class.getName(), inputElement); + responseType.setMetadata(OPERATION_KEY, op); + + WrapperInfo wrapperInfo = + new WrapperInfo(inputElement, outputElement, inputElements, outputElements, inputType, statusType); + op.setWrapper(wrapperInfo); + op.setDataBinding(DOMDataBinding.NAME); + + MediatorImpl m = new MediatorImpl(); + TransformerRegistryImpl tr = new TransformerRegistryImpl(); + tr.registerTransformer(new String2Node()); + tr.registerTransformer(new Node2String()); + tr.registerTransformer(new Node2Object()); + tr.registerTransformer(new Object2Node()); + m.setTransformerRegistry(tr); + DataBindingRegistry dataBindingRegistry = new DataBindingRegistryImpl(); + dataBindingRegistry.register(new DOMDataBinding()); + m.setDataBindingRegistry(dataBindingRegistry); + + Object[] source = new Object[] {"cust001", IPO_XML, Integer.valueOf(1)}; + Input2InputTransformer t = new Input2InputTransformer(); + t.setDataBindingRegistry(dataBindingRegistry); + t.setMediator(m); + + TransformationContext context = new TransformationContextImpl(); + List<DataType<Class>> types = new ArrayList<DataType<Class>>(); + types.add(new DataType<Class>(Object.class.getName(), String.class, String.class)); + types.add(new DataType<Class>("java.lang.String", String.class, String.class)); + types.add(new DataType<Class>(Object.class.getName(), int.class, int.class)); + DataType<List<DataType<Class>>> inputType1 = + new DataType<List<DataType<Class>>>("idl:input", Object[].class, types); + context.setSourceDataType(inputType1); + context.setTargetDataType(op.getInputType()); + Object[] results = t.transform(source, context); + assertEquals(1, results.length); + assertTrue(results[0] instanceof Element); + Element element = (Element)results[0]; + assertEquals("http://example.com/order.xsd", element.getNamespaceURI()); + assertEquals("checkOrderStatus", element.getLocalName()); + + TransformationContext context1 = new TransformationContextImpl(); + DataType<DataType> sourceType = + new DataType<DataType>("idl:output", Object.class, op.getOutputType()); + sourceType.setMetadata(OPERATION_KEY, op.getOutputType().getMetadata(OPERATION_KEY)); + + context1.setSourceDataType(sourceType); + DataType<DataType> targetType = + new DataType<DataType>("idl:output", Object.class, + new DataType<Class>("java.lang.Object", String.class, String.class)); + context1.setTargetDataType(targetType); + + Document factory = DOMHelper.newDocument(); + Element responseElement = + factory.createElementNS("http://example.com/order.wsdl", "p:checkOrderStatusResponse"); + Element status = factory.createElement("status"); + responseElement.appendChild(status); + status.appendChild(factory.createTextNode("shipped")); + Output2OutputTransformer t2 = new Output2OutputTransformer(); + t2.setMediator(m); + t2.setDataBindingRegistry(dataBindingRegistry); + Object st = t2.transform(responseElement, context1); + assertEquals("shipped", st); + + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/MediatorImplTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/MediatorImplTestCase.java new file mode 100644 index 0000000000..3cb7f243a9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/MediatorImplTestCase.java @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.impl; + +import java.io.StringWriter; +import java.io.Writer; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.core.databinding.xml.Node2String; +import org.apache.tuscany.core.databinding.xml.Node2Writer; +import org.apache.tuscany.core.databinding.xml.SAX2DOMPipe; +import org.apache.tuscany.core.databinding.xml.String2SAX; +import org.apache.tuscany.spi.databinding.DataBindingRegistry; +import org.apache.tuscany.spi.databinding.TransformationContext; +import org.apache.tuscany.spi.databinding.TransformerRegistry; +import org.apache.tuscany.spi.model.DataType; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * Test case for MediatorImpl + */ +public class MediatorImplTestCase extends TestCase { + private static final String IPO_XML = + "<?xml version=\"1.0\"?>" + "<ipo:purchaseOrder" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + + " xmlns:ipo=\"http://www.example.com/IPO\"" + + " xsi:schemaLocation=\"http://www.example.com/IPO ipo.xsd\"" + + " orderDate=\"1999-12-01\">" + + " <shipTo exportCode=\"1\" xsi:type=\"ipo:UKAddress\">" + + " <name>Helen Zoe</name>" + + " <street>47 Eden Street</street>" + + " <city>Cambridge</city>" + + " <postcode>CB1 1JR</postcode>" + + " </shipTo>" + + " <billTo xsi:type=\"ipo:USAddress\">" + + " <name>Robert Smith</name>" + + " <street>8 Oak Avenue</street>" + + " <city>Old Town</city>" + + "<state>PA</state>" + + " <zip>95819</zip>" + + " </billTo>" + + " <items>" + + " <item partNum=\"833-AA\">" + + " <productName>Lapis necklace</productName>" + + " <quantity>1</quantity>" + + "<USPrice>99.95</USPrice>" + + " <ipo:comment>Want this for the holidays</ipo:comment>" + + " <shipDate>1999-12-05</shipDate>" + + " </item>" + + " </items>" + + "</ipo:purchaseOrder>"; + + private MediatorImpl mediator; + + protected void setUp() throws Exception { + super.setUp(); + + TransformerRegistry registry = new TransformerRegistryImpl(); + registry.registerTransformer(new String2SAX()); + registry.registerTransformer(new SAX2DOMPipe()); + registry.registerTransformer(new Node2String()); + registry.registerTransformer(new Node2Writer()); + + mediator = new MediatorImpl(); + mediator.setTransformerRegistry(registry); + + DataBindingRegistry dataBindingRegistry = new DataBindingRegistryImpl(); + mediator.setDataBindingRegistry(dataBindingRegistry); + } + + private TransformationContext createTransformationContext(Class sourceType, Class targetType) { + TransformationContext context = new TransformationContextImpl(); + DataType sourceDataType = new DataType<Class>(sourceType, sourceType); + DataType targetDataType = new DataType<Class>(targetType, targetType); + context.setSourceDataType(sourceDataType); + context.setTargetDataType(targetDataType); + return context; + } + + public void testTransform1() { + TransformationContext context = createTransformationContext(String.class, Node.class); + Object node = + mediator.mediate(IPO_XML, context.getSourceDataType(), context.getTargetDataType(), null); + Assert.assertTrue(node instanceof Document); + Element root = ((Document)node).getDocumentElement(); + Assert.assertEquals(root.getNamespaceURI(), "http://www.example.com/IPO"); + Assert.assertEquals(root.getLocalName(), "purchaseOrder"); + } + + public void testTransform2() { + TransformationContext context = createTransformationContext(String.class, Writer.class); + Writer writer = new StringWriter(); + mediator.mediate(IPO_XML, writer, context.getSourceDataType(), context.getTargetDataType(), null); + String str = writer.toString(); + Assert.assertTrue(str != null && str.indexOf("<shipDate>1999-12-05</shipDate>") != -1); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/TransformerRegistryImplTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/TransformerRegistryImplTestCase.java new file mode 100644 index 0000000000..6250efd897 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/impl/TransformerRegistryImplTestCase.java @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.impl; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; + +import java.util.List; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.spi.databinding.Transformer; +import org.apache.tuscany.spi.databinding.TransformerRegistry; + +/** + * + */ +public class TransformerRegistryImplTestCase extends TestCase { + private TransformerRegistry registry; + + /** + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + registry = new TransformerRegistryImpl(); + } + + public void testRegisterTransformer1() { + Transformer transformer = createMock(Transformer.class); + registry.registerTransformer("a", "b", 10, transformer); + Transformer t = registry.getTransformer("a", "b"); + Assert.assertSame(t, transformer); + } + + public void testRegisterTransformerTransformer() { + Transformer transformer = createMock(Transformer.class); + expect(transformer.getSourceDataBinding()).andReturn("a"); + expect(transformer.getTargetDataBinding()).andReturn("b"); + expect(transformer.getWeight()).andReturn(10); + replay(transformer); + registry.registerTransformer(transformer); + Transformer t = registry.getTransformer("a", "b"); + Assert.assertSame(t, transformer); + } + + public void testUnregisterTransformer() { + Transformer transformer = createMock(Transformer.class); + registry.registerTransformer("a", "b", 10, transformer); + boolean result = registry.unregisterTransformer("a", "b"); + Assert.assertTrue(result); + Transformer t = registry.getTransformer("a", "b"); + Assert.assertNull(t); + } + + public void testGetTransformerChain() { + Transformer t1 = createMock(Transformer.class); + expect(t1.getSourceDataBinding()).andReturn("a"); + expect(t1.getTargetDataBinding()).andReturn("b"); + expect(t1.getWeight()).andReturn(10); + replay(t1); + Transformer t2 = createMock(Transformer.class); + expect(t2.getSourceDataBinding()).andReturn("b"); + expect(t2.getTargetDataBinding()).andReturn("c"); + expect(t2.getWeight()).andReturn(20); + replay(t2); + + Transformer t3 = createMock(Transformer.class); + expect(t3.getSourceDataBinding()).andReturn("a"); + expect(t3.getTargetDataBinding()).andReturn("c"); + expect(t3.getWeight()).andReturn(120); + replay(t3); + + registry.registerTransformer(t1); + registry.registerTransformer(t2); + registry.registerTransformer(t3); + + List<Transformer> l1 = registry.getTransformerChain("a", "b"); + Assert.assertTrue(l1.size() == 1 && l1.get(0) == t1); + List<Transformer> l2 = registry.getTransformerChain("a", "c"); + Assert.assertTrue(l2.size() == 2 && l2.get(0) == t1 && l2.get(1) == t2); + List<Transformer> l3 = registry.getTransformerChain("a", "d"); + Assert.assertNull(l3); + + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/DOM2StAXTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/DOM2StAXTestCase.java new file mode 100644 index 0000000000..942b2d67e9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/DOM2StAXTestCase.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.stream.XMLStreamReader; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.w3c.dom.Node; + +public class DOM2StAXTestCase extends TestCase { + private static final String IPO_XML = + "<?xml version=\"1.0\"?>" + "<ipo:purchaseOrder" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + + " xmlns:ipo=\"http://www.example.com/IPO\"" + + " xsi:schemaLocation=\"http://www.example.com/IPO ipo.xsd\"" + + " orderDate=\"1999-12-01\">" + + " <shipTo exportCode=\"1\" xsi:type=\"ipo:UKAddress\">" + + " <name>Helen Zoe</name>" + + " <street>47 Eden Street</street>" + + " <city>Cambridge</city>" + + " <postcode>CB1 1JR</postcode>" + + " </shipTo>" + + " <billTo xsi:type=\"ipo:USAddress\">" + + " <name>Robert Smith</name>" + + " <street>8 Oak Avenue</street>" + + " <city>Old Town</city>" + + " <state>PA</state>" + + " <zip>95819</zip>" + + " </billTo>" + + " <items>" + + " <item partNum=\"833-AA\">" + + " <productName>Lapis necklace</productName>" + + " <quantity>1</quantity>" + + " <USPrice>99.95</USPrice>" + + " <ipo:comment>Want this for the holidays</ipo:comment>" + + " <shipDate>1999-12-05</shipDate>" + + " </item>" + + " </items>" + + "</ipo:purchaseOrder>"; + + /** + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + } + + public void testTransformation() { + String2Node t1 = new String2Node(); + Node node = t1.transform(IPO_XML, null); + Node2XMLStreamReader t2 = new Node2XMLStreamReader(); + XMLStreamReader reader = t2.transform(node, null); + XMLStreamReader2String t3 = new XMLStreamReader2String(); + String xml = t3.transform(reader, null); + Assert.assertTrue(xml != null && xml.indexOf("<shipDate>1999-12-05</shipDate>") != -1); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/DataPipeTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/DataPipeTestCase.java new file mode 100644 index 0000000000..d4eaf9b2a9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/DataPipeTestCase.java @@ -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.core.databinding.xml; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.core.databinding.impl.PipedTransformer; +import org.apache.tuscany.spi.databinding.extension.DOMHelper; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * Test case for DataPipe + */ +public class DataPipeTestCase extends TestCase { + + public final void testStreamPipe() throws IOException { + byte[] bytes = new byte[] {1, 2, 3}; + StreamDataPipe pipe = new StreamDataPipe(); + Assert.assertSame(OutputStream.class, pipe.getSourceType()); + Assert.assertSame(InputStream.class, pipe.getTargetType()); + OutputStream os = pipe.getSink(); + os.write(bytes); + byte[] newBytes = new byte[16]; + int count = pipe.getResult().read(newBytes); + Assert.assertEquals(3, count); + for (int i = 0; i < bytes.length; i++) { + Assert.assertEquals(bytes[i], newBytes[i]); + } + } + + public final void testWriter2ReaderPipe() throws IOException { + String str = "ABC"; + Writer2ReaderDataPipe pipe = new Writer2ReaderDataPipe(); + Assert.assertSame(Writer.class, pipe.getSourceType()); + Assert.assertSame(Reader.class, pipe.getTargetType()); + pipe.getSink().write(str); + char[] buf = new char[16]; + int count = pipe.getResult().read(buf); + Assert.assertEquals(3, count); + for (int i = 0; i < str.length(); i++) { + Assert.assertEquals(str.charAt(i), buf[i]); + } + } + + public final void testPiped() throws Exception { + Node2Writer node2Writer = new Node2Writer(); + Writer2ReaderDataPipe pipe = new Writer2ReaderDataPipe(); + PipedTransformer<Node, Writer, Reader> transformer = + new PipedTransformer<Node, Writer, Reader>(node2Writer, pipe); + Document document = DOMHelper.newDocument(); + Element element = document.createElementNS("http://ns1", "root"); + document.appendChild(element); + Reader reader = transformer.transform(document, null); + Assert.assertEquals(transformer.getWeight(), node2Writer.getWeight() + pipe.getWeight()); + Assert.assertEquals(transformer.getSourceDataBinding(), node2Writer.getSourceDataBinding()); + Assert.assertEquals(transformer.getTargetDataBinding(), pipe.getTargetDataBinding()); + char[] buf = new char[120]; + int count = reader.read(buf); + String xml = new String(buf, 0, count); + Assert.assertTrue(xml.contains("<root xmlns=\"http://ns1\"/>")); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/Node2StringTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/Node2StringTestCase.java new file mode 100755 index 0000000000..9b9aa3b893 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/Node2StringTestCase.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import junit.framework.TestCase; + +import org.apache.tuscany.spi.databinding.extension.DOMHelper; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class Node2StringTestCase extends TestCase { + public void testTransformation() throws Exception { + Document document = DOMHelper.newDocument(); + Element element = document.createElementNS("http://ns1", "test"); + document.appendChild(element); + + new Node2String().transform(document, null); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/PushTransformationTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/PushTransformationTestCase.java new file mode 100644 index 0000000000..a2318b2faa --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/PushTransformationTestCase.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.databinding.xml; + +import javax.xml.stream.XMLStreamReader; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.tuscany.core.databinding.impl.PipedTransformer; +import org.w3c.dom.Node; +import org.xml.sax.ContentHandler; + +public class PushTransformationTestCase extends TestCase { + private static final String IPO_XML = + "<?xml version=\"1.0\"?>" + "<ipo:purchaseOrder" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + + " xmlns:ipo=\"http://www.example.com/IPO\"" + + " xsi:schemaLocation=\"http://www.example.com/IPO ipo.xsd\"" + + " orderDate=\"1999-12-01\">" + + " <shipTo exportCode=\"1\" xsi:type=\"ipo:UKAddress\">" + + " <name>Helen Zoe</name>" + + " <street>47 Eden Street</street>" + + " <city>Cambridge</city>" + + " <postcode>CB1 1JR</postcode>" + + " </shipTo>" + + " <billTo xsi:type=\"ipo:USAddress\">" + + " <name>Robert Smith</name>" + + " <street>8 Oak Avenue</street>" + + " <city>Old Town</city>" + + " <state>PA</state>" + + " <zip>95819</zip>" + + " </billTo>" + + " <items>" + + " <item partNum=\"833-AA\">" + + " <productName>Lapis necklace</productName>" + + " <quantity>1</quantity>" + + " <USPrice>99.95</USPrice>" + + " <ipo:comment>Want this for the holidays</ipo:comment>" + + " <shipDate>1999-12-05</shipDate>" + + " </item>" + + " </items>" + + "</ipo:purchaseOrder>"; + + /** + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + } + + public void testTransformation() { + String2XMLStreamReader t1 = new String2XMLStreamReader(); + XMLStreamReader reader = t1.transform(IPO_XML, null); + XMLStreamReader2SAX t2 = new XMLStreamReader2SAX(); + PipedTransformer<XMLStreamReader, ContentHandler, Node> t3 = + new PipedTransformer<XMLStreamReader, ContentHandler, Node>(t2, new SAX2DOMPipe()); + Node node = t3.transform(reader, null); + Assert.assertNotNull(node); + Node2String t4 = new Node2String(); + String xml = t4.transform(node, null); + Assert.assertTrue(xml != null && xml.indexOf("<shipDate>1999-12-05</shipDate>") != -1); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/StAXHelperTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/StAXHelperTestCase.java new file mode 100644 index 0000000000..7d18e83ac6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/StAXHelperTestCase.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.core.databinding.xml; + +import javax.xml.stream.XMLStreamReader; + +import junit.framework.TestCase; + +/** + * Test Case for StAXHelper + */ +public class StAXHelperTestCase extends TestCase { + private static final String XML = + "<a:foo xmlns:a='http://a' name='foo'><bar name='bar'>" + "<doo a:name='doo' xmlns:a='http://doo'/>" + + "</bar></a:foo>"; + + /** + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + } + + public void testHelper() throws Exception { + XMLStreamReader reader = StAXHelper.createXMLStreamReader(XML); + String xml = StAXHelper.save(reader); + reader = StAXHelper.createXMLStreamReader(xml); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/TraxTransformerTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/TraxTransformerTestCase.java new file mode 100644 index 0000000000..7e9494d423 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/TraxTransformerTestCase.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.databinding.xml; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import java.net.URL; + +import junit.framework.TestCase; + +import org.w3c.dom.Node; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * + */ +public class TraxTransformerTestCase extends TestCase { + private URL url; + + /** + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + url = getClass().getResource("foo.xml"); + } + + public void testTransformDOM() throws IOException { + InputStream is = url.openStream(); + InputStream2Node t1 = new InputStream2Node(); + Node node = t1.transform(is, null); + is.close(); + Writer writer = new StringWriter(); + Node2Writer t2 = new Node2Writer(); + t2.transform(node, writer, null); + String str = writer.toString(); + StringReader reader = new StringReader(str); + Reader2Node t3 = new Reader2Node(); + node = t3.transform(reader, null); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + Node2OutputStream t4 = new Node2OutputStream(); + t4.transform(node, os, null); + InputSource inputSource = new InputSource(new ByteArrayInputStream(os.toByteArray())); + InputSource2Node t5 = new InputSource2Node(); + node = t5.transform(inputSource, null); + } + + public void testTransformSAX() throws IOException { + MyContentHandler handler = new MyContentHandler(); + InputStream is = url.openStream(); + InputStream2SAX t1 = new InputStream2SAX(); + t1.transform(is, handler, null); + is.close(); + + String xml = "<foo xmlns=\"http://foo\">bar</foo>"; + + InputSource inputSource = new InputSource(new StringReader(xml)); + InputSource2SAX t2 = new InputSource2SAX(); + MyContentHandler handler2 = new MyContentHandler(); + t2.transform(inputSource, handler2, null); + + } + + private static class MyContentHandler extends DefaultHandler { + + @Override + public void startElement(String namespaceURI, String localName, String qName, Attributes atts) + throws SAXException { + super.startElement(namespaceURI, localName, qName, atts); + } + + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/deployer/BootstrapDeployerTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/deployer/BootstrapDeployerTestCase.java new file mode 100644 index 0000000000..f988c5d3a4 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/deployer/BootstrapDeployerTestCase.java @@ -0,0 +1,163 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.deployer; + +import java.net.URL; +import java.util.Map; +import javax.xml.stream.XMLInputFactory; + +import org.apache.tuscany.spi.component.Component; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.SCAObject; +import org.apache.tuscany.spi.deployer.Deployer; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.model.BoundServiceDefinition; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.ComponentType; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.Implementation; +import org.apache.tuscany.spi.model.Include; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.model.PropertyValue; +import org.apache.tuscany.spi.model.ReferenceDefinition; +import org.apache.tuscany.spi.model.ServiceDefinition; + +import junit.framework.TestCase; +import org.apache.tuscany.core.bootstrap.Bootstrapper; +import org.apache.tuscany.core.bootstrap.DefaultBootstrapper; +import org.apache.tuscany.core.implementation.system.model.SystemBinding; +import org.apache.tuscany.core.implementation.system.model.SystemCompositeImplementation; +import org.apache.tuscany.core.mock.component.BasicInterface; +import org.apache.tuscany.core.monitor.NullMonitorFactory; +import static org.easymock.EasyMock.createNiceMock; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Verifies the default boostrap deployer + * + * @version $Rev$ $Date$ + */ +public class BootstrapDeployerTestCase extends TestCase { + private DeployerImpl deployer; + private DeploymentContext deploymentContext; + private ComponentDefinition<SystemCompositeImplementation> componentDefinition; + private SystemCompositeImplementation implementation; + + public void testBoot1Load() throws LoaderException { + CompositeComponent parent = createNiceMock(CompositeComponent.class); + URL scdl = BootstrapDeployerTestCase.class.getResource("boot1.scdl"); + implementation.setScdlLocation(scdl); + deployer.load(parent, componentDefinition, deploymentContext); + CompositeComponentType<ServiceDefinition, ReferenceDefinition, Property<?>> composite = + implementation.getComponentType(); + assertNotNull(composite); + assertEquals("boot1", composite.getName()); + + // check parse of <service> + Map<String, ServiceDefinition> services = composite.getDeclaredServices(); + assertEquals(1, services.size()); // included doesn't count + services = composite.getServices(); + assertEquals(2, services.size()); // included counts + BoundServiceDefinition serviceDefinition = (BoundServiceDefinition) services.get("service"); + assertNotNull(serviceDefinition); + assertEquals("service", serviceDefinition.getName()); + assertEquals(BasicInterface.class, serviceDefinition.getServiceContract().getInterfaceClass()); + assertTrue(serviceDefinition.getBinding() instanceof SystemBinding); + + // check parse of <component> + Map<String, ComponentDefinition<? extends Implementation<?>>> components = composite.getDeclaredComponents(); + assertEquals(1, components.size()); // included doesn't count + components = composite.getComponents(); + assertEquals(2, components.size()); // included counts + ComponentDefinition<? extends Implementation<?>> component = components.get("component"); + assertNotNull(component); + PropertyValue<?> propVal = component.getPropertyValues().get("publicProperty"); + assertEquals("propval", propVal.getValueFactory().getInstance()); + + // check introspection of implementation + ComponentType<?, ?, ?> componentType = component.getImplementation().getComponentType(); + assertNotNull(componentType); // details checked in SystemComponentTypeLoaderTestCase + + // check included component + Map<String, Include> includes = composite.getIncludes(); + assertEquals(1, includes.size()); + Include include = includes.get("boot1-include"); + assertNotNull(include); + CompositeComponentType included = include.getIncluded(); + assertNotNull(included); + assertEquals(1, included.getComponents().size()); + } + + public void testBoot1Deployment() throws LoaderException { + URL scdl = BootstrapDeployerTestCase.class.getResource("boot1.scdl"); + implementation.setScdlLocation(scdl); + CompositeComponent parent = createNiceMock(CompositeComponent.class); + parent.register(isA(SCAObject.class)); + replay(parent); + // load the boot1 file using the bootstrap deployer + componentDefinition.setName("simple"); + Component component = deployer.deploy(parent, componentDefinition); + assertNotNull(component); + verify(parent); + } + + public void testBoot2Deployment() throws LoaderException { + URL scdl = BootstrapDeployerTestCase.class.getResource("boot2.scdl"); + implementation.setScdlLocation(scdl); + CompositeComponent parent = createNiceMock(CompositeComponent.class); + parent.register(isA(SCAObject.class)); + replay(parent); + + // load the boot2 file using the bootstrap deployer + componentDefinition.setName("newDeployer"); + CompositeComponent component = (CompositeComponent) deployer.deploy(parent, componentDefinition); + assertNotNull(component); + verify(parent); + component.start(); + Deployer newDeployer = (Deployer) component.getSystemServiceInstance("deployer"); + assertNotNull(newDeployer); + +/* // FIXME + // load the boot2 file using the newly loaded deployer + parent.reset(); + parent.expects(once()).method("register").withAnyArguments(); + componentDefinition.setName("newDeployer2"); + component = newDeployer.deploy((CompositeComponent) parent.proxy(), componentDefinition); + assertNotNull(component); + parent.verify(); + component.start(); + Deployer newDeployer2 = (Deployer) component.getServiceInstance("deployer"); + assertNotNull(newDeployer2); +*/ + } + + protected void setUp() throws Exception { + super.setUp(); + XMLInputFactory xmlFactory = XMLInputFactory.newInstance(); + Bootstrapper bootstrapper = new DefaultBootstrapper(new NullMonitorFactory(), xmlFactory); + deployer = (DeployerImpl) bootstrapper.createDeployer(); + deploymentContext = new RootDeploymentContext(null, xmlFactory, null, null); + implementation = new SystemCompositeImplementation(); + implementation.setClassLoader(getClass().getClassLoader()); + componentDefinition = new ComponentDefinition<SystemCompositeImplementation>(implementation); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/idl/java/JavaInterfaceProcessorRegistryImplTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/idl/java/JavaInterfaceProcessorRegistryImplTestCase.java new file mode 100644 index 0000000000..e3a7deb10a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/idl/java/JavaInterfaceProcessorRegistryImplTestCase.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.idl.java; + +import java.lang.reflect.Type; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessor; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.model.DataType; +import org.apache.tuscany.spi.model.Operation; + +import junit.framework.TestCase; +import org.apache.tuscany.core.util.JavaIntrospectionHelper; +import org.easymock.EasyMock; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * @version $Rev$ $Date$ + */ +public class JavaInterfaceProcessorRegistryImplTestCase extends TestCase { + private JavaInterfaceProcessorRegistryImpl impl; + + public void testSimpleInterface() throws InvalidServiceContractException { + JavaServiceContract contract = impl.introspect(Simple.class); + // TODO spec to clairfy interface name + assertEquals(JavaIntrospectionHelper.getBaseName(Simple.class), contract.getInterfaceName()); + assertEquals(Simple.class, contract.getInterfaceClass()); + Map<String, Operation<Type>> operations = contract.getOperations(); + assertEquals(1, operations.size()); + Operation<Type> baseInt = operations.get("baseInt"); + assertNotNull(baseInt); + + DataType<Type> returnType = baseInt.getOutputType(); + assertEquals(Integer.TYPE, returnType.getPhysical()); + assertEquals(Integer.TYPE, returnType.getLogical()); + + List<DataType<Type>> parameterTypes = baseInt.getInputType().getLogical(); + assertEquals(1, parameterTypes.size()); + DataType<Type> arg0 = parameterTypes.get(0); + assertEquals(Integer.TYPE, arg0.getPhysical()); + assertEquals(Integer.TYPE, arg0.getLogical()); + + List<DataType<Type>> faultTypes = baseInt.getFaultTypes(); + assertEquals(1, faultTypes.size()); + DataType<Type> fault0 = faultTypes.get(0); + assertEquals(IllegalArgumentException.class, fault0.getPhysical()); + assertEquals(IllegalArgumentException.class, fault0.getLogical()); + } + + public void testUnregister() throws Exception { + JavaInterfaceProcessor processor = createMock(JavaInterfaceProcessor.class); + processor.visitInterface(eq(Base.class), EasyMock.same((Class)null), isA(JavaServiceContract.class)); + expectLastCall().once(); + replay(processor); + impl.registerProcessor(processor); + impl.introspect(Base.class); + impl.unregisterProcessor(processor); + impl.introspect(Base.class); + verify(processor); + } + + protected void setUp() throws Exception { + super.setUp(); + impl = new JavaInterfaceProcessorRegistryImpl(); + + } + + private static interface Base { + int baseInt(int param) throws IllegalArgumentException; + } + + private static interface Simple extends Base { + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/IntrospectionRegistryTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/IntrospectionRegistryTestCase.java new file mode 100644 index 0000000000..fb5e7fbb1f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/IntrospectionRegistryTestCase.java @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation; + +import java.lang.reflect.Method; +import java.lang.reflect.Field; +import java.lang.reflect.Constructor; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessor; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; + +import junit.framework.TestCase; +import org.apache.tuscany.core.implementation.IntrospectionRegistryImpl.Monitor; +import org.apache.tuscany.core.monitor.NullMonitorFactory; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class IntrospectionRegistryTestCase extends TestCase { + + private Monitor monitor; + + public void testRegister() throws Exception { + IntrospectionRegistryImpl registry = new IntrospectionRegistryImpl(monitor); + ImplementationProcessor processor = EasyMock.createNiceMock(ImplementationProcessor.class); + registry.registerProcessor(processor); + } + + public void testUnegister() throws Exception { + IntrospectionRegistryImpl registry = new IntrospectionRegistryImpl(monitor); + ImplementationProcessor processor = EasyMock.createNiceMock(ImplementationProcessor.class); + registry.registerProcessor(processor); + registry.unregisterProcessor(processor); + } + + @SuppressWarnings("unchecked") + public void testWalk() throws Exception { + IntrospectionRegistryImpl registry = new IntrospectionRegistryImpl(monitor); + ImplementationProcessor processor = EasyMock.createMock(ImplementationProcessor.class); + processor.visitClass(EasyMock.isA(CompositeComponent.class), + EasyMock.eq(Bar.class), + EasyMock.isA(PojoComponentType.class), + EasyMock.isA(DeploymentContext.class)); + processor.visitConstructor(EasyMock.isA(CompositeComponent.class), + EasyMock.isA(Constructor.class), + EasyMock.isA(PojoComponentType.class), + EasyMock.isA(DeploymentContext.class)); + processor.visitMethod(EasyMock.isA(CompositeComponent.class), + EasyMock.isA(Method.class), + EasyMock.isA(PojoComponentType.class), + EasyMock.isA(DeploymentContext.class)); + processor.visitField(EasyMock.isA(CompositeComponent.class), + EasyMock.isA(Field.class), + EasyMock.isA(PojoComponentType.class), + EasyMock.isA(DeploymentContext.class)); + processor.visitSuperClass(EasyMock.isA(CompositeComponent.class), + EasyMock.isA(Class.class), + EasyMock.isA(PojoComponentType.class), + EasyMock.isA(DeploymentContext.class)); + processor.visitEnd(EasyMock.isA(CompositeComponent.class), + EasyMock.isA(Class.class), + EasyMock.isA(PojoComponentType.class), + EasyMock.isA(DeploymentContext.class)); + + // mock.expects(once()).method("visitClass"); +// mock.expects(once()).method("visitMethod"); +// mock.expects(once()).method("visitField"); +// mock.expects(once()).method("visitConstructor"); +// mock.expects(once()).method("visitSuperClass"); +// mock.expects(once()).method("visitEnd"); + EasyMock.replay(processor); + registry.registerProcessor(processor); + registry.introspect(EasyMock.createNiceMock(CompositeComponent.class), + Bar.class, + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(), + EasyMock.createNiceMock(DeploymentContext.class)); + EasyMock.verify(processor); + } + + + protected void setUp() throws Exception { + super.setUp(); + monitor = new NullMonitorFactory().getMonitor(Monitor.class); + } + + private class Baz { + + } + + private class Bar extends Baz { + + protected String bar; + + public Bar() { + } + + public void bar() { + } + + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/AutowireResolutionTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/AutowireResolutionTestCase.java new file mode 100644 index 0000000000..7d9e2a75ee --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/AutowireResolutionTestCase.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import org.apache.tuscany.spi.component.CompositeComponent; + +import junit.framework.TestCase; +import org.easymock.EasyMock; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * Verfies specific autowire resolution scenarios + * + * @version $Rev$ $Date$ + */ +public class AutowireResolutionTestCase extends TestCase { + + public void testConstruction() { + CompositeComponent parent = createMock(CompositeComponent.class); + replay(parent); + CompositeComponent component = new CompositeComponentImpl("test", parent, null, null); + assertEquals("test", component.getName()); + assertSame(parent, component.getParent()); + verify(parent); + } + + public void testResolveToSelf() { + CompositeComponent parent = createMock(CompositeComponent.class); + replay(parent); + CompositeComponent component = new CompositeComponentImpl("test", parent, null, null); + assertSame(component, component.resolveInstance(CompositeComponent.class)); + verify(parent); + } + + public void testSystemResolveToSelf() { + CompositeComponent parent = createMock(CompositeComponent.class); + replay(parent); + CompositeComponent component = new CompositeComponentImpl("test", parent, null, null); + assertSame(component, component.resolveSystemInstance(CompositeComponent.class)); + verify(parent); + } + + public void testResolvedByAutowire() { + Foo foo = new Foo() { + }; + CompositeComponent parent = createMock(CompositeComponent.class); + EasyMock.expect(parent.resolveInstance(eq(Foo.class))).andReturn(foo); + replay(parent); + CompositeComponent component = new CompositeComponentImpl("test", parent, null, null); + assertSame(foo, component.resolveInstance(Foo.class)); + verify(parent); + } + + public void testSystemResolvedByAutowire() { + Foo foo = new Foo() { + }; + CompositeComponent parent = createMock(CompositeComponent.class); + EasyMock.expect(parent.resolveSystemInstance(eq(Foo.class))).andReturn(foo); + replay(parent); + CompositeComponent component = new CompositeComponentImpl("test", parent, null, null); + assertSame(foo, component.resolveSystemInstance(Foo.class)); + verify(parent); + } + + /** + * Verify parent resolution strategy for application services + */ + public void testNamespaceIsolationAutowire() { + Foo foo = new Foo() { + }; + CompositeComponent parent = new CompositeComponentImpl("parent", null, null, null); + parent.registerJavaObject("foo", Foo.class, foo); + CompositeComponent component = new CompositeComponentImpl("test", parent, null, null); + assertNull(component.resolveInstance(Foo.class)); + } + + protected void setUp() throws Exception { + super.setUp(); + } + + public static interface Foo { + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/AutowireTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/AutowireTestCase.java new file mode 100644 index 0000000000..d565777cd2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/AutowireTestCase.java @@ -0,0 +1,231 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.Reference; +import org.apache.tuscany.spi.component.Service; +import org.apache.tuscany.spi.component.SystemAtomicComponent; + +import junit.framework.TestCase; +import org.apache.tuscany.core.implementation.system.component.SystemReference; +import org.apache.tuscany.core.implementation.system.component.SystemService; +import org.easymock.EasyMock; + +/** + * Performs basic autowiring tests to composite artifacts + * + * @version $$Rev$$ $$Date$$ + */ +public class AutowireTestCase extends TestCase { + + /** + * Tests autowiring to an system atomic component + */ + public void testSystemAtomicAutowire() throws Exception { + CompositeComponent parent = new CompositeComponentImpl("parent", null, null, null); + parent.start(); + + List<Class<?>> interfaces = new ArrayList<Class<?>>(); + interfaces.add(Source.class); + interfaces.add(Source2.class); + Source originalSource = new SourceImpl(); + SystemAtomicComponent component = EasyMock.createMock(SystemAtomicComponent.class); + EasyMock.expect(component.getName()).andReturn("source").atLeastOnce(); + EasyMock.expect(component.getServiceInstance()).andReturn(originalSource).atLeastOnce(); + EasyMock.expect(component.getServiceInterfaces()).andReturn(interfaces); + EasyMock.expect(component.isSystem()).andReturn(true).atLeastOnce(); + + EasyMock.replay(component); + parent.register(component); + + Source source = parent.resolveSystemInstance(Source.class); + assertNotNull(source); + Source2 source2 = parent.resolveSystemInstance(Source2.class); + assertSame(source, source2); + assertNull(parent.resolveSystemExternalInstance(Source.class)); + EasyMock.verify(component); + } + + /** + * Tests autowiring to an system atomic component + */ + public void testAtomicAutowire() throws Exception { + CompositeComponent parent = new CompositeComponentImpl("parent", null, null, null); + parent.start(); + + List<Class<?>> interfaces = new ArrayList<Class<?>>(); + interfaces.add(Source.class); + interfaces.add(Source2.class); + Source originalSource = new SourceImpl(); + AtomicComponent component = EasyMock.createMock(AtomicComponent.class); + EasyMock.expect(component.getName()).andReturn("source").atLeastOnce(); + EasyMock.expect(component.getServiceInstance()).andReturn(originalSource).atLeastOnce(); + EasyMock.expect(component.getServiceInterfaces()).andReturn(interfaces); + EasyMock.expect(component.isSystem()).andReturn(false).atLeastOnce(); + + EasyMock.replay(component); + parent.register(component); + + Source source = parent.resolveInstance(Source.class); + assertNotNull(source); + Source2 source2 = parent.resolveInstance(Source2.class); + assertSame(source, source2); + assertNull(parent.resolveExternalInstance(Source.class)); + EasyMock.verify(component); + } + + /** + * Tests autowiring to a system service which is wired to an atomic component. + */ + public void testSystemServiceAutowire() throws Exception { + CompositeComponent parent = new CompositeComponentImpl("parent", null, null, null); + parent.start(); + + List<Class<?>> interfaces = new ArrayList<Class<?>>(); + interfaces.add(Source.class); + interfaces.add(Source2.class); + + Source serviceSource = new SourceImpl(); + SystemService component = EasyMock.createMock(SystemService.class); + EasyMock.expect(component.getName()).andReturn("service").atLeastOnce(); + component.getInterface(); + EasyMock.expectLastCall().andReturn(Source.class).atLeastOnce(); + EasyMock.expect(component.isSystem()).andReturn(true).atLeastOnce(); + EasyMock.expect(component.getServiceInstance()).andReturn(serviceSource); + EasyMock.replay(component); + parent.register(component); + + + SystemAtomicComponent component2 = EasyMock.createMock(SystemAtomicComponent.class); + EasyMock.expect(component2.getName()).andReturn("source").atLeastOnce(); + EasyMock.expect(component2.getServiceInterfaces()).andReturn(interfaces).atLeastOnce(); + EasyMock.expect(component2.isSystem()).andReturn(true).atLeastOnce(); + EasyMock.replay(component2); + parent.register(component2); + + Source source = parent.resolveSystemExternalInstance(Source.class); + assertSame(serviceSource, source); + Source2 source2 = parent.resolveSystemExternalInstance(Source2.class); + assertNull(source2); + EasyMock.verify(component); + EasyMock.verify(component2); + } + + /** + * Tests autowiring to a system service which is wired to an atomic component. + */ + public void testServiceAutowire() throws Exception { + CompositeComponent parent = new CompositeComponentImpl("parent", null, null, null); + parent.start(); + + List<Class<?>> interfaces = new ArrayList<Class<?>>(); + interfaces.add(Source.class); + interfaces.add(Source2.class); + + Source serviceSource = new SourceImpl(); + Service component = EasyMock.createMock(Service.class); + EasyMock.expect(component.getName()).andReturn("service").atLeastOnce(); + component.getInterface(); + EasyMock.expectLastCall().andReturn(Source.class).atLeastOnce(); + EasyMock.expect(component.isSystem()).andReturn(false).atLeastOnce(); + EasyMock.expect(component.getServiceInstance()).andReturn(serviceSource); + EasyMock.replay(component); + parent.register(component); + + + AtomicComponent component2 = EasyMock.createMock(AtomicComponent.class); + EasyMock.expect(component2.getName()).andReturn("source").atLeastOnce(); + EasyMock.expect(component2.getServiceInterfaces()).andReturn(interfaces).atLeastOnce(); + EasyMock.expect(component2.isSystem()).andReturn(false).atLeastOnce(); + EasyMock.replay(component2); + parent.register(component2); + + Source source = parent.resolveExternalInstance(Source.class); + assertSame(serviceSource, source); + Source2 source2 = parent.resolveExternalInstance(Source2.class); + assertNull(source2); + EasyMock.verify(component); + EasyMock.verify(component2); + } + + + /** + * Tests autowiring to a system reference + */ + public void testSystemReferenceAutowire() throws Exception { + CompositeComponent parent = new CompositeComponentImpl("parent", null, null, null); + parent.start(); + + Source refSource = new SourceImpl(); + SystemReference reference = EasyMock.createMock(SystemReference.class); + EasyMock.expect(reference.getName()).andReturn("service").atLeastOnce(); + EasyMock.expect(reference.getServiceInstance()).andReturn(refSource); + EasyMock.expect(reference.isSystem()).andReturn(true).atLeastOnce(); + reference.getInterface(); + EasyMock.expectLastCall().andReturn(Source.class); + EasyMock.replay(reference); + parent.register(reference); + + Source source = parent.resolveSystemInstance(Source.class); + assertNotNull(source); + assertNull(parent.resolveSystemExternalInstance(Source.class)); + EasyMock.verify(reference); + } + + /** + * Tests autowiring to a reference + */ + public void testReferenceAutowire() throws Exception { + CompositeComponent parent = new CompositeComponentImpl("parent", null, null, null); + parent.start(); + Source refSource = new SourceImpl(); + Reference reference = EasyMock.createMock(Reference.class); + EasyMock.expect(reference.getName()).andReturn("service").atLeastOnce(); + EasyMock.expect(reference.getServiceInstance()).andReturn(refSource); + EasyMock.expect(reference.isSystem()).andReturn(false).atLeastOnce(); + reference.getInterface(); + EasyMock.expectLastCall().andReturn(Source.class); + EasyMock.replay(reference); + parent.register(reference); + + Source source = parent.resolveInstance(Source.class); + assertNotNull(source); + assertNull(parent.resolveExternalInstance(Source.class)); + EasyMock.verify(reference); + } + + + public static class SourceImpl implements Source, Source2 { + public SourceImpl() { + } + } + + public static interface Source { + + } + + public static interface Source2 { + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeBuilderTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeBuilderTestCase.java new file mode 100644 index 0000000000..fb665a55f4 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeBuilderTestCase.java @@ -0,0 +1,235 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.net.URI; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.model.BindlessServiceDefinition; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.CompositeImplementation; +import org.apache.tuscany.spi.model.ReferenceDefinition; +import org.apache.tuscany.spi.model.ReferenceTarget; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.model.ServiceDefinition; +import org.apache.tuscany.spi.wire.WireService; + +import junit.framework.TestCase; +import org.apache.tuscany.core.builder.BuilderRegistryImpl; +import org.apache.tuscany.core.builder.ConnectorImpl; +import org.apache.tuscany.core.deployer.RootDeploymentContext; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.implementation.java.JavaComponentBuilder; +import org.apache.tuscany.core.implementation.java.JavaImplementation; +import org.apache.tuscany.core.implementation.java.mock.components.OtherTarget; +import org.apache.tuscany.core.implementation.java.mock.components.Source; +import org.apache.tuscany.core.implementation.java.mock.components.SourceImpl; +import org.apache.tuscany.core.implementation.java.mock.components.Target; +import org.apache.tuscany.core.implementation.java.mock.components.TargetImpl; +import org.apache.tuscany.core.wire.jdk.JDKWireService; +import org.easymock.EasyMock; +import org.easymock.IAnswer; + +/** + * @version $$Rev$$ $$Date$$ + */ +public class CompositeBuilderTestCase extends TestCase { + private DeploymentContext deploymentContext; + + protected void setUp() throws Exception { + super.setUp(); + ScopeContainer mock = createMock(); + deploymentContext = new RootDeploymentContext(null, null, mock, null); + } + + @SuppressWarnings("unchecked") + public void testBuildConnect() throws Exception { + CompositeComponent parent = new CompositeComponentImpl(null, null, null, null); + + CompositeBuilder builder = new CompositeBuilder(); + WireService wireService = new JDKWireService(); + builder.setWireService(wireService); + BuilderRegistryImpl builderRegistry = new BuilderRegistryImpl(); + builderRegistry.setWireService(wireService); + JavaComponentBuilder jBuilder = new JavaComponentBuilder(); + jBuilder.setWireService(wireService); + builderRegistry.register(JavaImplementation.class, jBuilder); + builderRegistry.register(CompositeImplementation.class, builder); + CompositeBindlessBuilder bindlessBuilder = new CompositeBindlessBuilder(); + bindlessBuilder.setWireService(wireService); + builderRegistry.register(bindlessBuilder); + builder.setBuilderRegistry(builderRegistry); + CompositeComponent component = + (CompositeComponent) builder.build(parent, createTopComponentDef(), deploymentContext); + + ConnectorImpl connector = new ConnectorImpl(); + connector.connect(component); + + deploymentContext.getModuleScope().start(); + component.start(); + CompositeComponent sourceComponent = (CompositeComponent) component.getChild("SourceComponent"); + Source source = (Source) sourceComponent.getServiceInstance("InnerSourceService"); + assertNotNull(source); + AtomicComponent innerSourceComponent = (AtomicComponent) sourceComponent.getChild("InnerSourceComponent"); + Source innerSourceInstance = (Source) deploymentContext.getModuleScope().getInstance(innerSourceComponent); + assertNotNull(innerSourceInstance); + component.stop(); + } + + private ComponentDefinition createTopComponentDef() throws Exception { + + CompositeComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> outerType = + new CompositeComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + outerType.add(createSourceComponentDef()); + outerType.add(createTargetComponentDef()); + + CompositeImplementation outerImpl = new CompositeImplementation(); + outerImpl.setComponentType(outerType); + + return new ComponentDefinition<CompositeImplementation>(outerImpl); + } + + private ComponentDefinition<CompositeImplementation> createSourceComponentDef() throws Exception { + + CompositeComponentType<ServiceDefinition, ReferenceDefinition, JavaMappedProperty<?>> innerType = + new CompositeComponentType<ServiceDefinition, ReferenceDefinition, JavaMappedProperty<?>>(); + innerType.add(createInnerSourceComponentDef()); + ReferenceDefinition reference = new ReferenceDefinition(); + reference.setName("TargetComponentRef"); + JavaInterfaceProcessorRegistry registry = new JavaInterfaceProcessorRegistryImpl(); + JavaServiceContract targetContract = registry.introspect(Target.class); + reference.setServiceContract(targetContract); + innerType.add(reference); + BindlessServiceDefinition service = new BindlessServiceDefinition(); + service.setName("InnerSourceService"); + JavaServiceContract sourceContract = registry.introspect(Source.class); + service.setServiceContract(sourceContract); + service.setTarget(new URI("InnerSourceComponent")); + innerType.add(service); + + CompositeImplementation innerImpl = new CompositeImplementation(); + innerImpl.setComponentType(innerType); + + ComponentDefinition<CompositeImplementation> sourceComponentDefinition = + new ComponentDefinition<CompositeImplementation>("SourceComponent", innerImpl); + ReferenceTarget refTarget = new ReferenceTarget(); + refTarget.setReferenceName("TargetComponentRef"); + refTarget.addTarget(new URI("TargetComponent")); + sourceComponentDefinition.add(refTarget); + + return sourceComponentDefinition; + } + + private ComponentDefinition<JavaImplementation> createInnerSourceComponentDef() throws Exception { + + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> sourceType = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + sourceType.setImplementationScope(Scope.MODULE); + JavaMappedReference reference = new JavaMappedReference(); + reference.setName("targetReference"); + JavaInterfaceProcessorRegistry registry = new JavaInterfaceProcessorRegistryImpl(); + ServiceContract<?> targetContract = registry.introspect(Target.class); + targetContract.setCallbackClass(OtherTarget.class); + targetContract.setCallbackName("OtherTarget"); + reference.setServiceContract(targetContract); + reference.setMember(SourceImpl.class.getMethod("setTarget", Target.class)); + sourceType.add(reference); + + ServiceContract<?> sourceContract = registry.introspect(Source.class); + + JavaMappedService sourceServiceDefinition = new JavaMappedService(); + sourceServiceDefinition.setName("Source"); + sourceServiceDefinition.setServiceContract(sourceContract); + + sourceType.add(sourceServiceDefinition); + sourceType.setConstructorDefinition(new ConstructorDefinition<SourceImpl>(SourceImpl.class.getConstructor())); + JavaImplementation sourceImpl = new JavaImplementation(); + sourceImpl.setComponentType(sourceType); + sourceImpl.setImplementationClass(SourceImpl.class); + ComponentDefinition<JavaImplementation> innerSourceComponentDefinition = + new ComponentDefinition<JavaImplementation>("InnerSourceComponent", sourceImpl); + ReferenceTarget refTarget = new ReferenceTarget(); + refTarget.setReferenceName("targetReference"); + refTarget.addTarget(new URI("TargetComponentRef")); + innerSourceComponentDefinition.add(refTarget); + + return innerSourceComponentDefinition; + } + + private ComponentDefinition<JavaImplementation> createTargetComponentDef() throws Exception { + + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> targetType = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + targetType.setImplementationScope(Scope.MODULE); + + JavaInterfaceProcessorRegistry registry = new JavaInterfaceProcessorRegistryImpl(); + ServiceContract<?> targetContract = registry.introspect(Target.class); + targetContract.setCallbackClass(OtherTarget.class); + targetContract.setCallbackName("OtherTarget"); + + JavaMappedService serviceDefinition = new JavaMappedService(); + serviceDefinition.setName("Target"); + serviceDefinition.setServiceContract(targetContract); + serviceDefinition.setCallbackReferenceName("otherTarget"); + + targetType.add(serviceDefinition); + targetType.setConstructorDefinition(new ConstructorDefinition<TargetImpl>(TargetImpl.class.getConstructor())); + JavaImplementation targetImpl = new JavaImplementation(); + targetImpl.setComponentType(targetType); + targetImpl.setImplementationClass(TargetImpl.class); + return new ComponentDefinition<JavaImplementation>("TargetComponent", targetImpl); + } + + private ScopeContainer createMock() { + ScopeContainer container = EasyMock.createMock(ScopeContainer.class); + container.start(); + container.register(EasyMock.isA(AtomicComponent.class)); + EasyMock.expectLastCall().anyTimes(); + EasyMock.expect(container.getScope()).andReturn(Scope.MODULE).anyTimes(); + EasyMock.expect(container.getInstance(EasyMock.isA(AtomicComponent.class))).andAnswer(new IAnswer<Object>() { + private Map<AtomicComponent, Object> cache = new HashMap<AtomicComponent, Object>(); + + public Object answer() throws Throwable { + AtomicComponent component = (AtomicComponent) EasyMock.getCurrentArguments()[0]; + Object instance = cache.get(component); + if (instance == null) { + instance = component.createInstance(); + cache.put(component, instance); + } + return instance; + } + }); + EasyMock.replay(container); + return container; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImplBasicTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImplBasicTestCase.java new file mode 100644 index 0000000000..8694d9ddc6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImplBasicTestCase.java @@ -0,0 +1,223 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.util.List; + +import org.apache.tuscany.spi.component.ComponentNotFoundException; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.IllegalTargetException; +import org.apache.tuscany.spi.component.Reference; +import org.apache.tuscany.spi.component.Service; +import org.apache.tuscany.spi.component.TargetNotFoundException; +import org.apache.tuscany.spi.event.Event; +import org.apache.tuscany.spi.event.RuntimeEventListener; +import org.apache.tuscany.spi.extension.ServiceExtension; +import org.apache.tuscany.spi.model.Scope; + +import junit.framework.Assert; +import junit.framework.TestCase; +import org.apache.tuscany.core.component.event.CompositeStart; +import org.easymock.EasyMock; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; + +/** + * @version $Rev$ $Date$ + */ +public class CompositeComponentImplBasicTestCase extends TestCase { + + public void testGetScope() { + CompositeComponent composite = new CompositeComponentImpl("parent", null, null, null); + Assert.assertEquals(Scope.COMPOSITE, composite.getScope()); + } + + public void testGetChildren() { + CompositeComponent composite = new CompositeComponentImpl("parent", null, null, null); + composite.register(new ServiceExtension("foo", null, null, null)); + Assert.assertEquals(1, composite.getChildren().size()); + } + + public void testGetServices() { + CompositeComponent composite = new CompositeComponentImpl("parent", null, null, null); + composite.register(new ServiceExtension("foo", null, null, null)); + composite.register(getReference("bar")); + Assert.assertEquals(1, composite.getServices().size()); + } + + public void testGetService() { + CompositeComponent composite = new CompositeComponentImpl("parent", null, null, null); + composite.register(new ServiceExtension("foo", null, null, null)); + composite.start(); + assertNotNull(composite.getService("foo")); + } + + public void testServiceNotFound() { + CompositeComponent composite = new CompositeComponentImpl("parent", null, null, null); + composite.register(new ServiceExtension("foo", null, null, null)); + composite.start(); + try { + composite.getService("bar"); + fail(); + } catch (ComponentNotFoundException e) { + // expected + } + } + + public void testNotService() { + CompositeComponent composite = new CompositeComponentImpl("parent", null, null, null); + composite.register(getReference("foo")); + composite.start(); + try { + composite.getService("foo"); + fail(); + } catch (ComponentNotFoundException e) { + // expected + } + } + + public void testTargetNotFound() { + CompositeComponent composite = new CompositeComponentImpl("parent", null, null, null); + composite.register(getReference("foo")); + composite.start(); + try { + composite.locateService(Foo.class, "foo1"); + fail(); + } catch (TargetNotFoundException e) { + // expected + } + } + + public void testReferencesServices() { + CompositeComponent composite = new CompositeComponentImpl("parent", null, null, null); + composite.register(new ServiceExtension("foo", null, null, null)); + composite.register(getReference("bar")); + Assert.assertEquals(1, composite.getReferences().size()); + } + + public void testServiceInterfaces() { + CompositeComponent composite = new CompositeComponentImpl("parent", null, null, null); + Service service1 = getService("foo", Foo.class); + composite.register(service1); + Service service2 = getService("bar", Bar.class); + composite.register(service2); + + List<Class<?>> interfaces = composite.getServiceInterfaces(); + assertEquals(2, interfaces.size()); + for (Class o : interfaces) { + if (!(Foo.class.isAssignableFrom(o)) && !(Bar.class.isAssignableFrom(o))) { + fail(); + } + } + } + + public void testGetServiceInstanceByName() { + CompositeComponent composite = new CompositeComponentImpl("parent", null, null, null); + Service service = createMock(Service.class); + EasyMock.expect(service.isSystem()).andReturn(false).atLeastOnce(); + service.getName(); + expectLastCall().andReturn("foo").anyTimes(); + service.getInterface(); + expectLastCall().andReturn(Foo.class); + service.getServiceInstance(); + expectLastCall().andReturn(new Foo() { + }); + replay(service); + composite.register(service); + assertNotNull(composite.getServiceInstance("foo")); + } + + public void testGetServiceInstanceNotFound() { + CompositeComponent composite = new CompositeComponentImpl("parent", null, null, null); + Service service = getService("foo", Foo.class); + composite.register(service); + try { + composite.getServiceInstance("bar"); + fail(); + } catch (TargetNotFoundException e) { + //expected + } + } + + public void testGetServiceInstanceNotService() { + CompositeComponent composite = new CompositeComponentImpl("parent", null, null, null); + Reference reference = getReference("foo"); + composite.register(reference); + try { + composite.getServiceInstance("foo"); + fail(); + } catch (IllegalTargetException e) { + //expected + } + } + + public void testOnEvent() { + CompositeComponent composite = new CompositeComponentImpl("parent", null, null, null); + Event event = new Event() { + public Object getSource() { + return null; + } + }; + RuntimeEventListener listener = createMock(RuntimeEventListener.class); + listener.onEvent(isA(CompositeStart.class)); + listener.onEvent(eq(event)); + expectLastCall(); + replay(listener); + composite.addListener(listener); + composite.start(); + composite.onEvent(event); + } + + public void testPrepare() { + CompositeComponent composite = new CompositeComponentImpl("parent", null, null, null); + composite.prepare(); + } + + private Reference getReference(String name) { + Reference reference = EasyMock.createNiceMock(Reference.class); + EasyMock.expect(reference.isSystem()).andReturn(false).atLeastOnce(); + reference.getName(); + expectLastCall().andReturn(name).anyTimes(); + reference.getInterface(); + expectLastCall().andReturn(Object.class).atLeastOnce(); + replay(reference); + return reference; + } + + private Service getService(String name, Class<?> interfaze) { + Service service = createMock(Service.class); + EasyMock.expect(service.isSystem()).andReturn(false).atLeastOnce(); + service.getName(); + expectLastCall().andReturn(name).anyTimes(); + service.getInterface(); + expectLastCall().andReturn(interfaze).atLeastOnce(); + replay(service); + return service; + } + + private interface Foo { + } + + private interface Bar { + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImplSystemWireTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImplSystemWireTestCase.java new file mode 100644 index 0000000000..c3bf846400 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImplSystemWireTestCase.java @@ -0,0 +1,168 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.spi.QualifiedName; +import org.apache.tuscany.spi.builder.BuilderConfigException; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.SystemAtomicComponent; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundWire; + +import junit.framework.TestCase; +import org.apache.tuscany.core.builder.ConnectorImpl; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class CompositeComponentImplSystemWireTestCase extends TestCase { + + /** + * Verifies system services in a CompositeComponentImpl are wired during the parent composite's prepare callback + */ + public void testSystemServiceWire() { + InboundWire inbound = EasyMock.createMock(InboundWire.class); + EasyMock.expect(inbound.getServiceContract()).andReturn(new JavaServiceContract(Foo.class)); + inbound.getInvocationChains(); + EasyMock.expectLastCall().andReturn(Collections.emptyMap()); + + List<Class<?>> services = new ArrayList<Class<?>>(); + services.add(Foo.class); + QualifiedName qName = new QualifiedName("target/bar"); + OutboundWire outbound = EasyMock.createMock(OutboundWire.class); + EasyMock.expect(outbound.getTargetName()).andReturn(qName).atLeastOnce(); + outbound.getInvocationChains(); + EasyMock.expectLastCall().andReturn(Collections.emptyMap()); + outbound.setTargetWire(EasyMock.eq(inbound)); + EasyMock.expect(outbound.getServiceContract()).andReturn(new JavaServiceContract(Foo.class)).atLeastOnce(); + List<OutboundWire> wires = new ArrayList<OutboundWire>(); + wires.add(outbound); + Map<String, List<OutboundWire>> wireMap = new HashMap<String, List<OutboundWire>>(); + wireMap.put("ref", wires); + CompositeComponent parent = new CompositeComponentImpl("foo", "foo", null, new ConnectorImpl(), null); + SystemAtomicComponent source = EasyMock.createMock(SystemAtomicComponent.class); + EasyMock.expect(source.getScope()).andReturn(Scope.MODULE).atLeastOnce(); + EasyMock.expect(source.getName()).andReturn("source").atLeastOnce(); + EasyMock.expect(source.getServiceInterfaces()).andReturn(services); + EasyMock.expect(source.getOutboundWires()).andReturn(wireMap); + source.getInboundWires(); + EasyMock.expectLastCall().andReturn(Collections.emptyMap()); + EasyMock.expect(source.isSystem()).andReturn(true).atLeastOnce(); + EasyMock.expect(source.getParent()).andReturn(parent).atLeastOnce(); + + source.prepare(); + EasyMock.replay(source); + + EasyMock.expect(outbound.getContainer()).andReturn(source); + EasyMock.replay(outbound); + + parent.register(source); + + SystemAtomicComponent target = EasyMock.createMock(SystemAtomicComponent.class); + EasyMock.expect(target.getName()).andReturn("target").atLeastOnce(); + EasyMock.expect(target.getServiceInterfaces()).andReturn(services); + EasyMock.expect(target.getInboundWire("bar")).andReturn(inbound).atLeastOnce(); + EasyMock.expect(target.getScope()).andReturn(Scope.MODULE).atLeastOnce(); + EasyMock.expect(target.getParent()).andReturn(parent).atLeastOnce(); + target.getInboundWires(); + EasyMock.expectLastCall().andReturn(Collections.emptyMap()); + + target.prepare(); + target.getOutboundWires(); + EasyMock.expectLastCall().andReturn(Collections.emptyMap()); + EasyMock.expect(target.isSystem()).andReturn(true).atLeastOnce(); + EasyMock.replay(target); + + EasyMock.expect(inbound.getContainer()).andReturn(target); + EasyMock.replay(inbound); + + parent.register(target); + parent.prepare(); + EasyMock.verify(source); + EasyMock.verify(target); + EasyMock.verify(inbound); + EasyMock.verify(outbound); + } + + + /** + * Verifies an application component cannot be wired to a system service in the same composite + */ + public void testSystemServiceIsolationWire() { + InboundWire inbound = EasyMock.createMock(InboundWire.class); + EasyMock.replay(inbound); + + List<Class<?>> services = new ArrayList<Class<?>>(); + services.add(Foo.class); + QualifiedName qName = new QualifiedName("target/bar"); + OutboundWire outbound = EasyMock.createMock(OutboundWire.class); + EasyMock.expect(outbound.getReferenceName()).andReturn("foo"); + EasyMock.expect(outbound.getTargetName()).andReturn(qName).atLeastOnce(); + EasyMock.replay(outbound); + + List<OutboundWire> wires = new ArrayList<OutboundWire>(); + wires.add(outbound); + Map<String, List<OutboundWire>> wireMap = new HashMap<String, List<OutboundWire>>(); + wireMap.put("ref", wires); + CompositeComponent parent = new CompositeComponentImpl("foo", "foo", null, new ConnectorImpl(), null); + SystemAtomicComponent source = EasyMock.createMock(SystemAtomicComponent.class); + EasyMock.expect(source.getName()).andReturn("source").atLeastOnce(); + EasyMock.expect(source.getServiceInterfaces()).andReturn(services); + EasyMock.expect(source.getOutboundWires()).andReturn(wireMap); + EasyMock.expect(source.isSystem()).andReturn(true).atLeastOnce(); + EasyMock.expect(source.getParent()).andReturn(parent).atLeastOnce(); + EasyMock.replay(source); + + parent.register(source); + + AtomicComponent target = EasyMock.createMock(AtomicComponent.class); + EasyMock.expect(target.getName()).andReturn("target").atLeastOnce(); + EasyMock.expect(target.getServiceInterfaces()).andReturn(services); + EasyMock.expect(target.isSystem()).andReturn(false).atLeastOnce(); + EasyMock.replay(target); + + parent.register(target); + try { + parent.prepare(); + fail(); + } catch (BuilderConfigException e) { + //expected + } + EasyMock.verify(source); + EasyMock.verify(target); + EasyMock.verify(inbound); + EasyMock.verify(outbound); + } + + + private class Foo { + + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImplTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImplTestCase.java new file mode 100644 index 0000000000..29df7f0f85 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeComponentImplTestCase.java @@ -0,0 +1,174 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.SystemAtomicComponent; + +import junit.framework.TestCase; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class CompositeComponentImplTestCase extends TestCase { + + public void testSetUri() throws Exception { + CompositeComponentImpl component = new CompositeComponentImpl("foo", "foo/bar", null, null, null); + assertEquals("foo/bar", component.getURI()); + } + + public void testRegisterSystemService() throws Exception { + List<Class<?>> services = new ArrayList<Class<?>>(); + services.add(Foo.class); + CompositeComponent parent = new CompositeComponentImpl("foo", "foo", null, null, null); + SystemAtomicComponent component = EasyMock.createMock(SystemAtomicComponent.class); + EasyMock.expect(component.getName()).andReturn("bar").atLeastOnce(); + EasyMock.expect(component.getServiceInterfaces()).andReturn(services); + EasyMock.expect(component.isSystem()).andReturn(true).atLeastOnce(); + EasyMock.replay(component); + parent.register(component); + assertNull(parent.getChild("bar")); + assertNotNull(parent.getSystemChild("bar")); + EasyMock.verify(component); + } + + public void testRegister() throws Exception { + List<Class<?>> services = new ArrayList<Class<?>>(); + services.add(Foo.class); + CompositeComponent parent = new CompositeComponentImpl("foo", "foo", null, null, null); + AtomicComponent component = EasyMock.createMock(AtomicComponent.class); + EasyMock.expect(component.getName()).andReturn("bar").atLeastOnce(); + EasyMock.expect(component.getServiceInterfaces()).andReturn(services); + EasyMock.expect(component.isSystem()).andReturn(false).atLeastOnce(); + EasyMock.replay(component); + parent.register(component); + assertNull(parent.getSystemChild("bar")); + assertNotNull(parent.getChild("bar")); + EasyMock.verify(component); + } + + /** + * Verifies a system service and application component can be registered with the same name in a composite + */ + public void testSystemServiceApplicationNamespaceIsolation() throws Exception { + List<Class<?>> services = new ArrayList<Class<?>>(); + services.add(Foo.class); + CompositeComponent parent = new CompositeComponentImpl("foo", "foo", null, null, null); + SystemAtomicComponent component = EasyMock.createMock(SystemAtomicComponent.class); + EasyMock.expect(component.getName()).andReturn("bar").atLeastOnce(); + EasyMock.expect(component.getServiceInterfaces()).andReturn(services); + EasyMock.expect(component.isSystem()).andReturn(true).atLeastOnce(); + EasyMock.replay(component); + parent.register(component); + AtomicComponent component2 = EasyMock.createMock(AtomicComponent.class); + EasyMock.expect(component2.getName()).andReturn("bar").atLeastOnce(); + EasyMock.expect(component2.getServiceInterfaces()).andReturn(services); + EasyMock.expect(component2.isSystem()).andReturn(false).atLeastOnce(); + EasyMock.replay(component2); + parent.register(component2); + EasyMock.verify(component); + EasyMock.verify(component2); + } + + public void testSystemServiceLifecycle() throws Exception { + List<Class<?>> services = new ArrayList<Class<?>>(); + services.add(Foo.class); + CompositeComponent parent = new CompositeComponentImpl("foo", "foo", null, null, null); + SystemAtomicComponent component = EasyMock.createMock(SystemAtomicComponent.class); + component.start(); + EasyMock.expect(component.getName()).andReturn("bar").atLeastOnce(); + EasyMock.expect(component.getServiceInterfaces()).andReturn(services); + EasyMock.expect(component.isSystem()).andReturn(true).atLeastOnce(); + component.stop(); + EasyMock.replay(component); + parent.register(component); + parent.start(); + parent.stop(); + EasyMock.verify(component); + } + + public void testComponentLifecycle() throws Exception { + List<Class<?>> services = new ArrayList<Class<?>>(); + services.add(Foo.class); + CompositeComponent parent = new CompositeComponentImpl("foo", "foo", null, null, null); + AtomicComponent component = EasyMock.createMock(AtomicComponent.class); + component.start(); + EasyMock.expect(component.getName()).andReturn("bar").atLeastOnce(); + EasyMock.expect(component.getServiceInterfaces()).andReturn(services); + EasyMock.expect(component.isSystem()).andReturn(false).atLeastOnce(); + component.stop(); + EasyMock.replay(component); + parent.register(component); + parent.start(); + parent.stop(); + EasyMock.verify(component); + } + + public void testSystemServiceAutowire() throws Exception { + List<Class<?>> services = new ArrayList<Class<?>>(); + services.add(Foo.class); + CompositeComponent parent = new CompositeComponentImpl("foo", "foo", null, null, null); + SystemAtomicComponent component = EasyMock.createMock(SystemAtomicComponent.class); + component.start(); + EasyMock.expect(component.getName()).andReturn("bar").atLeastOnce(); + EasyMock.expect(component.getServiceInterfaces()).andReturn(services); + EasyMock.expect(component.getServiceInstance()).andReturn(new Foo() { + }); + EasyMock.expect(component.isSystem()).andReturn(true).atLeastOnce(); + component.stop(); + EasyMock.replay(component); + parent.register(component); + parent.start(); + assertNull(parent.resolveSystemExternalInstance(Foo.class)); + assertNotNull(parent.resolveSystemInstance(Foo.class)); + parent.stop(); + EasyMock.verify(component); + } + + + public void testAutowire() throws Exception { + List<Class<?>> services = new ArrayList<Class<?>>(); + services.add(Foo.class); + CompositeComponent parent = new CompositeComponentImpl("foo", "foo", null, null, null); + SystemAtomicComponent component = EasyMock.createMock(SystemAtomicComponent.class); + component.start(); + EasyMock.expect(component.getName()).andReturn("bar").atLeastOnce(); + EasyMock.expect(component.getServiceInterfaces()).andReturn(services); + EasyMock.expect(component.getServiceInstance()).andReturn(new Foo() { + }); + EasyMock.expect(component.isSystem()).andReturn(false).atLeastOnce(); + component.stop(); + EasyMock.replay(component); + parent.register(component); + parent.start(); + assertNull(parent.resolveExternalInstance(Foo.class)); + assertNotNull(parent.resolveInstance(Foo.class)); + parent.stop(); + EasyMock.verify(component); + } + + private class Foo { + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeComponentResolutionTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeComponentResolutionTestCase.java new file mode 100644 index 0000000000..0ad1e6f649 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeComponentResolutionTestCase.java @@ -0,0 +1,167 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.ComponentNotFoundException; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.Service; +import org.apache.tuscany.spi.component.SystemAtomicComponent; + +import junit.framework.TestCase; +import org.apache.tuscany.core.mock.component.Source; +import org.apache.tuscany.core.mock.component.SourceImpl; +import org.easymock.EasyMock; + +/** + * Verifies an atomic component can be resolved from its parent + * + * @version $$Rev$$ $$Date$$ + */ +public class CompositeComponentResolutionTestCase extends TestCase { + + public void testSystemComponentResolution() throws NoSuchMethodException { + CompositeComponent parent = new CompositeComponentImpl("foo", null, null, null); + parent.start(); + List<Class<?>> interfaces = new ArrayList<Class<?>>(); + interfaces.add(Source.class); + Source originalSource = new SourceImpl(); + SystemAtomicComponent component = EasyMock.createMock(SystemAtomicComponent.class); + EasyMock.expect(component.getName()).andReturn("source").atLeastOnce(); + EasyMock.expect(component.getServiceInstance()).andReturn(originalSource); + EasyMock.expect(component.isSystem()).andReturn(true).atLeastOnce(); + EasyMock.expect(component.getServiceInterfaces()).andReturn(interfaces); + EasyMock.replay(component); + parent.register(component); + assertNull(parent.getChild("source")); + AtomicComponent target = (AtomicComponent) parent.getSystemChild("source"); + Source source = (Source) target.getServiceInstance(); + assertNotNull(source); + EasyMock.verify(component); + } + + public void testLocateSystemService() throws NoSuchMethodException { + CompositeComponent parent = new CompositeComponentImpl("foo", null, null, null); + parent.start(); + List<Class<?>> interfaces = new ArrayList<Class<?>>(); + interfaces.add(Source.class); + Source originalSource = new SourceImpl(); + SystemAtomicComponent component = EasyMock.createMock(SystemAtomicComponent.class); + EasyMock.expect(component.getName()).andReturn("source").atLeastOnce(); + EasyMock.expect(component.getServiceInstance()).andReturn(originalSource); + EasyMock.expect(component.isSystem()).andReturn(true).atLeastOnce(); + EasyMock.expect(component.getServiceInterfaces()).andReturn(interfaces); + EasyMock.replay(component); + parent.register(component); + Source source = parent.locateSystemService(Source.class, "source"); + assertNotNull(source); + EasyMock.verify(component); + } + + public void testLocateService() throws NoSuchMethodException { + CompositeComponent parent = new CompositeComponentImpl("foo", null, null, null); + parent.start(); + List<Class<?>> interfaces = new ArrayList<Class<?>>(); + interfaces.add(Source.class); + Source originalSource = new SourceImpl(); + AtomicComponent component = EasyMock.createMock(AtomicComponent.class); + EasyMock.expect(component.getName()).andReturn("source").atLeastOnce(); + EasyMock.expect(component.getServiceInstance()).andReturn(originalSource); + EasyMock.expect(component.isSystem()).andReturn(false).atLeastOnce(); + EasyMock.expect(component.getServiceInterfaces()).andReturn(interfaces); + EasyMock.replay(component); + parent.register(component); + Source source = parent.locateService(Source.class, "source"); + assertNotNull(source); + EasyMock.verify(component); + } + + public void testComponentResolution() throws NoSuchMethodException { + CompositeComponent parent = new CompositeComponentImpl("foo", null, null, null); + parent.start(); + List<Class<?>> interfaces = new ArrayList<Class<?>>(); + interfaces.add(Source.class); + Source originalSource = new SourceImpl(); + AtomicComponent component = EasyMock.createMock(AtomicComponent.class); + EasyMock.expect(component.getName()).andReturn("source").atLeastOnce(); + EasyMock.expect(component.getServiceInstance()).andReturn(originalSource); + EasyMock.expect(component.isSystem()).andReturn(false).atLeastOnce(); + EasyMock.expect(component.getServiceInterfaces()).andReturn(interfaces); + EasyMock.replay(component); + parent.register(component); + assertNull(parent.getSystemChild("source")); + AtomicComponent target = (AtomicComponent) parent.getChild("source"); + Source source = (Source) target.getServiceInstance(); + assertNotNull(source); + EasyMock.verify(component); + } + + + public void testGetService() throws NoSuchMethodException { + CompositeComponent parent = new CompositeComponentImpl("foo", null, null, null); + parent.start(); + Service service = EasyMock.createMock(Service.class); + EasyMock.expect(service.getName()).andReturn("source").atLeastOnce(); + EasyMock.expect(service.isSystem()).andReturn(false).atLeastOnce(); + service.getInterface(); + EasyMock.expectLastCall().andReturn(Source.class); + EasyMock.replay(service); + parent.register(service); + assertNotNull(parent.getService("source")); + try { + parent.getSystemService("source"); + fail(); + } catch (ComponentNotFoundException e) { + // expected + } + EasyMock.verify(service); + } + + public void testSystemGetService() throws NoSuchMethodException { + CompositeComponent parent = new CompositeComponentImpl("foo", null, null, null); + parent.start(); + Service service = EasyMock.createMock(Service.class); + EasyMock.expect(service.getName()).andReturn("source").atLeastOnce(); + EasyMock.expect(service.isSystem()).andReturn(true).atLeastOnce(); + service.getInterface(); + EasyMock.expectLastCall().andReturn(Source.class); + EasyMock.replay(service); + parent.register(service); + assertNotNull(parent.getSystemService("source")); + try { + parent.getService("source"); + fail(); + } catch (ComponentNotFoundException e) { + // expected + } + EasyMock.verify(service); + } + + + protected void setUp() throws Exception { + super.setUp(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeLifecycleTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeLifecycleTestCase.java new file mode 100644 index 0000000000..5b0af72caa --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeLifecycleTestCase.java @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.SystemAtomicComponent; + +import junit.framework.TestCase; +import org.apache.tuscany.core.mock.component.Source; +import org.apache.tuscany.core.mock.component.SourceImpl; +import org.easymock.EasyMock; + +/** + * @version $$Rev$$ $$Date$$ + */ +public class CompositeLifecycleTestCase extends TestCase { + + public void testLifecycle() throws Exception { + CompositeComponent composite = new CompositeComponentImpl("foo", null, null, null); + composite.start(); + assertNull(composite.getChild("nothtere")); + composite.stop(); + composite.start(); + assertNull(composite.getChild("nothtere")); + composite.stop(); + } + + public void testSystemRestart() throws NoSuchMethodException { + List<Class<?>> interfaces = new ArrayList<Class<?>>(); + interfaces.add(Source.class); + Source originalSource = new SourceImpl(); + SystemAtomicComponent component = EasyMock.createMock(SystemAtomicComponent.class); + component.start(); + component.stop(); + EasyMock.expectLastCall().times(2); + EasyMock.expect(component.getName()).andReturn("source").atLeastOnce(); + EasyMock.expect(component.isSystem()).andReturn(true).atLeastOnce(); + EasyMock.expect(component.getServiceInstance()).andReturn(originalSource).atLeastOnce(); + EasyMock.expect(component.getServiceInterfaces()).andReturn(interfaces); + EasyMock.replay(component); + + CompositeComponent composite = new CompositeComponentImpl("foo", null, null, null); + composite.start(); + composite.register(component); + + AtomicComponent atomicComponent = (AtomicComponent) composite.getSystemChild("source"); + Source source = (Source) atomicComponent.getServiceInstance(); + assertNotNull(source); + composite.stop(); + composite.start(); + atomicComponent = (AtomicComponent) composite.getSystemChild("source"); + Source source2 = (Source) atomicComponent.getServiceInstance(); + assertNotNull(source2); + composite.stop(); + EasyMock.verify(component); + } + + public void testRestart() throws NoSuchMethodException { + List<Class<?>> interfaces = new ArrayList<Class<?>>(); + interfaces.add(Source.class); + Source originalSource = new SourceImpl(); + AtomicComponent component = EasyMock.createMock(AtomicComponent.class); + component.start(); + component.stop(); + EasyMock.expectLastCall().times(2); + EasyMock.expect(component.getName()).andReturn("source").atLeastOnce(); + EasyMock.expect(component.isSystem()).andReturn(false).atLeastOnce(); + EasyMock.expect(component.getServiceInstance()).andReturn(originalSource).atLeastOnce(); + EasyMock.expect(component.getServiceInterfaces()).andReturn(interfaces); + EasyMock.replay(component); + + CompositeComponent composite = new CompositeComponentImpl("foo", null, null, null); + composite.start(); + composite.register(component); + + AtomicComponent atomicComponent = (AtomicComponent) composite.getChild("source"); + Source source = (Source) atomicComponent.getServiceInstance(); + assertNotNull(source); + composite.stop(); + composite.start(); + atomicComponent = (AtomicComponent) composite.getChild("source"); + Source source2 = (Source) atomicComponent.getServiceInstance(); + assertNotNull(source2); + composite.stop(); + EasyMock.verify(component); + } + + public void testChildStoppedBeforeParent() { + CompositeComponent parent = new CompositeComponentImpl("parent", null, null, null); + CompositeComponent child = new CompositeComponentImpl("child", null, null, null); + parent.register(child); + parent.start(); + child.stop(); + parent.stop(); + } + + protected void setUp() throws Exception { + super.setUp(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositePropagationTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositePropagationTestCase.java new file mode 100644 index 0000000000..69b8c3f34f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositePropagationTestCase.java @@ -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.core.implementation.composite; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.SystemAtomicComponent; + +import junit.framework.TestCase; +import org.apache.tuscany.core.mock.component.Source; +import org.easymock.EasyMock; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * + * @version $Rev$ $Date$ + */ +public class CompositePropagationTestCase extends TestCase { + + private CompositeComponent parent; + private CompositeComponent child2; + + public void testSystemLifecyclePropagation() throws NoSuchMethodException { + parent.start(); + List<Class<?>> interfaces = new ArrayList<Class<?>>(); + interfaces.add(Source.class); + SystemAtomicComponent component = createMock(SystemAtomicComponent.class); + expect(component.getName()).andReturn("source").anyTimes(); + component.stop(); + expect(component.getServiceInterfaces()).andReturn(interfaces); + EasyMock.expect(component.isSystem()).andReturn(true).atLeastOnce(); + replay(component); + child2.register(component); + parent.stop(); + verify(component); + } + + public void testLifecyclePropagation() throws NoSuchMethodException { + parent.start(); + List<Class<?>> interfaces = new ArrayList<Class<?>>(); + interfaces.add(Source.class); + SystemAtomicComponent component = createMock(SystemAtomicComponent.class); + expect(component.getName()).andReturn("source").anyTimes(); + component.stop(); + expect(component.getServiceInterfaces()).andReturn(interfaces); + EasyMock.expect(component.isSystem()).andReturn(false).atLeastOnce(); + replay(component); + child2.register(component); + parent.stop(); + verify(component); + } + + + protected void setUp() throws Exception { + super.setUp(); + parent = new CompositeComponentImpl("parent", null, null, null); + CompositeComponent child1 = new CompositeComponentImpl("child1", parent, null, null); + child2 = new CompositeComponentImpl("child2", child1, null, null); + child1.register(child2); + parent.register(child1); + } + + protected void tearDown() throws Exception { + parent.stop(); + super.tearDown(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeReferenceCallbackTargetInvokerInvocationExceptionTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeReferenceCallbackTargetInvokerInvocationExceptionTestCase.java new file mode 100644 index 0000000000..b1e850d703 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeReferenceCallbackTargetInvokerInvocationExceptionTestCase.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.core.implementation.composite; + +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.MessageImpl; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; + +import junit.framework.TestCase; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class CompositeReferenceCallbackTargetInvokerInvocationExceptionTestCase extends TestCase { + private InboundWire wire; + private WorkContext context; + private Message message; + private OutboundInvocationChain chain; + private CompositeReferenceCallbackTargetInvoker invoker; + + /** + * Verfies an InvocationTargetException thrown when invoking the target is propagated to the client correctly and + * the originating error is unwrapped + */ + public void testThrowableTargetInvocation() throws Exception { + Message response = invoker.invoke(message); + assertTrue(response.isFault()); + Object body = response.getBody(); + assertTrue(SomeException.class.equals(body.getClass())); + EasyMock.verify(wire); + EasyMock.verify(context); + EasyMock.verify(chain); + } + + protected void setUp() throws Exception { + super.setUp(); + Object id = new Object(); + Object corrId = new Object(); + Object targetAddress = new Object(); + message = new MessageImpl(); + message.setMessageId(id); + message.setCorrelationId(corrId); + message.setBody("foo"); + Message response = new MessageImpl(); + response.setBody("response"); + Operation<Type> operation = new Operation<Type>("echo", null, null, null); + Interceptor head = new ErrorInterceptor(); + chain = EasyMock.createMock(OutboundInvocationChain.class); + EasyMock.expect(chain.getTargetInvoker()).andReturn(null); + EasyMock.expect(chain.getHeadInterceptor()).andReturn(head); + EasyMock.replay(chain); + Map<Operation<?>, OutboundInvocationChain> chains = new HashMap<Operation<?>, OutboundInvocationChain>(); + chains.put(operation, chain); + wire = EasyMock.createMock(InboundWire.class); + EasyMock.expect(wire.retrieveMapping(corrId)).andReturn(targetAddress); + EasyMock.expect(wire.getSourceCallbackInvocationChains(targetAddress)).andReturn(chains); + EasyMock.expect(wire.getContainer()).andReturn(null); + EasyMock.replay(wire); + context = EasyMock.createMock(WorkContext.class); + context.setCurrentMessageId(EasyMock.eq(id)); + context.setCurrentMessageId(EasyMock.isNull()); + context.setCurrentCorrelationId(corrId); + context.setCurrentCorrelationId(EasyMock.isNull()); + EasyMock.expect(context.getCurrentMessageId()).andReturn(id); + EasyMock.expect(context.getCurrentCorrelationId()).andReturn(corrId); + EasyMock.replay(context); + invoker = new CompositeReferenceCallbackTargetInvoker(operation, wire, context); + } + + private class SomeException extends Exception { + + } + + private class ErrorInterceptor implements Interceptor { + + public Message invoke(Message msg) { + msg.setBodyWithFault(new SomeException()); + return msg; + } + + public void setNext(Interceptor next) { + + } + + public Interceptor getNext() { + return null; + } + + public boolean isOptimizable() { + return false; + } + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeReferenceCallbackTargetInvokerTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeReferenceCallbackTargetInvokerTestCase.java new file mode 100644 index 0000000000..8e047e3ad1 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeReferenceCallbackTargetInvokerTestCase.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.MessageImpl; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; + +import junit.framework.TestCase; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class CompositeReferenceCallbackTargetInvokerTestCase extends TestCase { + private InboundWire wire; + private WorkContext context; + private Message message; + private OutboundInvocationChain chain; + private Interceptor head; + private CompositeReferenceCallbackTargetInvoker invoker; + + /** + * Verfies the normal execution path through a callback + */ + public void testNormalPathMessageInvocation() throws Exception { + Message response = invoker.invoke(message); + assertEquals("response", response.getBody()); + EasyMock.verify(wire); + EasyMock.verify(context); + EasyMock.verify(chain); + EasyMock.verify(head); + } + + protected void setUp() throws Exception { + super.setUp(); + Object id = new Object(); + Object corrId = new Object(); + Object targetAddress = new Object(); + message = new MessageImpl(); + message.setMessageId(id); + message.setCorrelationId(corrId); + message.setBody("foo"); + Message response = new MessageImpl(); + response.setBody("response"); + Operation<Type> operation = new Operation<Type>("echo", null, null, null); + head = EasyMock.createMock(Interceptor.class); + EasyMock.expect(head.invoke(EasyMock.isA(Message.class))).andReturn(response); + EasyMock.replay(head); + chain = EasyMock.createMock(OutboundInvocationChain.class); + EasyMock.expect(chain.getTargetInvoker()).andReturn(null); + EasyMock.expect(chain.getHeadInterceptor()).andReturn(head); + EasyMock.replay(chain); + Map<Operation<?>, OutboundInvocationChain> chains = new HashMap<Operation<?>, OutboundInvocationChain>(); + chains.put(operation, chain); + wire = EasyMock.createMock(InboundWire.class); + EasyMock.expect(wire.retrieveMapping(corrId)).andReturn(targetAddress); + EasyMock.expect(wire.getSourceCallbackInvocationChains(targetAddress)).andReturn(chains); + EasyMock.expect(wire.getContainer()).andReturn(null); + EasyMock.replay(wire); + context = EasyMock.createMock(WorkContext.class); + context.setCurrentMessageId(EasyMock.eq(id)); + context.setCurrentMessageId(EasyMock.isNull()); + context.setCurrentCorrelationId(corrId); + context.setCurrentCorrelationId(EasyMock.isNull()); + EasyMock.expect(context.getCurrentMessageId()).andReturn(id); + EasyMock.expect(context.getCurrentCorrelationId()).andReturn(corrId); + EasyMock.replay(context); + invoker = new CompositeReferenceCallbackTargetInvoker(operation, wire, context); + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeReferenceCallbackTargetInvokerThrowableTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeReferenceCallbackTargetInvokerThrowableTestCase.java new file mode 100644 index 0000000000..462b6a5680 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeReferenceCallbackTargetInvokerThrowableTestCase.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.core.implementation.composite; + +import java.lang.reflect.Type; +import java.lang.reflect.UndeclaredThrowableException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.MessageImpl; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; + +import junit.framework.TestCase; +import org.easymock.EasyMock; +import org.easymock.IAnswer; + +/** + * @version $Rev$ $Date$ + */ +public class CompositeReferenceCallbackTargetInvokerThrowableTestCase extends TestCase { + private InboundWire wire; + private WorkContext context; + private Message message; + private OutboundInvocationChain chain; + private Interceptor head; + private CompositeReferenceCallbackTargetInvoker invoker; + + /** + * Verfies an exception thrown in the target is propagated to the client correctly + */ + public void testThrowableTargetInvocation() throws Exception { + Message response = invoker.invoke(message); + assertTrue(response.isFault()); + Object body = response.getBody(); + if (!(body instanceof UndeclaredThrowableException)) { + fail(); // EasyMock wraps the Throwable in an UndeclaredThrowableException + } + UndeclaredThrowableException e = (UndeclaredThrowableException) body; + assertTrue(InsidiousException.class.equals(e.getUndeclaredThrowable().getClass())); + EasyMock.verify(wire); + EasyMock.verify(context); + EasyMock.verify(chain); + EasyMock.verify(head); + } + + protected void setUp() throws Exception { + super.setUp(); + Object id = new Object(); + Object corrId = new Object(); + Object targetAddress = new Object(); + message = new MessageImpl(); + message.setMessageId(id); + message.setCorrelationId(corrId); + message.setBody("foo"); + Message response = new MessageImpl(); + response.setBody("response"); + Operation<Type> operation = new Operation<Type>("echo", null, null, null); + head = EasyMock.createMock(Interceptor.class); + EasyMock.expect(head.invoke(EasyMock.isA(Message.class))).andStubAnswer(new IAnswer() { + public Object answer() throws Throwable { + throw new InsidiousException(); // andThrow() does not seem to work here + } + }); + EasyMock.replay(head); + chain = EasyMock.createMock(OutboundInvocationChain.class); + EasyMock.expect(chain.getTargetInvoker()).andReturn(null); + EasyMock.expect(chain.getHeadInterceptor()).andReturn(head); + EasyMock.replay(chain); + Map<Operation<?>, OutboundInvocationChain> chains = new HashMap<Operation<?>, OutboundInvocationChain>(); + chains.put(operation, chain); + wire = EasyMock.createMock(InboundWire.class); + EasyMock.expect(wire.retrieveMapping(corrId)).andReturn(targetAddress); + EasyMock.expect(wire.getSourceCallbackInvocationChains(targetAddress)).andReturn(chains); + EasyMock.expect(wire.getContainer()).andReturn(null); + EasyMock.replay(wire); + context = EasyMock.createMock(WorkContext.class); + context.setCurrentMessageId(EasyMock.eq(id)); + context.setCurrentMessageId(EasyMock.isNull()); + context.setCurrentCorrelationId(corrId); + context.setCurrentCorrelationId(EasyMock.isNull()); + EasyMock.expect(context.getCurrentMessageId()).andReturn(id); + EasyMock.expect(context.getCurrentCorrelationId()).andReturn(corrId); + EasyMock.replay(context); + invoker = new CompositeReferenceCallbackTargetInvoker(operation, wire, context); + } + + private class InsidiousException extends Throwable { + + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeReferenceTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeReferenceTestCase.java new file mode 100644 index 0000000000..fe62691820 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/CompositeReferenceTestCase.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.lang.reflect.Type; + +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.TargetInvoker; + +import junit.framework.TestCase; + +/** + * + */ +public class CompositeReferenceTestCase extends TestCase { + + public void testCreateTargetInvoker() throws Exception { + + MyServiceContract serviceContract = new MyServiceContract(); + CompositeReference compositeReference = new CompositeReference("testCompositeReferemce", + null, + null, + serviceContract, + null); + Operation operation = new Operation<Type>("sayHi", null, null, null, false, null); + TargetInvoker targetInvoker = compositeReference.createTargetInvoker(serviceContract, operation); + assertNotNull(targetInvoker); + } + + public void testCreateCallbackTargetInvoker() throws Exception { + + MyServiceContract serviceContract = new MyServiceContract(); + CompositeReference compositeReference = new CompositeReference("testCompositeReferemce", + null, + null, + serviceContract, + null); + Operation operation = new Operation<Type>("sayHi", null, null, null, false, null); + TargetInvoker targetInvoker = compositeReference.createCallbackTargetInvoker(serviceContract, operation); + assertNotNull(targetInvoker); + } + + class MyServiceContract extends ServiceContract { + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/DuplicateRegistrationTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/DuplicateRegistrationTestCase.java new file mode 100644 index 0000000000..33235983b9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/DuplicateRegistrationTestCase.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.DuplicateNameException; +import org.apache.tuscany.spi.component.SystemAtomicComponent; + +import junit.framework.TestCase; +import org.apache.tuscany.core.mock.component.Source; +import org.easymock.EasyMock; + +/** + * Verfies children with the same name cannot be registered in the same composite + * + * @version $Rev$ $Date$ + */ +public class DuplicateRegistrationTestCase extends TestCase { + + public void testDuplicateRegistration() throws Exception { + CompositeComponent parent = new CompositeComponentImpl(null, null, null, null); + parent.start(); + + List<Class<?>> interfaces = new ArrayList<Class<?>>(); + interfaces.add(Source.class); + SystemAtomicComponent component1 = EasyMock.createMock(SystemAtomicComponent.class); + EasyMock.expect(component1.getName()).andReturn("source").atLeastOnce(); + EasyMock.expect(component1.isSystem()).andReturn(true).atLeastOnce(); + component1.stop(); + EasyMock.expect(component1.getServiceInterfaces()).andReturn(interfaces); + EasyMock.replay(component1); + + SystemAtomicComponent component2 = EasyMock.createMock(SystemAtomicComponent.class); + EasyMock.expect(component2.getName()).andReturn("source").atLeastOnce(); + EasyMock.expect(component2.isSystem()).andReturn(true).atLeastOnce(); + component2.stop(); + EasyMock.expect(component2.getServiceInterfaces()).andReturn(interfaces); + EasyMock.replay(component2); + + parent.register(component1); + try { + parent.register(component2); + fail(); + } catch (DuplicateNameException e) { + // ok + } + parent.stop(); + } + + public void testDuplicateNameSystemService() throws Exception { + List<Class<?>> services = new ArrayList<Class<?>>(); + services.add(Source.class); + CompositeComponent parent = new CompositeComponentImpl("foo", "foo", null, null, null); + SystemAtomicComponent component = EasyMock.createMock(SystemAtomicComponent.class); + EasyMock.expect(component.getName()).andReturn("bar").atLeastOnce(); + EasyMock.expect(component.getServiceInterfaces()).andReturn(services); + EasyMock.expect(component.isSystem()).andReturn(true).atLeastOnce(); + EasyMock.replay(component); + parent.register(component); + SystemAtomicComponent component2 = EasyMock.createMock(SystemAtomicComponent.class); + EasyMock.expect(component2.getName()).andReturn("bar").atLeastOnce(); + EasyMock.expect(component2.getServiceInterfaces()).andReturn(services); + EasyMock.expect(component2.isSystem()).andReturn(true).atLeastOnce(); + EasyMock.replay(component2); + try { + parent.register(component2); + fail(); + } catch (DuplicateNameException e) { + // expected + } + } + + + protected void setUp() throws Exception { + super.setUp(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/ImplementationCompositeLoaderTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/ImplementationCompositeLoaderTestCase.java new file mode 100644 index 0000000000..67efb6fd4c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/ImplementationCompositeLoaderTestCase.java @@ -0,0 +1,192 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.composite; + +import java.net.MalformedURLException; +import java.net.URL; +import javax.xml.namespace.QName; +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import junit.framework.TestCase; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.reportMatcher; +import static org.easymock.EasyMock.verify; +import org.easymock.IArgumentMatcher; +import static org.osoa.sca.Version.XML_NAMESPACE_1_0; + +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.deployer.CompositeClassLoader; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.model.CompositeImplementation; +import org.apache.tuscany.spi.services.artifact.Artifact; +import org.apache.tuscany.spi.services.artifact.ArtifactRepository; + +/** + * @version $Rev$ $Date$ + */ +public class ImplementationCompositeLoaderTestCase extends TestCase { + private static final QName IMPLEMENTATION_COMPOSITE = new QName(XML_NAMESPACE_1_0, "implementation.composite"); + + private ClassLoader cl; + private ImplementationCompositeLoader loader; + private XMLStreamReader reader; + private DeploymentContext context; + private ArtifactRepository artifactRepository; + + public void testName() throws LoaderException, XMLStreamException, MalformedURLException { + String name = "foo"; + expect(reader.getName()).andReturn(IMPLEMENTATION_COMPOSITE); + expect(reader.getAttributeValue(null, "name")).andReturn(name); + expect(reader.getAttributeValue(null, "group")).andReturn(null); + expect(reader.getAttributeValue(null, "version")).andReturn(null); + expect(reader.getAttributeValue(null, "scdlLocation")).andReturn(null); + expect(reader.getAttributeValue(null, "jarLocation")).andReturn(null); + expect(reader.next()).andReturn(END_ELEMENT); + replay(reader); + + replay(context); + replay(artifactRepository); + + CompositeImplementation impl = loader.load(null, reader, context); + verify(reader); + verify(context); + verify(artifactRepository); + assertEquals(name, impl.getName()); + assertNull(impl.getScdlLocation()); + assertNull(impl.getClassLoader()); + } + + public void testWithArtifact() throws LoaderException, XMLStreamException, MalformedURLException { + String name = "foo"; + expect(reader.getName()).andReturn(IMPLEMENTATION_COMPOSITE); + expect(reader.getAttributeValue(null, "name")).andReturn(name); + expect(reader.getAttributeValue(null, "group")).andReturn("com.example"); + expect(reader.getAttributeValue(null, "version")).andReturn("1.0"); + expect(reader.getAttributeValue(null, "scdlLocation")).andReturn(null); + expect(reader.getAttributeValue(null, "jarLocation")).andReturn(null); + expect(reader.next()).andReturn(END_ELEMENT); + replay(reader); + + expect(context.getClassLoader()).andReturn(cl); + replay(context); + URL url = new URL("http://www.example.com/sca/base.jar"); + artifactRepository.resolve(artifactMatcher(url, "com.example", name, "1.0")); + replay(artifactRepository); + + CompositeImplementation impl = loader.load(null, reader, context); + verify(reader); + verify(context); + verify(artifactRepository); + assertEquals(name, impl.getName()); + assertEquals(new URL("jar:http://www.example.com/sca/base.jar!/META-INF/sca/default.scdl"), impl.getScdlLocation()); + assertTrue(impl.getClassLoader() instanceof CompositeClassLoader); + } + + public void testWithScdlLocation() throws LoaderException, XMLStreamException, MalformedURLException { + String name = "foo"; + expect(reader.getName()).andReturn(IMPLEMENTATION_COMPOSITE); + expect(reader.getAttributeValue(null, "name")).andReturn(name); + expect(reader.getAttributeValue(null, "group")).andReturn(null); + expect(reader.getAttributeValue(null, "version")).andReturn(null); + expect(reader.getAttributeValue(null, "scdlLocation")).andReturn("bar.scdl"); + expect(reader.getAttributeValue(null, "jarLocation")).andReturn(null); + expect(reader.next()).andReturn(END_ELEMENT); + replay(reader); + + expect(context.getScdlLocation()).andReturn(new URL("http://www.example.com/sca/base.scdl")); + expect(context.getClassLoader()).andReturn(cl); + replay(context); + replay(artifactRepository); + + CompositeImplementation impl = loader.load(null, reader, context); + verify(reader); + verify(context); + verify(artifactRepository); + assertEquals(name, impl.getName()); + assertEquals(new URL("http://www.example.com/sca/bar.scdl"), impl.getScdlLocation()); + assertSame(cl, impl.getClassLoader()); + } + + public void testWithJarLocation() throws LoaderException, XMLStreamException, MalformedURLException { + String name = "foo"; + expect(reader.getName()).andReturn(IMPLEMENTATION_COMPOSITE); + expect(reader.getAttributeValue(null, "name")).andReturn(name); + expect(reader.getAttributeValue(null, "group")).andReturn(null); + expect(reader.getAttributeValue(null, "version")).andReturn(null); + expect(reader.getAttributeValue(null, "scdlLocation")).andReturn(null); + expect(reader.getAttributeValue(null, "jarLocation")).andReturn("bar.jar"); + expect(reader.next()).andReturn(END_ELEMENT); + replay(reader); + + expect(context.getScdlLocation()).andReturn(new URL("http://www.example.com/sca/base.scdl")); + expect(context.getClassLoader()).andReturn(cl); + replay(context); + replay(artifactRepository); + + CompositeImplementation impl = loader.load(null, reader, context); + verify(reader); + verify(context); + verify(artifactRepository); + assertEquals(name, impl.getName()); + assertEquals(new URL("jar:http://www.example.com/sca/bar.jar!/META-INF/sca/default.scdl"), + impl.getScdlLocation()); + } + + protected void setUp() throws Exception { + super.setUp(); + artifactRepository = createMock(ArtifactRepository.class); + reader = createMock(XMLStreamReader.class); + context = createMock(DeploymentContext.class); + cl = getClass().getClassLoader(); + loader = new ImplementationCompositeLoader(null, artifactRepository); + } + + protected static Artifact artifactMatcher(final URL url, + final String group, + final String name, + final String version) { + reportMatcher(new IArgumentMatcher() { + + public boolean matches(Object object) { + if (!(object instanceof Artifact)) { + return false; + } + + Artifact artifact = (Artifact) object; + boolean match = group.equals(artifact.getGroup()) && + name.equals(artifact.getName()) && + version.equals(artifact.getVersion()) && + "jar".equals(artifact.getType()); + if (match) { + artifact.setUrl(url); + } + return match; + } + + public void appendTo(StringBuffer stringBuffer) { + stringBuffer.append(group).append(':').append(name).append(':').append(version); + } + }); + return null; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/JavaObjectRegistrationTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/JavaObjectRegistrationTestCase.java new file mode 100644 index 0000000000..c3267f8ec6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/composite/JavaObjectRegistrationTestCase.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.core.implementation.composite; + +import javax.naming.ConfigurationException; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.DuplicateNameException; + +import junit.framework.TestCase; +import org.apache.tuscany.core.component.event.CompositeStart; +import org.apache.tuscany.core.component.event.CompositeStop; + +/** + * @version $Rev$ $Date$ + */ +public class JavaObjectRegistrationTestCase extends TestCase { + private CompositeComponent composite; + + public void testRegistration() throws Exception { + MockComponent instance = new MockComponent(); + composite.registerJavaObject("foo", MockComponent.class, instance); + MockComponent resolvedInstance = (MockComponent) composite.getSystemChild("foo").getServiceInstance(); + assertSame(instance, resolvedInstance); + } + + public void testDuplicateRegistration() throws ConfigurationException { + MockComponent instance = new MockComponent(); + composite.registerJavaObject("foo", MockComponent.class, instance); + try { + composite.registerJavaObject("foo", MockComponent.class, instance); + fail(); + } catch (DuplicateNameException e) { + // ok + } + } + + public void testSystemAutowireToObject() { + MockComponent instance = new MockComponent(); + composite.registerJavaObject("foo", MockComponent.class, instance); + assertSame(instance, composite.resolveSystemInstance(MockComponent.class)); + assertNull(composite.resolveSystemExternalInstance(MockComponent.class)); + } + + public void testApplicationAutowireToObject() { + MockComponent instance = new MockComponent(); + composite.registerJavaObject("foo", MockComponent.class, instance); + assertNull(composite.resolveInstance(MockComponent.class)); + assertNull(composite.resolveExternalInstance(MockComponent.class)); + } + + protected void setUp() throws Exception { + super.setUp(); + composite = new CompositeComponentImpl(null, null, null, null); + composite.start(); + composite.publish(new CompositeStart(this, null)); + } + + protected void tearDown() throws Exception { + composite.publish(new CompositeStop(this, null)); + composite.stop(); + super.tearDown(); + } + + private static class MockComponent { + public String hello(String message) { + return message; + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/AsyncJavaTargetInvokerTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/AsyncJavaTargetInvokerTestCase.java new file mode 100644 index 0000000000..77e48991d5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/AsyncJavaTargetInvokerTestCase.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import java.lang.reflect.Method; + +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.services.work.WorkScheduler; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.MessageImpl; + +import junit.framework.TestCase; +import static org.apache.tuscany.core.implementation.java.mock.MockFactory.createJavaComponent; +import org.apache.tuscany.core.implementation.java.mock.components.AsyncTarget; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.getCurrentArguments; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import org.easymock.IAnswer; + +/** + * @version $Rev$ $Date$ + */ +public class AsyncJavaTargetInvokerTestCase extends TestCase { + + public void testInvoke() throws Exception { + AsyncTarget target = createMock(AsyncTarget.class); + target.invoke(); + expectLastCall().once(); + replay(target); + JavaAtomicComponent component = createJavaComponent(target); + AsyncMonitor monitor = createMock(AsyncMonitor.class); + replay(monitor); + + Message msg = new MessageImpl(); + Object id = new Object(); + msg.setMessageId(id); + + WorkContext context = createMock(WorkContext.class); + context.setCurrentMessageId(null); + context.setCurrentCorrelationId(id); + replay(context); + Method method = AsyncTarget.class.getMethod("invoke"); + method.setAccessible(true); + InboundWire wire = createMock(InboundWire.class); + AsyncJavaTargetInvoker invoker = + new AsyncJavaTargetInvoker(method, wire, component, monitor, context); + invoker.invoke(msg); + verify(target); + } + + public void testClone() throws Exception { + AsyncTarget target = createMock(AsyncTarget.class); + target.invoke(); + expectLastCall().once(); + replay(target); + JavaAtomicComponent component = createJavaComponent(target); + AsyncMonitor monitor = createMock(AsyncMonitor.class); + replay(monitor); + WorkScheduler scheduler = createMock(WorkScheduler.class); + scheduler.scheduleWork(isA(Runnable.class)); + expectLastCall().andStubAnswer(new IAnswer<Object>() { + public Object answer() throws Throwable { + Runnable runnable = (Runnable) getCurrentArguments()[0]; + runnable.run(); + return null; + } + }); + replay(scheduler); + WorkContext context = createMock(WorkContext.class); + InboundWire wire = createMock(InboundWire.class); + Method method = AsyncTarget.class.getMethod("invoke"); + method.setAccessible(true); + AsyncJavaTargetInvoker invoker = + new AsyncJavaTargetInvoker(method, wire, component, monitor, context); + AsyncJavaTargetInvoker clone = invoker.clone(); + Message msg = new MessageImpl(); + clone.invoke(msg); + verify(target); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/DifferentInterfaceWireTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/DifferentInterfaceWireTestCase.java new file mode 100644 index 0000000000..64a573c6e5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/DifferentInterfaceWireTestCase.java @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.model.Scope; + +import junit.framework.TestCase; +import org.apache.tuscany.core.implementation.java.mock.MockFactory; +import org.apache.tuscany.core.implementation.java.mock.components.OtherTarget; +import org.apache.tuscany.core.implementation.java.mock.components.OtherTargetImpl; +import org.apache.tuscany.core.implementation.java.mock.components.Source; +import org.apache.tuscany.core.implementation.java.mock.components.SourceImpl; +import org.apache.tuscany.core.implementation.java.mock.components.Target; +import org.easymock.EasyMock; +import org.easymock.IAnswer; + + +/** + * Tests wires that have different interfaces on the source and target side + * + * @version $Rev$ $Date$ + */ +public class DifferentInterfaceWireTestCase extends TestCase { + + public void testDifferentInterfaceInjection() throws Exception { + Map<String, Member> members = new HashMap<String, Member>(); + Method m = SourceImpl.class.getMethod("setTarget", Target.class); + members.put("target", m); + ScopeContainer scope = createMock(); + scope.start(); + Map<String, AtomicComponent> contexts = + MockFactory.createWiredComponents("source", + SourceImpl.class, + Target.class, + scope, + members, + "target", + OtherTarget.class, + OtherTargetImpl.class, + scope); + AtomicComponent sourceComponent = contexts.get("source"); + Source source = (Source) sourceComponent.getServiceInstance(); + Target target = source.getTarget(); + assertTrue(Proxy.isProxyClass(target.getClass())); + assertNotNull(target); + scope.stop(); + EasyMock.verify(scope); + } + + public void testDifferentInterfaceMultiplicityInjection() throws Exception { + Map<String, Member> members = new HashMap<String, Member>(); + Method m = SourceImpl.class.getMethod("setTargets", List.class); + members.put("target", m); + ScopeContainer scope = createMock(); + scope.start(); + Map<String, AtomicComponent> contexts = + MockFactory.createWiredMultiplicity("source", SourceImpl.class, Target.class, scope, + "target", OtherTarget.class, OtherTargetImpl.class, members, scope); + AtomicComponent sourceComponent = contexts.get("source"); + Source source = (Source) sourceComponent.getServiceInstance(); + List<Target> targets = source.getTargets(); + assertEquals(1, targets.size()); + Target target = targets.get(0); + target.setString("foo"); + assertEquals("foo", target.getString()); + assertTrue(Proxy.isProxyClass(target.getClass())); + scope.stop(); + EasyMock.verify(scope); + } + + protected void setUp() throws Exception { + super.setUp(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + private ScopeContainer createMock() { + ScopeContainer scope = EasyMock.createMock(ScopeContainer.class); + scope.start(); + scope.stop(); + scope.register(EasyMock.isA(AtomicComponent.class)); + EasyMock.expectLastCall().atLeastOnce(); + EasyMock.expect(scope.getScope()).andReturn(Scope.MODULE).atLeastOnce(); + scope.getInstance(EasyMock.isA(AtomicComponent.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + private Map<AtomicComponent, Object> cache = new HashMap<AtomicComponent, Object>(); + + public Object answer() throws Throwable { + AtomicComponent component = (AtomicComponent) EasyMock.getCurrentArguments()[0]; + Object instance = cache.get(component); + if (instance == null) { + instance = component.createInstance(); + cache.put(component, instance); + } + return instance; + } + }).anyTimes(); + EasyMock.replay(scope); + return scope; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/GetServiceByNameTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/GetServiceByNameTestCase.java new file mode 100644 index 0000000000..4695866232 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/GetServiceByNameTestCase.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; + +import junit.framework.TestCase; +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.core.implementation.java.mock.components.Target; +import org.apache.tuscany.core.implementation.java.mock.components.TargetImpl; +import org.apache.tuscany.core.injection.PojoObjectFactory; +import org.apache.tuscany.core.wire.jdk.JDKWireService; +import org.easymock.EasyMock; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; + +/** + * @version $$Rev$$ $$Date$$ + */ +public class GetServiceByNameTestCase extends TestCase { + + public void testServiceLocate() throws Exception { + ScopeContainer scope = createMock(ScopeContainer.class); + scope.register(EasyMock.isA(JavaAtomicComponent.class)); + expect(scope.getScope()).andReturn(Scope.MODULE); + replay(scope); + PojoConfiguration configuration = new PojoConfiguration(); + configuration.setScopeContainer(scope); + configuration.setInstanceFactory(new PojoObjectFactory<TargetImpl>(TargetImpl.class.getConstructor())); + configuration.addServiceInterface(Target.class); + configuration.setWireService(new JDKWireService()); + final JavaAtomicComponent component = new JavaAtomicComponent("target", configuration, null); + + InboundWire wire = createMock(InboundWire.class); + + JavaServiceContract contract = new JavaServiceContract(Target.class); + EasyMock.expect(wire.getServiceContract()).andReturn(contract).anyTimes(); + expect(wire.getServiceName()).andReturn("Target"); + Map<Operation<?>, InboundInvocationChain> chains = new HashMap<Operation<?>, InboundInvocationChain>(); + expect(wire.getInvocationChains()).andReturn(chains); + expect(wire.getCallbackReferenceName()).andReturn(null); + replay(wire); + component.addInboundWire(wire); + component.prepare(); + component.start(); + assertTrue(component.getServiceInstance("Target") instanceof Target); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponentMetadataInjectionTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponentMetadataInjectionTestCase.java new file mode 100644 index 0000000000..a907e047b8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponentMetadataInjectionTestCase.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import junit.framework.TestCase; + +/** + * Tests SCA metadata such as <code>@ComponentName</code> and <code>@SCAObject</code> are handled properly + * + * @version $Rev$ $Date$ + */ +public class JavaAtomicComponentMetadataInjectionTestCase extends TestCase { + + public void testComponentNameSet() throws Exception { + } + + public void testModuleContextSet() throws Exception { + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponentNegativeMetadataTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponentNegativeMetadataTestCase.java new file mode 100644 index 0000000000..365de8e41f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/JavaAtomicComponentNegativeMetadataTestCase.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import junit.framework.TestCase; + + +/** + * Performs rudimentary negative testing by using malformed metadata on a POJO + * + * @version $Rev $Date + */ +public class JavaAtomicComponentNegativeMetadataTestCase extends TestCase { + + /** + * Tests that a pojo with <code>@ComponentName</code> specified on a non-String type generates an error. + * <p/> + * <strong>NB:</strong> the test assumes an error with a message containing "@ComponentName" is generated + */ + public void testBadNameType() throws Exception { +// CompositeComponent mc = new CompositeComponentImpl(); +// mc.setName("mc"); +// try { +// MockFactory.createPojoContext("BadNamePojo", BadNamePojo.class, Scope.MODULE, mc); +// } catch (NoSuchMethodException e) { +// if (e.getMessage().indexOf("@ComponentName") < 0) { +// throw e; +// } +// } +// + } + + /** + * Tests that a pojo with <code>@Context</code> specified on a non-ModuleContext type generates an error. + * <p/> + * <strong>NB:</strong> the test assumes an error with a message containing "@Context" is generated + */ + public void testContextType() throws Exception { +// CompositeComponent mc = new CompositeComponentImpl(); +// mc.setName("mc"); +// try { +// MockFactory.createPojoContext("BadContextPojo", BadContextPojo.class, Scope.MODULE, mc); +// } catch (NoSuchMethodException e) { +// if (e.getMessage().indexOf("@SCAObject") < 0) { +// throw e; +// } +// } +// + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/JavaComponentBuilderTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/JavaComponentBuilderTestCase.java new file mode 100644 index 0000000000..4877d06aba --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/JavaComponentBuilderTestCase.java @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import java.lang.reflect.Constructor; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.model.ServiceContract; + +import junit.framework.TestCase; +import org.apache.tuscany.core.deployer.RootDeploymentContext; +import org.apache.tuscany.core.implementation.composite.CompositeComponentImpl; +import org.apache.tuscany.core.implementation.java.mock.components.Source; +import org.apache.tuscany.core.implementation.java.mock.components.SourceImpl; +import org.apache.tuscany.core.implementation.java.mock.components.Target; +import org.apache.tuscany.core.wire.jdk.JDKWireService; +import org.easymock.EasyMock; +import org.easymock.IAnswer; + +/** + * @version $$Rev$$ $$Date$$ + */ +public class JavaComponentBuilderTestCase extends TestCase { + private DeploymentContext deploymentContext; + + public void testBuild() throws Exception { + CompositeComponent parent = new CompositeComponentImpl(null, null, null, null); + + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> sourceType = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + sourceType.setImplementationScope(Scope.MODULE); + JavaMappedReference reference = new JavaMappedReference(); + reference.setName("target"); + reference.setMember(SourceImpl.class.getMethod("setTarget", Target.class)); + sourceType.add(reference); + + ServiceContract<?> sourceContract = new JavaServiceContract(Source.class); + JavaMappedService sourceServiceDefinition = new JavaMappedService(); + sourceServiceDefinition.setName("Source"); + sourceServiceDefinition.setServiceContract(sourceContract); + + sourceType.add(sourceServiceDefinition); + Constructor<SourceImpl> constructor = SourceImpl.class.getConstructor((Class[]) null); + sourceType.setConstructorDefinition(new ConstructorDefinition<SourceImpl>(constructor)); + JavaImplementation sourceImpl = new JavaImplementation(); + sourceImpl.setComponentType(sourceType); + sourceImpl.setImplementationClass(SourceImpl.class); + ComponentDefinition<JavaImplementation> sourceComponentDefinition = + new ComponentDefinition<JavaImplementation>(sourceImpl); + + JavaComponentBuilder builder = new JavaComponentBuilder(); + builder.setWireService(new JDKWireService()); + JavaAtomicComponent component = + (JavaAtomicComponent) builder.build(parent, sourceComponentDefinition, deploymentContext); + deploymentContext.getModuleScope().start(); + component.start(); + Source source = (Source) component.getServiceInstance(); + assertNotNull(source); + component.stop(); + } + + protected void setUp() throws Exception { + super.setUp(); + deploymentContext = new RootDeploymentContext(null, null, createMock(), null); + } + + private ScopeContainer createMock() { + ScopeContainer scope = EasyMock.createMock(ScopeContainer.class); + scope.start(); + scope.stop(); + scope.register(EasyMock.isA(AtomicComponent.class)); + EasyMock.expectLastCall().atLeastOnce(); + EasyMock.expect(scope.getScope()).andReturn(Scope.MODULE).atLeastOnce(); + scope.getInstance(EasyMock.isA(AtomicComponent.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + private Map<AtomicComponent, Object> cache = new HashMap<AtomicComponent, Object>(); + + public Object answer() throws Throwable { + AtomicComponent component = (AtomicComponent) EasyMock.getCurrentArguments()[0]; + Object instance = cache.get(component); + if (instance == null) { + instance = component.createInstance(); + cache.put(component, instance); + } + return instance; + } + }).anyTimes(); + EasyMock.replay(scope); + return scope; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/JavaReferenceWireTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/JavaReferenceWireTestCase.java new file mode 100644 index 0000000000..5afc8b6511 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/JavaReferenceWireTestCase.java @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import java.lang.reflect.Constructor; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.WireService; + +import junit.framework.TestCase; +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.core.implementation.java.mock.components.Source; +import org.apache.tuscany.core.implementation.java.mock.components.SourceImpl; +import org.apache.tuscany.core.implementation.java.mock.components.Target; +import org.apache.tuscany.core.implementation.java.mock.components.TargetImpl; +import org.apache.tuscany.core.injection.PojoObjectFactory; +import org.easymock.EasyMock; +import org.easymock.IAnswer; + +/** + * Validates wiring from a Java atomic context + * + * @version $$Rev$$ $$Date$$ + */ +public class JavaReferenceWireTestCase extends TestCase { + + public void testReferenceSet() throws Exception { + ScopeContainer scope = createMock(); + scope.start(); + final Target target = new TargetImpl(); + PojoConfiguration configuration = new PojoConfiguration(); + configuration.addReferenceSite("target", SourceImpl.class.getMethod("setTarget", Target.class)); + configuration.addServiceInterface(Source.class); + Constructor<SourceImpl> ctr = SourceImpl.class.getConstructor(); + configuration.setInstanceFactory(new PojoObjectFactory<SourceImpl>(ctr)); + configuration.setScopeContainer(scope); + OutboundWire wire = EasyMock.createMock(OutboundWire.class); + wire.getInvocationChains(); + EasyMock.expectLastCall().andReturn(new HashMap<Operation<?>, OutboundInvocationChain>()); + EasyMock.expect(wire.getReferenceName()).andReturn("target").atLeastOnce(); + EasyMock.replay(wire); + WireService service = EasyMock.createMock(WireService.class); + EasyMock.expect(service.createProxy(EasyMock.eq(wire))).andAnswer(new IAnswer<Object>() { + public Object answer() throws Throwable { + OutboundWire wire = (OutboundWire) EasyMock.getCurrentArguments()[0]; + wire.getInvocationChains(); + return target; + } + + }).atLeastOnce(); + EasyMock.replay(service); + configuration.setWireService(service); + JavaAtomicComponent sourceContext = new JavaAtomicComponent("source", configuration, null); + sourceContext.addOutboundWire(wire); + sourceContext.start(); + Source source = (Source) sourceContext.getServiceInstance(); + assertSame(target, source.getTarget()); + scope.stop(); + EasyMock.verify(wire); + EasyMock.verify(scope); + EasyMock.verify(service); + } + + private ScopeContainer createMock() { + ScopeContainer scope = EasyMock.createMock(ScopeContainer.class); + scope.start(); + scope.stop(); + scope.register(EasyMock.isA(AtomicComponent.class)); + EasyMock.expectLastCall().atLeastOnce(); + EasyMock.expect(scope.getScope()).andReturn(Scope.MODULE).atLeastOnce(); + scope.getInstance(EasyMock.isA(AtomicComponent.class)); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + private Map<AtomicComponent, Object> cache = new HashMap<AtomicComponent, Object>(); + + public Object answer() throws Throwable { + AtomicComponent component = (AtomicComponent) EasyMock.getCurrentArguments()[0]; + Object instance = cache.get(component); + if (instance == null) { + instance = component.createInstance(); + cache.put(component, instance); + } + return instance; + } + }).anyTimes(); + EasyMock.replay(scope); + return scope; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/JavaTargetInvokerTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/JavaTargetInvokerTestCase.java new file mode 100644 index 0000000000..018273be28 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/JavaTargetInvokerTestCase.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.core.implementation.java; + +import java.lang.reflect.Method; + +import org.apache.tuscany.spi.component.ScopeContainer; + +import junit.framework.Assert; +import junit.framework.TestCase; +import org.apache.tuscany.core.component.scope.ModuleScopeContainer; +import org.apache.tuscany.core.implementation.java.mock.MockFactory; + +public class JavaTargetInvokerTestCase extends TestCase { + + private Method echoMethod; + + public JavaTargetInvokerTestCase() { + super(); + } + + public JavaTargetInvokerTestCase(String arg0) { + super(arg0); + } + + public void setUp() throws Exception { + echoMethod = Echo.class.getDeclaredMethod("echo", String.class); + Assert.assertNotNull(echoMethod); + } + + public void testScopedInvoke() throws Exception { + ScopeContainer scope = new ModuleScopeContainer(null); + scope.start(); + JavaAtomicComponent component = + MockFactory.createJavaComponent("foo", scope, Echo.class); + scope.register(component); + JavaTargetInvoker invoker = new JavaTargetInvoker(echoMethod, component); + invoker.setCacheable(false); + assertEquals("foo", invoker.invokeTarget("foo")); + scope.stop(); + } + + public void testClone() throws Exception { + ScopeContainer scope = new ModuleScopeContainer(null); + scope.start(); + JavaAtomicComponent component = + MockFactory.createJavaComponent("foo", scope, Echo.class); + scope.register(component); + JavaTargetInvoker invoker = new JavaTargetInvoker(echoMethod, component); + invoker.setCacheable(false); + JavaTargetInvoker clone = invoker.clone(); + assertEquals("foo", clone.invokeTarget("foo")); + scope.stop(); + } + + public static class Echo { + public String echo(String message) throws Exception { + return message; + } + + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/MultiplicityTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/MultiplicityTestCase.java new file mode 100644 index 0000000000..92c8c7acfa --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/MultiplicityTestCase.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import junit.framework.TestCase; + + +/** + * Tests wires that are configured with a multiplicity + * + * @version $Rev$ $Date$ + */ +public class MultiplicityTestCase extends TestCase { + + public void testMultiplicity() throws Exception { +// CompositeComponent context = createContext(); +// context.start(); +// context.registerModelObject(MockFactory.createModuleWithWiredComponents(Scope.MODULE, Scope.MODULE)); +// context.publish(new CompositeStart(this)); +// Source source = (Source) ((AtomicComponent) context.getContext("source")).getTargetInstance(); +// Assert.assertNotNull(source); +// Target target = (Target) ((AtomicComponent)context.getContext("target")).getTargetInstance(); +// Assert.assertNotNull(target); +// // test setter injection +// List<Target> targets = source.getTargets(); +// Assert.assertEquals(1, targets.size()); +// +// // test field injection +// targets = source.getTargetsThroughField(); +// Assert.assertEquals(1, targets.size()); + } + +// private CompositeComponent createContext() { +// CompositeComponentImpl context = new CompositeComponentImpl(); +// context.setName("system.context"); +// List<ContextFactoryBuilder>builders = MockFactory.createSystemBuilders(); +// WireService wireService = new DefaultWireFactoryService(new MessageFactoryImpl(), +// new JDKWireFactoryService(), new DefaultPolicyBuilderRegistry()); +// builders.add(new JavaContextFactoryBuilder(wireService)); +// List<WireBuilder> wireBuilders = new ArrayList<WireBuilder>(); +// wireBuilders.add(new JavaTargetWireBuilder()); +// context.setConfigurationContext(new MockConfigContext(builders,wireBuilders)); +// return context; +// } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/ReferenceInjectionTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/ReferenceInjectionTestCase.java new file mode 100644 index 0000000000..e6309e0c97 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/ReferenceInjectionTestCase.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java; + +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.ScopeContainer; + +import junit.framework.TestCase; +import org.apache.tuscany.core.implementation.java.mock.MockFactory; +import org.apache.tuscany.core.implementation.java.mock.components.Source; +import org.apache.tuscany.core.implementation.java.mock.components.SourceImpl; +import org.apache.tuscany.core.implementation.java.mock.components.Target; +import org.apache.tuscany.core.implementation.java.mock.components.TargetImpl; +import org.apache.tuscany.core.component.scope.ModuleScopeContainer; + +/** + * @version $$Rev$$ $$Date$$ + */ +public class ReferenceInjectionTestCase extends TestCase { + + private Map<String, Member> members; + + public void testProxiedReferenceInjection() throws Exception { + ScopeContainer scope = new ModuleScopeContainer(null); + scope.start(); + Map<String, AtomicComponent> contexts = + MockFactory.createWiredComponents("source", SourceImpl.class, scope, + members, "target", Target.class, TargetImpl.class, scope); + AtomicComponent sourceComponent = contexts.get("source"); + Source source = (Source) sourceComponent.getServiceInstance(); + Target target = source.getTarget(); + assertTrue(Proxy.isProxyClass(target.getClass())); + + assertNotNull(target); + scope.stop(); + } + + protected void setUp() throws Exception { + super.setUp(); + members = new HashMap<String, Member>(); + Method m = SourceImpl.class.getMethod("setTarget", Target.class); + members.put("target", m); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/integration/component/CallbackInvocationTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/integration/component/CallbackInvocationTestCase.java new file mode 100644 index 0000000000..718fd50845 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/integration/component/CallbackInvocationTestCase.java @@ -0,0 +1,266 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java.integration.component; + +import java.lang.reflect.Method; +import java.net.URI; +import java.net.URISyntaxException; + +import org.osoa.sca.annotations.Callback; + +import org.apache.tuscany.spi.builder.Connector; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.ReferenceTarget; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.services.work.WorkScheduler; +import org.apache.tuscany.spi.wire.WireService; + +import junit.framework.TestCase; +import org.apache.tuscany.core.builder.ConnectorImpl; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.component.scope.ModuleScopeContainer; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.implementation.java.JavaAtomicComponent; +import org.apache.tuscany.core.implementation.java.JavaComponentBuilder; +import org.apache.tuscany.core.implementation.java.JavaImplementation; +import org.apache.tuscany.core.wire.jdk.JDKWireService; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.getCurrentArguments; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import org.easymock.IAnswer; + +/** + * Verifies callback integration scenarios. + * + * @version $Rev$ $Date$ + */ +public class CallbackInvocationTestCase extends TestCase { + + private ScopeContainer container; + private DeploymentContext context; + private JavaComponentBuilder builder; + private WireService wireService; + private WorkScheduler scheduler; + private WorkContext workContext; + /** + * Verifies callback wires are built and callback invocations are handled properly + */ + public void testComponentToComponentCallback() throws Exception { + ComponentDefinition<JavaImplementation> targetDefinition = createTarget(); + JavaAtomicComponent fooComponent = + (JavaAtomicComponent) builder.build(null, targetDefinition, context); + wireService.createWires(fooComponent, targetDefinition); + container.register(fooComponent); + + CompositeComponent parent = createMock(CompositeComponent.class); + parent.getChild(isA(String.class)); + expectLastCall().andReturn(fooComponent).anyTimes(); + replay(parent); + + ComponentDefinition<JavaImplementation> sourceDefinition = createSource("fooClient"); + JavaAtomicComponent clientComponent = + (JavaAtomicComponent) builder.build(parent, sourceDefinition, context); + wireService.createWires(clientComponent, sourceDefinition); + container.register(clientComponent); + + Connector connector = new ConnectorImpl(new JDKWireService(), null, scheduler , workContext); + + connector.connect(clientComponent); + FooClient client = (FooClient) clientComponent.getServiceInstance(); + client.invoke(); + assertTrue(client.invoked); + } + + /** + * Verifies a callback in response to an invocation from two different client components is routed back to the + * appropriate client. + */ + public void testTwoSourceComponentToComponentCallback() throws Exception { + ComponentDefinition<JavaImplementation> targetDefinition = createTarget(); + JavaAtomicComponent fooComponent = + (JavaAtomicComponent) builder.build(null, targetDefinition, context); + wireService.createWires(fooComponent, targetDefinition); + container.register(fooComponent); + + CompositeComponent parent = createMock(CompositeComponent.class); + parent.getChild(isA(String.class)); + expectLastCall().andReturn(fooComponent).anyTimes(); + replay(parent); + + ComponentDefinition<JavaImplementation> sourceDefinition1 = createSource("fooCleint1"); + ComponentDefinition<JavaImplementation> sourceDefinition2 = createSource("fooCleint2"); + JavaAtomicComponent clientComponent1 = + (JavaAtomicComponent) builder.build(parent, sourceDefinition1, context); + wireService.createWires(clientComponent1, sourceDefinition1); + container.register(clientComponent1); + JavaAtomicComponent clientComponent2 = + (JavaAtomicComponent) builder.build(parent, sourceDefinition2, context); + wireService.createWires(clientComponent2, sourceDefinition2); + container.register(clientComponent2); + + Connector connector = new ConnectorImpl(new JDKWireService(), null, scheduler, workContext); + connector.connect(clientComponent1); + connector.connect(clientComponent2); + FooClient client1 = (FooClient) clientComponent1.getServiceInstance(); + client1.invoke(); + assertTrue(client1.invoked); + FooClient client2 = (FooClient) clientComponent2.getServiceInstance(); + client2.invoke(); + assertTrue(client2.invoked); + } + + + private ComponentDefinition<JavaImplementation> createTarget() throws NoSuchMethodException, + InvalidServiceContractException { + ConstructorDefinition<FooImpl> ctorDef = new ConstructorDefinition<FooImpl>(FooImpl.class.getConstructor()); + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + type.setConstructorDefinition(ctorDef); + type.setImplementationScope(Scope.MODULE); + Method method = FooImpl.class.getMethod("setCallback", FooCallback.class); + JavaInterfaceProcessorRegistry registry = new JavaInterfaceProcessorRegistryImpl(); + ServiceContract<?> contract = registry.introspect(Foo.class); + contract.setCallbackClass(FooCallback.class); + contract.setCallbackName("callback"); + JavaMappedService mappedService = new JavaMappedService("Foo", contract, false, "callback", method); + type.getServices().put("Foo", mappedService); + + JavaImplementation impl = new JavaImplementation(); + impl.setComponentType(type); + impl.setImplementationClass(FooImpl.class); + return new ComponentDefinition<JavaImplementation>("foo", impl); + } + + private ComponentDefinition<JavaImplementation> createSource(String name) + throws NoSuchMethodException, URISyntaxException, InvalidServiceContractException { + ConstructorDefinition<FooClient> ctorDef = + new ConstructorDefinition<FooClient>(FooClient.class.getConstructor()); + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + type.setConstructorDefinition(ctorDef); + type.setImplementationScope(Scope.MODULE); + Method method = FooClient.class.getMethod("setFoo", Foo.class); + JavaInterfaceProcessorRegistry registry = new JavaInterfaceProcessorRegistryImpl(); + ServiceContract<?> contract = registry.introspect(Foo.class); + contract.setCallbackClass(FooCallback.class); + contract.setCallbackName("callback"); + JavaMappedReference mappedReference = new JavaMappedReference("foo", contract, method); + type.getReferences().put("foo", mappedReference); + ReferenceTarget refTarget = new ReferenceTarget(); + refTarget.setReferenceName("foo"); + refTarget.getTargets().add(new URI("foo")); + JavaImplementation impl = new JavaImplementation(); + impl.setComponentType(type); + impl.setImplementationClass(FooClient.class); + ComponentDefinition<JavaImplementation> def = new ComponentDefinition<JavaImplementation>(name, impl); + def.getReferenceTargets().put("foo", refTarget); + return def; + } + + @Callback(FooCallback.class) + public static interface Foo { + void call(); + } + + public static class FooImpl implements Foo { + private FooCallback callback; + + public FooImpl() { + } + + @Callback + public void setCallback(FooCallback callback) { + this.callback = callback; + } + + public void call() { + callback.callback(); + } + } + + public static class FooClient implements FooCallback { + + private Foo foo; + private boolean invoked; + + public FooClient() { + } + + public void setFoo(Foo foo) { + this.foo = foo; + } + + public void callback() { + if (invoked) { + fail(); + } + invoked = true; + } + + public void invoke() { + foo.call(); + } + } + + public interface FooCallback { + void callback(); + } + + protected void setUp() throws Exception { + super.setUp(); + wireService = new JDKWireService(); + container = new ModuleScopeContainer(); + container.start(); + context = createMock(DeploymentContext.class); + context.getModuleScope(); + expectLastCall().andReturn(container).anyTimes(); + replay(context); + + scheduler = createMock(WorkScheduler.class); + scheduler.scheduleWork(isA(Runnable.class)); + expectLastCall().andStubAnswer(new IAnswer<Object>() { + public Object answer() throws Throwable { + Runnable runnable = (Runnable) getCurrentArguments()[0]; + runnable.run(); + return null; + } + }); + replay(scheduler); + + builder = new JavaComponentBuilder(); + workContext = new WorkContextImpl(); + builder.setWorkContext(workContext); + builder.setWireService(new JDKWireService(workContext, null)); + builder.setWorkScheduler(scheduler); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/integration/component/OneWayWireInvocationTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/integration/component/OneWayWireInvocationTestCase.java new file mode 100644 index 0000000000..91d31d2db2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/integration/component/OneWayWireInvocationTestCase.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java.integration.component; + +import java.lang.reflect.Method; +import java.util.Map; + +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.services.work.WorkScheduler; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.MessageImpl; +import org.apache.tuscany.spi.wire.WireService; + +import junit.framework.TestCase; +import org.apache.tuscany.core.implementation.java.AsyncJavaTargetInvoker; +import org.apache.tuscany.core.implementation.java.JavaAtomicComponent; +import org.apache.tuscany.core.implementation.java.mock.MockFactory; +import static org.apache.tuscany.core.implementation.java.mock.MockFactory.createServiceWire; +import org.apache.tuscany.core.implementation.java.mock.components.AsyncTarget; +import org.apache.tuscany.core.wire.jdk.JDKWireService; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.getCurrentArguments; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import org.easymock.IAnswer; + +/** + * Verifies non-blocking invocations are properly made through a wire + * + * @version $Rev$ $Date$ + */ +public class OneWayWireInvocationTestCase extends TestCase { + + WireService wireService = new JDKWireService(); + + public void testNoInterceptors() throws Exception { + AsyncTarget target = createMock(AsyncTarget.class); + target.invoke(); + expectLastCall().once(); + replay(target); + JavaAtomicComponent component = MockFactory.createJavaComponent(target); + WorkScheduler scheduler = createMock(WorkScheduler.class); + scheduler.scheduleWork(isA(Runnable.class)); + expectLastCall().andStubAnswer(new IAnswer<Object>() { + public Object answer() throws Throwable { + Runnable runnable = (Runnable) getCurrentArguments()[0]; + runnable.run(); + return null; + } + }); + replay(scheduler); + WorkContext context = createMock(WorkContext.class); + Method method = AsyncTarget.class.getMethod("invoke"); + method.setAccessible(true); + InboundWire inboundWire = createMock(InboundWire.class); + AsyncJavaTargetInvoker invoker = + new AsyncJavaTargetInvoker(method, inboundWire, component, null, context); + InboundWire wire = createServiceWire("foo", AsyncTarget.class, null); + Map<Operation<?>, InboundInvocationChain> chains = wire.getInvocationChains(); + InboundInvocationChain chain = chains.get(wire.getServiceContract().getOperations().get("invoke")); + chain.setTargetInvoker(invoker); + chain.prepare(); + MessageImpl msg = new MessageImpl(); + msg.setTargetInvoker(invoker); + chain.getHeadInterceptor().invoke(msg); + verify(target); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/integration/component/OutboundWireToJavaTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/integration/component/OutboundWireToJavaTestCase.java new file mode 100644 index 0000000000..9ea0cd99e3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/integration/component/OutboundWireToJavaTestCase.java @@ -0,0 +1,229 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java.integration.component; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.FutureTask; + +import org.apache.tuscany.spi.QualifiedName; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.WireService; + +import junit.framework.TestCase; +import org.apache.tuscany.core.builder.ConnectorImpl; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.component.event.CompositeStart; +import org.apache.tuscany.core.component.event.CompositeStop; +import org.apache.tuscany.core.component.event.HttpSessionEnd; +import org.apache.tuscany.core.component.event.HttpSessionStart; +import org.apache.tuscany.core.component.event.RequestEnd; +import org.apache.tuscany.core.component.event.RequestStart; +import org.apache.tuscany.core.component.scope.HttpSessionScopeContainer; +import org.apache.tuscany.core.component.scope.ModuleScopeContainer; +import org.apache.tuscany.core.component.scope.RequestScopeContainer; +import org.apache.tuscany.core.component.scope.StatelessScopeContainer; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.core.implementation.java.JavaAtomicComponent; +import org.apache.tuscany.core.implementation.java.mock.MockFactory; +import org.apache.tuscany.core.implementation.java.mock.components.Target; +import org.apache.tuscany.core.implementation.java.mock.components.TargetImpl; +import org.apache.tuscany.core.injection.PojoObjectFactory; +import org.apache.tuscany.core.wire.OutboundInvocationChainImpl; +import org.apache.tuscany.core.wire.OutboundWireImpl; +import org.apache.tuscany.core.wire.jdk.JDKWireService; +import org.easymock.EasyMock; + +/** + * Validates wiring from a service context to Java atomic contexts by scope + * + * @version $$Rev$$ $$Date$$ + */ +public class OutboundWireToJavaTestCase extends TestCase { + private WorkContext workContext = new WorkContextImpl(); + private WireService wireService = new JDKWireService(new WorkContextImpl(), null); + + public void testToStatelessScope() throws Exception { + StatelessScopeContainer scope = new StatelessScopeContainer(workContext); + scope.start(); + final OutboundWire wire = getWire(scope); + Target service = (Target) wireService.createProxy(wire); + assertNotNull(service); + service.setString("foo"); + assertEquals(null, service.getString()); + scope.stop(); + } + + public void testToRequestScope() throws Exception { + final RequestScopeContainer scope = new RequestScopeContainer(workContext); + scope.start(); + + scope.onEvent(new RequestStart(this)); + + final OutboundWire wire = getWire(scope); + Target service = (Target) wireService.createProxy(wire); + assertNotNull(service); + service.setString("foo"); + + // another request + Executor executor = Executors.newSingleThreadExecutor(); + FutureTask<Void> future = new FutureTask<Void>(new Runnable() { + public void run() { + scope.onEvent(new RequestStart(this)); + Target service2 = (Target) wireService.createProxy(wire); + Target target2 = (Target) wireService.createProxy(wire); + assertEquals(null, service2.getString()); + service2.setString("bar"); + assertEquals("bar", service2.getString()); + assertEquals("bar", target2.getString()); + scope.onEvent(new RequestEnd(this)); + } + }, null); + executor.execute(future); + future.get(); + + assertEquals("foo", service.getString()); + scope.onEvent(new RequestEnd(this)); + scope.stop(); + } + + public void testToSessionScope() throws Exception { + HttpSessionScopeContainer scope = new HttpSessionScopeContainer(workContext); + scope.start(); + Object session1 = new Object(); + workContext.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session1); + scope.onEvent(new HttpSessionStart(this, session1)); + + final OutboundWire wire = getWire(scope); + Target service = (Target) wireService.createProxy(wire); + Target target = (Target) wireService.createProxy(wire); + assertNotNull(service); + service.setString("foo"); + assertEquals("foo", service.getString()); + assertEquals("foo", target.getString()); + + workContext.clearIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER); + + //second session + Object session2 = new Object(); + workContext.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session2); + scope.onEvent(new HttpSessionStart(this, session2)); + + Target service2 = (Target) wireService.createProxy(wire); + assertNotNull(service2); + assertNull(service2.getString()); + Target target2 = (Target) wireService.createProxy(wire); + service2.setString("bar"); + assertEquals("bar", service2.getString()); + assertEquals("bar", target2.getString()); + + scope.onEvent(new HttpSessionEnd(this, session2)); + workContext.clearIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER); + + workContext.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session1); + assertEquals("foo", service.getString()); + + scope.onEvent(new HttpSessionEnd(this, session1)); + + scope.stop(); + } + + public void testToModuleScope() throws Exception { + + ModuleScopeContainer scope = new ModuleScopeContainer(workContext); + scope.start(); + scope.onEvent(new CompositeStart(this, null)); + final OutboundWire wire = getWire(scope); + Target service = (Target) wireService.createProxy(wire); + Target target = (Target) wireService.createProxy(wire); + assertNotNull(service); + service.setString("foo"); + assertEquals("foo", service.getString()); + assertEquals("foo", target.getString()); + scope.onEvent(new CompositeStop(this, null)); + scope.stop(); + } + + private OutboundWire getWire(ScopeContainer scope) throws NoSuchMethodException, + InvalidServiceContractException { + ConnectorImpl connector = new ConnectorImpl(); + + CompositeComponent parent = EasyMock.createMock(CompositeComponent.class); + + PojoConfiguration configuration = new PojoConfiguration(); + configuration.setScopeContainer(scope); + configuration.setInstanceFactory(new PojoObjectFactory<TargetImpl>(TargetImpl.class.getConstructor())); + configuration.addServiceInterface(Target.class); + configuration.setParent(parent); + + JavaAtomicComponent source = new JavaAtomicComponent("source", configuration, null); + OutboundWire outboundWire = createOutboundWire(new QualifiedName("target/Target"), Target.class); + outboundWire.setContainer(source); + source.addOutboundWire(outboundWire); + JavaAtomicComponent target = new JavaAtomicComponent("target", configuration, null); + InboundWire targetWire = MockFactory.createTargetWire("Target", Target.class); + targetWire.setContainer(target); + target.addInboundWire(targetWire); + InboundWire inboundWire = target.getInboundWire("Target"); + inboundWire.setContainer(target); + + EasyMock.expect(parent.getChild("target")).andReturn(target); + EasyMock.replay(parent); + + connector.connect(source); + target.start(); + return outboundWire; + } + + public static <T> OutboundWire createOutboundWire(QualifiedName targetName, Class<T> interfaze) + throws InvalidServiceContractException { + OutboundWire wire = new OutboundWireImpl(); + JavaServiceContract contract = new JavaServiceContract(interfaze); + wire.setServiceContract(contract); + wire.setTargetName(targetName); + wire.addInvocationChains(createInvocationChains(interfaze)); + return wire; + } + + private static Map<Operation<?>, OutboundInvocationChain> createInvocationChains(Class<?> interfaze) + throws InvalidServiceContractException { + Map<Operation<?>, OutboundInvocationChain> invocations = new HashMap<Operation<?>, OutboundInvocationChain>(); + JavaInterfaceProcessorRegistry registry = new JavaInterfaceProcessorRegistryImpl(); + ServiceContract<?> contract = registry.introspect(interfaze); + for (Operation operation : contract.getOperations().values()) { + OutboundInvocationChain chain = new OutboundInvocationChainImpl(operation); + invocations.put(operation, chain); + } + return invocations; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/integration/component/ScopeReferenceTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/integration/component/ScopeReferenceTestCase.java new file mode 100644 index 0000000000..87a8be3a01 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/integration/component/ScopeReferenceTestCase.java @@ -0,0 +1,746 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java.integration.component; + +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.FutureTask; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.component.WorkContext; + +import junit.framework.TestCase; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.component.event.CompositeStart; +import org.apache.tuscany.core.component.event.CompositeStop; +import org.apache.tuscany.core.component.event.HttpSessionEnd; +import org.apache.tuscany.core.component.event.HttpSessionStart; +import org.apache.tuscany.core.component.event.RequestEnd; +import org.apache.tuscany.core.component.event.RequestStart; +import org.apache.tuscany.core.component.scope.HttpSessionScopeContainer; +import org.apache.tuscany.core.component.scope.ModuleScopeContainer; +import org.apache.tuscany.core.component.scope.RequestScopeContainer; +import org.apache.tuscany.core.component.scope.StatelessScopeContainer; +import org.apache.tuscany.core.implementation.java.mock.MockFactory; +import org.apache.tuscany.core.implementation.java.mock.components.Source; +import org.apache.tuscany.core.implementation.java.mock.components.SourceImpl; +import org.apache.tuscany.core.implementation.java.mock.components.Target; +import org.apache.tuscany.core.implementation.java.mock.components.TargetImpl; +import org.apache.tuscany.core.util.JavaIntrospectionHelper; + +/** + * Tests scoping is properly handled for service references + * + * @version $Rev$ $Date$ + */ +public class ScopeReferenceTestCase extends TestCase { + + private Map<String, Member> members; + + /** + * Tests a module-to-module scoped wire + */ + public void testModuleToModule() throws Exception { + ScopeContainer scope = new ModuleScopeContainer(null); + scope.start(); + + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", SourceImpl.class, + scope, members, "target", Target.class, TargetImpl.class, scope); + scope.onEvent(new CompositeStart(this, null)); + AtomicComponent sourceComponent = contexts.get("source"); + AtomicComponent targetComponent = contexts.get("target"); + Source source = (Source) sourceComponent.getServiceInstance(); + Target target = (Target) targetComponent.getServiceInstance(); + assertNull(source.getTarget().getString()); + assertNull(target.getString()); + target.setString("foo"); + assertTrue(Proxy.isProxyClass(source.getTarget().getClass())); + assertEquals("foo", source.getTarget().getString()); + scope.onEvent(new CompositeStop(this, null)); + scope.stop(); + } + + /** + * Tests a module-to-session scoped wire is setup properly by the runtime + */ + public void testModuleToSession() throws Exception { + WorkContext ctx = new WorkContextImpl(); + ScopeContainer moduleScope = new ModuleScopeContainer(ctx); + moduleScope.start(); + ScopeContainer sessionScope = new HttpSessionScopeContainer(ctx); + sessionScope.start(); + + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", SourceImpl.class, + moduleScope, members, "target", Target.class, TargetImpl.class, sessionScope); + moduleScope.onEvent(new CompositeStart(this, null)); + Object session1 = new Object(); + ctx.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session1); + sessionScope.onEvent(new HttpSessionStart(this, session1)); + AtomicComponent sourceComponent = contexts.get("source"); + AtomicComponent targetComponent = contexts.get("target"); + Source source = (Source) sourceComponent.getServiceInstance(); + Target target = (Target) targetComponent.getServiceInstance(); + assertNull(source.getTarget().getString()); + assertNull(target.getString()); + target.setString("foo"); + assertTrue(Proxy.isProxyClass(source.getTarget().getClass())); + assertEquals("foo", source.getTarget().getString()); + ctx.clearIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER); + sessionScope.onEvent(new HttpSessionEnd(this, session1)); + + //second session + Object session2 = new Object(); + ctx.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session2); + sessionScope.onEvent(new HttpSessionStart(this, session2)); + + Target target2 = (Target) targetComponent.getServiceInstance(); + assertFalse("foo".equals(target2.getString())); + + assertFalse("foo".equals(source.getTarget().getString())); + source.getTarget().setString("bar"); + assertEquals("bar", target2.getString()); + assertEquals("bar", source.getTarget().getString()); + sessionScope.onEvent(new HttpSessionEnd(this, session2)); + + ctx.clearIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER); + moduleScope.onEvent(new CompositeStop(this, null)); + sessionScope.stop(); + moduleScope.stop(); + } + + /** + * Tests a module-to-request scoped wire + */ + public void testModuleToRequest() throws Exception { + WorkContext ctx = new WorkContextImpl(); + ScopeContainer moduleScope = new ModuleScopeContainer(ctx); + moduleScope.start(); + final ScopeContainer requestScope = new RequestScopeContainer(ctx); + requestScope.start(); + + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", SourceImpl.class, + moduleScope, members, "target", Target.class, TargetImpl.class, requestScope); + moduleScope.onEvent(new CompositeStart(this, null)); + requestScope.onEvent(new RequestStart(this)); + + AtomicComponent sourceComponent = contexts.get("source"); + final AtomicComponent targetComponent = contexts.get("target"); + final Source source = (Source) sourceComponent.getServiceInstance(); + Target target = (Target) targetComponent.getServiceInstance(); + assertNull(source.getTarget().getString()); + assertNull(target.getString()); + target.setString("foo"); + assertTrue(Proxy.isProxyClass(source.getTarget().getClass())); + assertEquals("foo", source.getTarget().getString()); + + // spin off another request + Executor executor = Executors.newSingleThreadExecutor(); + FutureTask<Void> future = new FutureTask<Void>(new Runnable() { + public void run() { + requestScope.onEvent(new RequestStart(this)); + Target target2 = (Target) targetComponent.getServiceInstance(); + assertFalse("foo".equals(target2.getString())); + assertFalse("foo".equals(source.getTarget().getString())); + source.getTarget().setString("bar"); + assertEquals("bar", target2.getString()); + assertEquals("bar", source.getTarget().getString()); + requestScope.onEvent(new RequestEnd(this)); + } + }, null); + executor.execute(future); + future.get(); + assertEquals("foo", source.getTarget().getString()); + requestScope.onEvent(new RequestEnd(this)); + moduleScope.onEvent(new CompositeStop(this, null)); + requestScope.stop(); + moduleScope.stop(); + } + + /** + * Tests a module-to-stateless scoped wire is setup properly by the runtime + */ + public void testModuleToStateless() throws Exception { + WorkContext ctx = new WorkContextImpl(); + ScopeContainer moduleScope = new ModuleScopeContainer(ctx); + moduleScope.start(); + ScopeContainer statelessScope = new StatelessScopeContainer(ctx); + statelessScope.start(); + + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", SourceImpl.class, + moduleScope, members, "target", Target.class, TargetImpl.class, statelessScope); + moduleScope.onEvent(new CompositeStart(this, null)); + + AtomicComponent sourceComponent = contexts.get("source"); + AtomicComponent targetComponent = contexts.get("target"); + Source source = (Source) sourceComponent.getServiceInstance(); + Target target = (Target) targetComponent.getServiceInstance(); + assertTrue(Proxy.isProxyClass(source.getTarget().getClass())); + assertNull(source.getTarget().getString()); + assertNull(target.getString()); + target.setString("foo"); + assertFalse("foo".equals(source.getTarget().getString())); + Target target2 = (Target) targetComponent.getServiceInstance(); + assertFalse("foo".equals(target2.getString())); + source.getTarget().setString("bar"); + assertFalse("bar".equals(source.getTarget().getString())); + moduleScope.onEvent(new CompositeStop(this, null)); + moduleScope.stop(); + statelessScope.stop(); + } + + + /** + * Tests a session-to-session scoped wire + */ + public void testSessionToSession() throws Exception { + WorkContext ctx = new WorkContextImpl(); + ScopeContainer sessionScope = new HttpSessionScopeContainer(ctx); + sessionScope.start(); + + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", SourceImpl.class, + sessionScope, members, "target", Target.class, TargetImpl.class, sessionScope); + + Object session1 = new Object(); + ctx.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session1); + sessionScope.onEvent(new HttpSessionStart(this, session1)); + AtomicComponent sourceComponent = contexts.get("source"); + AtomicComponent targetComponent = contexts.get("target"); + Source source = (Source) sourceComponent.getServiceInstance(); + Target target = (Target) targetComponent.getServiceInstance(); + source.getTarget().setString("foo"); + source.getTarget().setString("foo"); + assertEquals("foo", target.getString()); + + ctx.clearIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER); + sessionScope.onEvent(new HttpSessionEnd(this, session1)); + + //second session + Object session2 = new Object(); + ctx.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session2); + sessionScope.onEvent(new HttpSessionStart(this, session2)); + + Source source2 = (Source) sourceComponent.getServiceInstance(); + assertNotNull(source2); + Target target2 = (Target) targetComponent.getServiceInstance(); + + assertNotNull(target2); + assertNull(target2.getString()); + assertEquals(null, source2.getTarget().getString()); + source2.getTarget().setString("baz"); + assertEquals("baz", source2.getTarget().getString()); + assertEquals("baz", target2.getString()); + ctx.clearIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER); + sessionScope.onEvent(new HttpSessionEnd(this, session2)); + sessionScope.stop(); + } + + + /** + * Tests a session-to-module scoped wire + */ + public void testSessionToModule() throws Exception { + WorkContext ctx = new WorkContextImpl(); + ScopeContainer moduleScope = new ModuleScopeContainer(ctx); + moduleScope.start(); + ScopeContainer sessionScope = new HttpSessionScopeContainer(ctx); + sessionScope.start(); + + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", SourceImpl.class, + sessionScope, members, "target", Target.class, TargetImpl.class, moduleScope); + moduleScope.onEvent(new CompositeStart(this, null)); + Object session1 = new Object(); + ctx.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session1); + sessionScope.onEvent(new HttpSessionStart(this, session1)); + AtomicComponent sourceComponent = contexts.get("source"); + AtomicComponent targetComponent = contexts.get("target"); + Source source = (Source) sourceComponent.getServiceInstance(); + Target target = (Target) targetComponent.getServiceInstance(); + assertNull(source.getTarget().getString()); + assertNull(target.getString()); + target.setString("foo"); + assertTrue(Proxy.isProxyClass(source.getTarget().getClass())); + assertEquals("foo", source.getTarget().getString()); + ctx.clearIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER); + sessionScope.onEvent(new HttpSessionEnd(this, session1)); + + //second session + Object session2 = new Object(); + ctx.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session2); + sessionScope.onEvent(new HttpSessionStart(this, session2)); + + Target target2 = (Target) targetComponent.getServiceInstance(); + Source source2 = (Source) sourceComponent.getServiceInstance(); + assertEquals("foo", target2.getString()); + assertEquals("foo", source2.getTarget().getString()); + source2.getTarget().setString("baz"); + assertEquals("baz", source2.getTarget().getString()); + assertEquals("baz", target2.getString()); + assertEquals("baz", target.getString()); + ctx.clearIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER); + sessionScope.onEvent(new HttpSessionEnd(this, session2)); + moduleScope.stop(); + sessionScope.stop(); + } + + /** + * Tests a session-to-request scoped wire is setup properly by the runtime + */ + public void testSessionToRequest() throws Exception { + WorkContext ctx = new WorkContextImpl(); + final ScopeContainer requestScope = new RequestScopeContainer(ctx); + requestScope.start(); + ScopeContainer sessionScope = new HttpSessionScopeContainer(ctx); + sessionScope.start(); + + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", SourceImpl.class, + sessionScope, members, "target", Target.class, TargetImpl.class, requestScope); + Object session1 = new Object(); + ctx.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session1); + sessionScope.onEvent(new HttpSessionStart(this, session1)); + requestScope.onEvent(new RequestStart(this)); + AtomicComponent sourceComponent = contexts.get("source"); + final AtomicComponent targetComponent = contexts.get("target"); + final Source source = (Source) sourceComponent.getServiceInstance(); + Target target = (Target) targetComponent.getServiceInstance(); + assertNull(source.getTarget().getString()); + assertNull(target.getString()); + target.setString("foo"); + assertTrue(Proxy.isProxyClass(source.getTarget().getClass())); + assertEquals("foo", source.getTarget().getString()); + + // spin off another request + Executor executor = Executors.newSingleThreadExecutor(); + FutureTask<Void> future = new FutureTask<Void>(new Runnable() { + public void run() { + requestScope.onEvent(new RequestStart(this)); + Target target2 = (Target) targetComponent.getServiceInstance(); + assertFalse("foo".equals(target2.getString())); + assertFalse("foo".equals(source.getTarget().getString())); + source.getTarget().setString("bar"); + assertEquals("bar", target2.getString()); + assertEquals("bar", source.getTarget().getString()); + requestScope.onEvent(new RequestEnd(this)); + } + }, null); + executor.execute(future); + future.get(); + assertEquals("foo", source.getTarget().getString()); + requestScope.onEvent(new RequestEnd(this)); + ctx.clearIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER); + sessionScope.onEvent(new HttpSessionEnd(this, session1)); + requestScope.stop(); + sessionScope.stop(); + } + + + /** + * Tests a session-to-stateless scoped wire is setup properly by the runtime + */ + public void testSessionToStateless() throws Exception { + WorkContext ctx = new WorkContextImpl(); + ScopeContainer sessionScope = new HttpSessionScopeContainer(ctx); + sessionScope.start(); + ScopeContainer statelessScope = new StatelessScopeContainer(ctx); + statelessScope.start(); + + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", SourceImpl.class, + sessionScope, members, "target", Target.class, TargetImpl.class, statelessScope); + + Object session1 = new Object(); + ctx.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session1); + sessionScope.onEvent(new HttpSessionStart(this, session1)); + + AtomicComponent sourceComponent = contexts.get("source"); + AtomicComponent targetComponent = contexts.get("target"); + Source source = (Source) sourceComponent.getServiceInstance(); + Target target = (Target) targetComponent.getServiceInstance(); + assertTrue(Proxy.isProxyClass(source.getTarget().getClass())); + assertNull(source.getTarget().getString()); + assertNull(target.getString()); + target.setString("foo"); + assertFalse("foo".equals(source.getTarget().getString())); + Target target2 = (Target) targetComponent.getServiceInstance(); + assertFalse("foo".equals(target2.getString())); + source.getTarget().setString("bar"); + assertFalse("bar".equals(source.getTarget().getString())); + + ctx.clearIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER); + sessionScope.onEvent(new HttpSessionEnd(this, session1)); + sessionScope.stop(); + statelessScope.stop(); + } + + /** + * Tests a request-to-request scoped wire is setup properly by the runtime + */ + public void testRequestToRequest() throws Exception { + WorkContext ctx = new WorkContextImpl(); + final ScopeContainer requestScope = new RequestScopeContainer(ctx); + requestScope.start(); + + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", SourceImpl.class, + requestScope, members, "target", Target.class, TargetImpl.class, requestScope); + requestScope.onEvent(new RequestStart(this)); + + final AtomicComponent sourceComponent = contexts.get("source"); + final AtomicComponent targetComponent = contexts.get("target"); + Source source = (Source) sourceComponent.getServiceInstance(); + Target target = (Target) targetComponent.getServiceInstance(); + assertNull(source.getTarget().getString()); + assertNull(target.getString()); + target.setString("foo"); + assertTrue(Proxy.isProxyClass(source.getTarget().getClass())); + assertEquals("foo", source.getTarget().getString()); + + // spin off another request + Executor executor = Executors.newSingleThreadExecutor(); + FutureTask<Void> future = new FutureTask<Void>(new Runnable() { + public void run() { + requestScope.onEvent(new RequestStart(this)); + Source source2 = (Source) sourceComponent.getServiceInstance(); + Target target2 = (Target) targetComponent.getServiceInstance(); + assertFalse("foo".equals(target2.getString())); + assertFalse("foo".equals(source2.getTarget().getString())); + source2.getTarget().setString("bar"); + assertEquals("bar", target2.getString()); + assertEquals("bar", source2.getTarget().getString()); + requestScope.onEvent(new RequestEnd(this)); + } + }, null); + executor.execute(future); + future.get(); + requestScope.onEvent(new RequestEnd(this)); + requestScope.stop(); + } + + /** + * Tests a request-to-module scoped wire + */ + public void testRequestToModule() throws Exception { + WorkContext ctx = new WorkContextImpl(); + final ScopeContainer requestScope = new RequestScopeContainer(ctx); + final ScopeContainer moduleScope = new ModuleScopeContainer(ctx); + requestScope.start(); + moduleScope.start(); + moduleScope.onEvent(new CompositeStart(this, null)); + + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", SourceImpl.class, + requestScope, members, "target", Target.class, TargetImpl.class, moduleScope); + requestScope.onEvent(new RequestStart(this)); + + final AtomicComponent sourceComponent = contexts.get("source"); + final AtomicComponent targetComponent = contexts.get("target"); + Source source = (Source) sourceComponent.getServiceInstance(); + Target target = (Target) targetComponent.getServiceInstance(); + assertNull(source.getTarget().getString()); + assertNull(target.getString()); + target.setString("foo"); + assertTrue(Proxy.isProxyClass(source.getTarget().getClass())); + assertEquals("foo", source.getTarget().getString()); + + // spin off another request + Executor executor = Executors.newSingleThreadExecutor(); + FutureTask<Void> future = new FutureTask<Void>(new Runnable() { + public void run() { + requestScope.onEvent(new RequestStart(this)); + Source source2 = (Source) sourceComponent.getServiceInstance(); + Target target2 = (Target) targetComponent.getServiceInstance(); + assertEquals("foo", target2.getString()); + assertEquals("foo", source2.getTarget().getString()); + source2.getTarget().setString("bar"); + assertEquals("bar", target2.getString()); + assertEquals("bar", source2.getTarget().getString()); + requestScope.onEvent(new RequestEnd(this)); + } + }, null); + executor.execute(future); + future.get(); + assertEquals("bar", target.getString()); + + requestScope.onEvent(new RequestEnd(this)); + requestScope.stop(); + moduleScope.onEvent(new CompositeStop(this, null)); + moduleScope.stop(); + } + + /** + * Tests a request-to-session scoped wire is setup properly by the runtime + */ + public void testRequestToSession() throws Exception { + WorkContext ctx = new WorkContextImpl(); + final ScopeContainer requestScope = new RequestScopeContainer(ctx); + final ScopeContainer sessionScope = new HttpSessionScopeContainer(ctx); + requestScope.start(); + sessionScope.start(); + + Object session1 = new Object(); + ctx.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session1); + sessionScope.onEvent(new HttpSessionStart(this, session1)); + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", SourceImpl.class, + requestScope, members, "target", Target.class, TargetImpl.class, sessionScope); + + final AtomicComponent sourceComponent = contexts.get("source"); + final AtomicComponent targetComponent = contexts.get("target"); + requestScope.onEvent(new RequestStart(this)); + Source source = (Source) sourceComponent.getServiceInstance(); + Target target = (Target) targetComponent.getServiceInstance(); + assertNull(source.getTarget().getString()); + assertNull(target.getString()); + target.setString("foo"); + assertTrue(Proxy.isProxyClass(source.getTarget().getClass())); + assertEquals("foo", source.getTarget().getString()); + + // spin off another request + Executor executor = Executors.newSingleThreadExecutor(); + FutureTask<Void> future = new FutureTask<Void>(new Runnable() { + public void run() { + requestScope.onEvent(new RequestStart(this)); + Source source2 = (Source) sourceComponent.getServiceInstance(); + Target target2 = (Target) targetComponent.getServiceInstance(); + assertEquals("foo", target2.getString()); + assertEquals("foo", source2.getTarget().getString()); + source2.getTarget().setString("bar"); + assertEquals("bar", target2.getString()); + assertEquals("bar", source2.getTarget().getString()); + requestScope.onEvent(new RequestEnd(this)); + } + }, null); + executor.execute(future); + future.get(); + assertEquals("bar", target.getString()); + + requestScope.onEvent(new RequestEnd(this)); + requestScope.stop(); + ctx.clearIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER); + sessionScope.onEvent(new HttpSessionEnd(this, session1)); + sessionScope.stop(); + } + + + /** + * Tests a request-to-stateless scoped wire is setup properly by the runtime + */ + public void testRequestToStateless() throws Exception { + WorkContext ctx = new WorkContextImpl(); + ScopeContainer requestScope = new RequestScopeContainer(ctx); + requestScope.start(); + ScopeContainer statelessScope = new StatelessScopeContainer(ctx); + statelessScope.start(); + + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", SourceImpl.class, + requestScope, members, "target", Target.class, TargetImpl.class, statelessScope); + + AtomicComponent sourceComponent = contexts.get("source"); + AtomicComponent targetComponent = contexts.get("target"); + requestScope.onEvent(new RequestStart(this)); + Source source = (Source) sourceComponent.getServiceInstance(); + Target target = (Target) targetComponent.getServiceInstance(); + assertTrue(Proxy.isProxyClass(source.getTarget().getClass())); + assertNull(source.getTarget().getString()); + assertNull(target.getString()); + target.setString("foo"); + assertFalse("foo".equals(source.getTarget().getString())); + Target target2 = (Target) targetComponent.getServiceInstance(); + assertFalse("foo".equals(target2.getString())); + source.getTarget().setString("bar"); + assertFalse("bar".equals(source.getTarget().getString())); + requestScope.onEvent(new RequestEnd(this)); + requestScope.stop(); + statelessScope.stop(); + } + + + /** + * Tests a stateless-to-stateless scoped wire is setup properly by the runtime + */ + public void testStatelessToStateless() throws Exception { + WorkContext ctx = new WorkContextImpl(); + ScopeContainer statelessScope = new StatelessScopeContainer(ctx); + statelessScope.start(); + + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", SourceImpl.class, + statelessScope, members, "target", Target.class, TargetImpl.class, statelessScope); + + AtomicComponent sourceComponent = contexts.get("source"); + AtomicComponent targetComponent = contexts.get("target"); + Source source = (Source) sourceComponent.getServiceInstance(); + Target target = (Target) targetComponent.getServiceInstance(); + assertTrue(Proxy.isProxyClass(source.getTarget().getClass())); + assertNull(source.getTarget().getString()); + assertNull(target.getString()); + target.setString("foo"); + assertFalse("foo".equals(source.getTarget().getString())); + Target target2 = (Target) targetComponent.getServiceInstance(); + assertFalse("foo".equals(target2.getString())); + source.getTarget().setString("bar"); + assertFalse("bar".equals(source.getTarget().getString())); + statelessScope.stop(); + } + + /** + * Tests a stateless-to-request scoped wire is setup properly by the runtime + */ + public void testStatelessToRequest() throws Exception { + WorkContext ctx = new WorkContextImpl(); + final ScopeContainer requestScope = new RequestScopeContainer(ctx); + requestScope.start(); + ScopeContainer statelessScope = new StatelessScopeContainer(ctx); + statelessScope.start(); + + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", SourceImpl.class, + statelessScope, members, "target", Target.class, TargetImpl.class, requestScope); + requestScope.onEvent(new RequestStart(this)); + AtomicComponent sourceComponent = contexts.get("source"); + final AtomicComponent targetComponent = contexts.get("target"); + final Source source = (Source) sourceComponent.getServiceInstance(); + Target target = (Target) targetComponent.getServiceInstance(); + assertNull(source.getTarget().getString()); + assertNull(target.getString()); + target.setString("foo"); + assertTrue(Proxy.isProxyClass(source.getTarget().getClass())); + assertEquals("foo", source.getTarget().getString()); + + // spin off another request + Executor executor = Executors.newSingleThreadExecutor(); + FutureTask<Void> future = new FutureTask<Void>(new Runnable() { + public void run() { + requestScope.onEvent(new RequestStart(this)); + Target target2 = (Target) targetComponent.getServiceInstance(); + assertFalse("foo".equals(target2.getString())); + assertFalse("foo".equals(source.getTarget().getString())); + source.getTarget().setString("bar"); + assertEquals("bar", target2.getString()); + assertEquals("bar", source.getTarget().getString()); + requestScope.onEvent(new RequestEnd(this)); + } + }, null); + executor.execute(future); + future.get(); + requestScope.stop(); + statelessScope.stop(); + } + + /** + * Tests a stateless-to-session scoped wire is setup properly by the runtime + */ + public void testStatelessToSession() throws Exception { + WorkContext ctx = new WorkContextImpl(); + ScopeContainer statelessScope = new StatelessScopeContainer(ctx); + statelessScope.start(); + ScopeContainer sessionScope = new HttpSessionScopeContainer(ctx); + sessionScope.start(); + + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", SourceImpl.class, + statelessScope, members, "target", Target.class, TargetImpl.class, sessionScope); + Object session1 = new Object(); + ctx.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session1); + sessionScope.onEvent(new HttpSessionStart(this, session1)); + AtomicComponent sourceComponent = contexts.get("source"); + AtomicComponent targetComponent = contexts.get("target"); + Source source = (Source) sourceComponent.getServiceInstance(); + Target target = (Target) targetComponent.getServiceInstance(); + assertNull(source.getTarget().getString()); + assertNull(target.getString()); + target.setString("foo"); + assertTrue(Proxy.isProxyClass(source.getTarget().getClass())); + assertEquals("foo", source.getTarget().getString()); + ctx.clearIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER); + sessionScope.onEvent(new HttpSessionEnd(this, session1)); + + //second session + Object session2 = new Object(); + ctx.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session2); + sessionScope.onEvent(new HttpSessionStart(this, session2)); + + Target target2 = (Target) targetComponent.getServiceInstance(); + assertFalse("foo".equals(target2.getString())); + + assertFalse("foo".equals(source.getTarget().getString())); + source.getTarget().setString("bar"); + assertEquals("bar", target2.getString()); + assertEquals("bar", source.getTarget().getString()); + sessionScope.onEvent(new HttpSessionEnd(this, session2)); + + ctx.clearIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER); + sessionScope.stop(); + statelessScope.stop(); + } + + + /** + * Tests a stateless-to-module scoped wire is setup properly by the runtime + */ + public void testStatelessToModule() throws Exception { + WorkContext ctx = new WorkContextImpl(); + ScopeContainer statelessScope = new StatelessScopeContainer(ctx); + statelessScope.start(); + ScopeContainer moduleScope = new ModuleScopeContainer(ctx); + moduleScope.start(); + + Map<String, AtomicComponent> contexts = MockFactory.createWiredComponents("source", SourceImpl.class, + statelessScope, members, "target", Target.class, TargetImpl.class, moduleScope); + moduleScope.onEvent(new CompositeStart(this, null)); + AtomicComponent sourceComponent = contexts.get("source"); + AtomicComponent targetComponent = contexts.get("target"); + Source source = (Source) sourceComponent.getServiceInstance(); + Target target = (Target) targetComponent.getServiceInstance(); + assertNull(source.getTarget().getString()); + assertNull(target.getString()); + target.setString("foo"); + assertTrue(Proxy.isProxyClass(source.getTarget().getClass())); + assertEquals("foo", source.getTarget().getString()); + + //second session + Object session2 = new Object(); + ctx.setIdentifier(HttpSessionScopeContainer.HTTP_IDENTIFIER, session2); + moduleScope.onEvent(new HttpSessionStart(this, session2)); + + Target target2 = (Target) targetComponent.getServiceInstance(); + assertEquals("foo", target2.getString()); + + assertEquals("foo", source.getTarget().getString()); + source.getTarget().setString("bar"); + assertEquals("bar", target2.getString()); + assertEquals("bar", source.getTarget().getString()); + + moduleScope.onEvent(new CompositeStop(this, null)); + moduleScope.stop(); + statelessScope.stop(); + } + + protected void setUp() throws Exception { + super.setUp(); + members = new HashMap<String, Member>(); + Method[] methods = SourceImpl.class.getMethods(); + for (Method method : methods) { + if (method.getName().startsWith("set")) { + members.put(JavaIntrospectionHelper.toPropertyName(method.getName()), method); + } + } + } + + +} + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/MockFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/MockFactory.java new file mode 100644 index 0000000000..3c2093eee7 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/MockFactory.java @@ -0,0 +1,381 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java.mock; + +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.spi.builder.BuilderConfigException; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaIDLUtils; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.TargetInvoker; +import org.apache.tuscany.spi.wire.WireService; + +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.core.implementation.java.JavaAtomicComponent; +import org.apache.tuscany.core.implementation.java.JavaTargetInvoker; +import org.apache.tuscany.core.injection.PojoObjectFactory; +import org.apache.tuscany.core.wire.InboundInvocationChainImpl; +import org.apache.tuscany.core.wire.InboundWireImpl; +import org.apache.tuscany.core.wire.InvokerInterceptor; +import org.apache.tuscany.core.wire.OutboundInvocationChainImpl; +import org.apache.tuscany.core.wire.OutboundWireImpl; +import org.apache.tuscany.core.wire.jdk.JDKWireService; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; + +/** + * @version $$Rev$$ $$Date$$ + */ +public final class MockFactory { + + private static final WireService WIRE_SERVICE = new JDKWireService(new WorkContextImpl(), null); + private static final JavaInterfaceProcessorRegistry REGISTRY = new JavaInterfaceProcessorRegistryImpl(); + + private MockFactory() { + } + + /** + * Creates a JavaAtomicComponent which returns the given instance + */ + @SuppressWarnings("unchecked") + public static <T> JavaAtomicComponent createJavaComponent(T instance) { + ScopeContainer scope = createMock(ScopeContainer.class); + scope.getScope(); + expectLastCall().andReturn(Scope.MODULE); + scope.getInstance(isA(JavaAtomicComponent.class)); + expectLastCall().andReturn(instance).anyTimes(); + replay(scope); + PojoConfiguration configuration = new PojoConfiguration(); + configuration.setScopeContainer(scope); + try { + configuration.setInstanceFactory(new PojoObjectFactory(DummyImpl.class.getConstructor())); + } catch (NoSuchMethodException e) { + throw new AssertionError(e); + } + configuration.addServiceInterface(DummyImpl.class); + configuration.setWireService(WIRE_SERVICE); + return new JavaAtomicComponent(instance.getClass().getName(), configuration, null); + } + + @SuppressWarnings("unchecked") + public static <T> JavaAtomicComponent createJavaComponent(String name, ScopeContainer scope, Class<T> clazz) + throws NoSuchMethodException { + PojoConfiguration configuration = new PojoConfiguration(); + configuration.setScopeContainer(scope); + configuration.setInstanceFactory(new PojoObjectFactory(clazz.getConstructor())); + configuration.addServiceInterface(clazz); + configuration.setWireService(WIRE_SERVICE); + return new JavaAtomicComponent(name, configuration, null); + + } + + /** + * Wires two contexts together where the reference interface is the same as target service + * + * @param sourceName + * @param sourceClass + * @param sourceScope + * @param members + * @param targetName + * @param targetService + * @param targetClass + * @param targetScope + * @return + * @throws Exception + */ + public static Map<String, AtomicComponent> createWiredComponents(String sourceName, + Class<?> sourceClass, + ScopeContainer sourceScope, + Map<String, Member> members, + String targetName, + Class<?> targetService, + Class<?> targetClass, + ScopeContainer targetScope) throws Exception { + return createWiredComponents(sourceName, sourceClass, targetService, sourceScope, members, targetName, + targetService, targetClass, targetScope); + + } + + /** + * Wires two contexts together where the reference interface may be different from the target service + */ + public static Map<String, AtomicComponent> createWiredComponents(String sourceName, Class<?> sourceClass, + Class<?> sourceReferenceClass, + ScopeContainer sourceScope, + Map<String, Member> members, + String targetName, + Class<?> targetService, + Class<?> targetClass, + ScopeContainer targetScope) throws Exception { + return createWiredComponents(sourceName, + sourceClass, + sourceReferenceClass, + sourceScope, + null, + members, + targetName, + targetService, + targetClass, + targetScope, + null); + } + + @SuppressWarnings("unchecked") + public static Map<String, AtomicComponent> createWiredComponents(String sourceName, Class<?> sourceClass, + Class<?> sourceReferenceClass, + ScopeContainer sourceScope, + Interceptor sourceHeadInterceptor, + Map<String, Member> members, + String targetName, Class<?> targetService, + Class<?> targetClass, + ScopeContainer targetScope, + Interceptor targetHeadInterceptor) + throws Exception { + + JavaAtomicComponent targetContext = + createJavaComponent(targetName, targetScope, targetClass); + String serviceName = targetService.getName().substring(targetService.getName().lastIndexOf('.') + 1); + InboundWire inboundWire = createServiceWire(serviceName, targetService, targetHeadInterceptor); + targetContext.addInboundWire(inboundWire); + + PojoConfiguration configuration = new PojoConfiguration(); + configuration.setScopeContainer(sourceScope); + configuration.setInstanceFactory(new PojoObjectFactory(sourceClass.getConstructor())); + configuration.addServiceInterface(sourceClass); + configuration.setWireService(WIRE_SERVICE); + for (Map.Entry<String, Member> entry : members.entrySet()) { + configuration.addReferenceSite(entry.getKey(), entry.getValue()); + } + JavaAtomicComponent sourceContext = new JavaAtomicComponent(sourceName, configuration, null); + OutboundWire outboundWire = createReferenceWire(targetName, sourceReferenceClass, sourceHeadInterceptor); + sourceContext.addOutboundWire(outboundWire); + targetScope.register(targetContext); + sourceScope.register(sourceContext); + connect(outboundWire, inboundWire, targetContext, false); + Map<String, AtomicComponent> contexts = new HashMap<String, AtomicComponent>(); + contexts.put(sourceName, sourceContext); + contexts.put(targetName, targetContext); + return contexts; + } + + + /** + * Wires two contexts using a multiplicity reference + * + * @param sourceName + * @param sourceClass + * @param sourceReferenceClass + * @param sourceScope + * @param targetName + * @param targetService + * @param targetClass + * @param members + * @param targetScope + * @return + * @throws Exception + */ + @SuppressWarnings("unchecked") + public static Map<String, AtomicComponent> createWiredMultiplicity(String sourceName, Class<?> sourceClass, + Class<?> sourceReferenceClass, + ScopeContainer sourceScope, + String targetName, Class<?> targetService, + Class<?> targetClass, + Map<String, Member> members, + ScopeContainer targetScope) throws Exception { + JavaAtomicComponent targetContext = + createJavaComponent(targetName, targetScope, targetClass); + String serviceName = targetService.getName().substring(targetService.getName().lastIndexOf('.') + 1); + InboundWire inboundWire = createServiceWire(serviceName, targetService, null); + targetContext.addInboundWire(inboundWire); + + PojoConfiguration configuration = new PojoConfiguration(); + configuration.setScopeContainer(sourceScope); + configuration.setInstanceFactory(new PojoObjectFactory(sourceClass.getConstructor())); + configuration.addServiceInterface(sourceClass); + configuration.setWireService(WIRE_SERVICE); + for (Map.Entry<String, Member> entry : members.entrySet()) { + configuration.addReferenceSite(entry.getKey(), entry.getValue()); + } + JavaAtomicComponent sourceContext = new JavaAtomicComponent(sourceName, configuration, null); + OutboundWire outboundWire = createReferenceWire(targetName, sourceReferenceClass, null); + List<OutboundWire> factories = new ArrayList<OutboundWire>(); + factories.add(outboundWire); + sourceContext.addOutboundWires(sourceReferenceClass, factories); + targetScope.register(targetContext); + sourceScope.register(sourceContext); + connect(outboundWire, inboundWire, targetContext, false); + Map<String, AtomicComponent> contexts = new HashMap<String, AtomicComponent>(); + contexts.put(sourceName, sourceContext); + contexts.put(targetName, targetContext); + return contexts; + } + + public static <T> InboundWire createTargetWire(String serviceName, Class<T> interfaze) + throws InvalidServiceContractException { + return createServiceWire(serviceName, interfaze, null); + } + + + public static <T> InboundWire createServiceWire(String serviceName, Class<T> interfaze, Interceptor interceptor) + throws InvalidServiceContractException { + InboundWire wire = new InboundWireImpl(); + ServiceContract<?> contract = REGISTRY.introspect(interfaze); + wire.setServiceContract(contract); + wire.setServiceName(serviceName); + wire.addInvocationChains( + createInboundChains(interfaze, interceptor)); + return wire; + } + + public static <T> OutboundWire createReferenceWire(String refName, Class<T> interfaze, Interceptor interceptor) + throws InvalidServiceContractException { + + OutboundWire wire = new OutboundWireImpl(); + wire.setReferenceName(refName); + Map<Operation<?>, OutboundInvocationChain> outboundChains = createOutboundChains(interfaze, interceptor); + wire.addInvocationChains(outboundChains); + ServiceContract<?> contract = REGISTRY.introspect(interfaze); + wire.setServiceContract(contract); + return wire; + } + + public static <T> OutboundWire createReferenceWire(String refName, Class<T> interfaze) + throws InvalidServiceContractException { + OutboundWire wire = new OutboundWireImpl(); + wire.setReferenceName(refName); + wire.addInvocationChains(createOutboundChains(interfaze)); + ServiceContract<?> contract = REGISTRY.introspect(interfaze); + wire.setServiceContract(contract); + return wire; + } + + + /** + * @param outboundWire + * @param inboundWire + * @param targetContext + * @param cacheable + * @throws Exception + */ + public static void connect(OutboundWire outboundWire, + InboundWire inboundWire, + JavaAtomicComponent targetContext, + boolean cacheable) throws Exception { + if (inboundWire != null) { + // if null, the target side has no interceptors or handlers + Map<Operation<?>, InboundInvocationChain> targetInvocationConfigs = inboundWire.getInvocationChains(); + for (OutboundInvocationChain outboundInvocationConfig : outboundWire.getInvocationChains().values()) { + // match wire chains + InboundInvocationChain inboundInvocationConfig = + targetInvocationConfigs.get(outboundInvocationConfig.getOperation()); + if (inboundInvocationConfig == null) { + BuilderConfigException e = + new BuilderConfigException("Incompatible source and target interface types for reference"); + e.setIdentifier(outboundWire.getReferenceName()); + throw e; + } + if (inboundInvocationConfig.getHeadInterceptor() == null) { + BuilderConfigException e = + new BuilderConfigException("No target handler or interceptor for operation"); + e.setIdentifier(inboundInvocationConfig.getOperation().getName()); + throw e; + } + if (!(outboundInvocationConfig.getTailInterceptor() instanceof InvokerInterceptor + && inboundInvocationConfig.getHeadInterceptor() instanceof InvokerInterceptor)) { + // check that we do not have the case where the only interceptors are invokers since we just + // need one + outboundInvocationConfig.setTargetInterceptor(inboundInvocationConfig.getHeadInterceptor()); + } + } + + for (OutboundInvocationChain chain : outboundWire.getInvocationChains().values()) { + //FIXME should use target method, not outboundInvocationConfig.getMethod() + Method[] methods = outboundWire.getServiceContract().getInterfaceClass().getMethods(); + Method m = JavaIDLUtils.findMethod(chain.getOperation(), methods); + TargetInvoker invoker = new JavaTargetInvoker(m, targetContext); + invoker.setCacheable(cacheable); + chain.setTargetInvoker(invoker); + } + } + } + + private static Map<Operation<?>, OutboundInvocationChain> createOutboundChains(Class<?> interfaze) + throws InvalidServiceContractException { + return createOutboundChains(interfaze, null); + } + + private static Map<Operation<?>, OutboundInvocationChain> createOutboundChains(Class<?> interfaze, + Interceptor interceptor) + throws InvalidServiceContractException { + Map<Operation<?>, OutboundInvocationChain> invocations = new HashMap<Operation<?>, OutboundInvocationChain>(); + ServiceContract<?> contract = REGISTRY.introspect(interfaze); + for (Operation<?> operation : contract.getOperations().values()) { + OutboundInvocationChain chain = new OutboundInvocationChainImpl(operation); + if (interceptor != null) { + chain.addInterceptor(interceptor); + } + invocations.put(operation, chain); + } + return invocations; + } + + private static Map<Operation<?>, InboundInvocationChain> createInboundChains(Class<?> interfaze, + Interceptor interceptor) + throws InvalidServiceContractException { + + Map<Operation<?>, InboundInvocationChain> invocations = new HashMap<Operation<?>, InboundInvocationChain>(); + ServiceContract<?> contract = REGISTRY.introspect(interfaze); + for (Operation<?> method : contract.getOperations().values()) { + InboundInvocationChain chain = new InboundInvocationChainImpl(method); + if (interceptor != null) { + chain.addInterceptor(interceptor); + } + // add tail interceptor + chain.addInterceptor(new InvokerInterceptor()); + invocations.put(method, chain); + } + return invocations; + } + + private static class DummyImpl { + public DummyImpl() { + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/AsyncTarget.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/AsyncTarget.java new file mode 100644 index 0000000000..1abc9781e3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/AsyncTarget.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java.mock.components; + +import org.osoa.sca.annotations.OneWay; + +/** + * @version $Rev$ $Date$ + */ +public interface AsyncTarget { + @OneWay + void invoke(); + + int getCount(); +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/OtherTarget.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/OtherTarget.java new file mode 100644 index 0000000000..87b1fd87fa --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/OtherTarget.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java.mock.components; + +/** + * Implementations are used in wiring tests + * + * @version $Rev$ $Date$ + */ +public interface OtherTarget { + + String getString(); + + void setString(String val); +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/OtherTargetImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/OtherTargetImpl.java new file mode 100644 index 0000000000..b32fc7547e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/OtherTargetImpl.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.core.implementation.java.mock.components; + +/** + * A target used for testing wires with a different source and target interface + * + * @version $Rev$ $Date$ + */ +public class OtherTargetImpl implements OtherTarget { + + private String theString; + + public String getString() { + return theString; + } + + public void setString(String val) { + theString = val; + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/Source.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/Source.java new file mode 100644 index 0000000000..bffacc3c20 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/Source.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java.mock.components; + +import java.util.List; + + +/** + * Implementations are used in wiring tests + * + * @version $Rev$ $Date$ + */ +public interface Source { + + Target getTarget(); + + List<Target> getTargets(); + + List<Target> getTargetsThroughField(); + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/SourceImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/SourceImpl.java new file mode 100644 index 0000000000..bf9e30b306 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/SourceImpl.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.core.implementation.java.mock.components; + +import java.util.List; + + +/** + * Mock system component implementation used in wiring tests + * + * @version $Rev$ $Date$ + */ +public class SourceImpl implements Source { + + private Target target; + private List<Target> targets; + private Target[] targetsArray; + private List<Target> targetsThroughField; + + public void setTarget(Target target) { + this.target = target; + } + + public Target getTarget() { + return target; + } + + public List<Target> getTargets() { + return targets; + } + + public void setTargets(List<Target> targets) { + this.targets = targets; + } + + public List<Target> getTargetsThroughField() { + return targetsThroughField; + } + + + public Target[] getArrayOfTargets() { + return targetsArray; + } + + public void setArrayOfTargets(Target[] targets) { + targetsArray = targets; + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/Target.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/Target.java new file mode 100644 index 0000000000..cafebc0801 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/Target.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java.mock.components; + +/** + * Implementations are used in wiring tests + * + * @version $Rev$ $Date$ + */ +public interface Target { + + String getString(); + + void setString(String val); +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/TargetImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/TargetImpl.java new file mode 100644 index 0000000000..060ca292a9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/java/mock/components/TargetImpl.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.java.mock.components; + +/** + * Mock system component implementation used in wiring tests + * + * @version $Rev$ $Date$ + */ +public class TargetImpl implements Target { + + private String theString; + + public String getString() { + return theString; + } + + public void setString(String val) { + theString = val; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ConstructorAutowireTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ConstructorAutowireTestCase.java new file mode 100644 index 0000000000..c67d226b41 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ConstructorAutowireTestCase.java @@ -0,0 +1,154 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Constructor; +import java.util.List; + +import org.osoa.sca.annotations.Property; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; + +/** + * @version $Rev$ $Date$ + */ +public class ConstructorAutowireTestCase extends TestCase { + + ConstructorProcessor processor = + new ConstructorProcessor(new ImplementationProcessorServiceImpl(new JavaInterfaceProcessorRegistryImpl())); + + public void testAutowire() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Foo> ctor = Foo.class.getConstructor(Bar.class); + processor.visitConstructor(null, ctor, type, null); + assertNotNull(type.getReferences().get("myRef")); + } + + public void testNamesOnConstructor() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Foo> ctor = Foo.class.getConstructor(Bar.class, Bar.class); + processor.visitConstructor(null, ctor, type, null); + assertEquals(2, type.getConstructorDefinition().getInjectionNames().size()); + assertNotNull(type.getReferences().get("myRef1")); + assertNotNull(type.getReferences().get("myRef2")); + } + + public void testNoName() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Foo2> ctor = Foo2.class.getConstructor(Bar.class); + processor.visitConstructor(null, ctor, type, null); + assertNotNull(type.getReferences().get(Bar.class.getName() + "0")); + } + + public void testInvalidNumberOfNames() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<BadFoo> ctor = BadFoo.class.getConstructor(Bar.class, Bar.class); + try { + processor.visitConstructor(null, ctor, type, null); + fail(); + } catch (InvalidAutowireException e) { + // expected + } + } + + public void testNoMatchingNames() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<BadFoo> ctor = BadFoo.class.getConstructor(List.class, List.class); + try { + processor.visitConstructor(null, ctor, type, null); + fail(); + } catch (InvalidConstructorException e) { + // expected + } + } + + /** + * Verifies processing executes with additional extension annotations + */ + public void testRandomAnnotation() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Foo3> ctor = Foo3.class.getConstructor(String.class, String.class); + processor.visitConstructor(null, ctor, type, null); + assertEquals(1, type.getProperties().size()); + assertNotNull(type.getProperties().get("prop1")); + } + + private static interface Bar { + + } + + private static class Foo { + + @org.osoa.sca.annotations.Constructor() + public Foo(@Autowire(name = "myRef") Bar ref) { + + } + + @org.osoa.sca.annotations.Constructor({"myRef1", "myRef2"}) + public Foo(@Autowire Bar ref1, @Autowire Bar ref2) { + + } + + } + + private static class Foo2 { + @org.osoa.sca.annotations.Constructor() + public Foo2(@Autowire Bar ref) { + + } + } + + private static class BadFoo { + + @org.osoa.sca.annotations.Constructor({"ref1"}) + public BadFoo(@Autowire Bar ref1, @Autowire Bar ref2) { + + } + + @org.osoa.sca.annotations.Constructor({"myRef", "myRef2"}) + public BadFoo(@Autowire List ref, @Autowire(name = "myOtherRef") List ref2) { + + } + + } + + public static class Foo3 { + + @org.osoa.sca.annotations.Constructor + public Foo3(@Property(name = "prop1") String prop, @Baz String baz) { + } + } + + public @interface Baz { + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessorExtensibilityTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessorExtensibilityTestCase.java new file mode 100644 index 0000000000..25a8ab9a1a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessorExtensibilityTestCase.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.core.implementation.processor; + +import java.lang.reflect.Constructor; + +import org.osoa.sca.annotations.Property; + +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; + +/** + * Verifies the constructor processor works when parameters are marked with custom extension annotations + * + * @version $Rev$ $Date$ + */ +public class ConstructorProcessorExtensibilityTestCase extends TestCase { + private ConstructorProcessor processor = + new ConstructorProcessor(new ImplementationProcessorServiceImpl(new JavaInterfaceProcessorRegistryImpl())); + + public void testProcessFirst() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Foo> ctor1 = Foo.class.getConstructor(String.class, String.class); + processor.visitConstructor(null, ctor1, type, null); + assertEquals("foo", type.getConstructorDefinition().getInjectionNames().get(0)); + } + + /** + * Verifies the constructor processor can be called after another processor has evaluated the constructor and found + * an annotation + * + * @throws Exception + */ + public void testProcessLast() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Foo> ctor1 = Foo.class.getConstructor(String.class, String.class); + ConstructorDefinition<Foo> definition = new ConstructorDefinition<Foo>(ctor1); + definition.getInjectionNames().add(""); + definition.getInjectionNames().add("mybar"); + type.setConstructorDefinition(definition); + processor.visitConstructor(null, ctor1, type, null); + assertEquals("foo", type.getConstructorDefinition().getInjectionNames().get(0)); + } + + + private @interface Bar { + + } + + private static class Foo { + @org.osoa.sca.annotations.Constructor + public Foo(@Property(name = "foo") String foo, @Bar String bar) { + + } + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessorTestCase.java new file mode 100644 index 0000000000..364bfcc274 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ConstructorProcessorTestCase.java @@ -0,0 +1,148 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Constructor; + +import org.osoa.sca.annotations.Property; +import org.osoa.sca.annotations.Reference; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; + +/** + * @version $Rev$ $Date$ + */ +public class ConstructorProcessorTestCase extends TestCase { + private ConstructorProcessor processor = + new ConstructorProcessor(new ImplementationProcessorServiceImpl(new JavaInterfaceProcessorRegistryImpl())); + + public void testDuplicateConstructor() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + try { + processor.visitClass(null, BadFoo.class, type, null); + fail(); + } catch (DuplicateConstructorException e) { + // expected + } + } + + public void testConstructorAnnotation() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Foo> ctor1 = Foo.class.getConstructor(String.class); + processor.visitConstructor(null, ctor1, type, null); + assertEquals("foo", type.getConstructorDefinition().getInjectionNames().get(0)); + } + + public void testNoAnnotation() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<NoAnnotation> ctor1 = NoAnnotation.class.getConstructor(); + processor.visitConstructor(null, ctor1, type, null); + assertNull(type.getConstructorDefinition()); + } + + public void testBadAnnotation() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<BadAnnotation> ctor1 = BadAnnotation.class.getConstructor(String.class, Foo.class); + try { + processor.visitConstructor(null, ctor1, type, null); + fail(); + } catch (InvalidConstructorException e) { + // expected + } + } + + public void testMixedParameters() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Mixed> ctor1 = Mixed.class.getConstructor(String.class, String.class, String.class); + processor.visitConstructor(null, ctor1, type, null); + assertEquals("java.lang.String0", type.getConstructorDefinition().getInjectionNames().get(0)); + assertEquals("foo", type.getConstructorDefinition().getInjectionNames().get(1)); + assertEquals("bar", type.getConstructorDefinition().getInjectionNames().get(2)); + } + + public void testAllAutowireWithNoNames() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<AllAutowireNoName> ctor1 = + AllAutowireNoName.class.getConstructor(String.class, String.class, String.class); + processor.visitConstructor(null, ctor1, type, null); + assertEquals("java.lang.String0", type.getConstructorDefinition().getInjectionNames().get(0)); + assertEquals("java.lang.String1", type.getConstructorDefinition().getInjectionNames().get(1)); + assertEquals("java.lang.String2", type.getConstructorDefinition().getInjectionNames().get(2)); + } + + private static class BadFoo { + + @org.osoa.sca.annotations.Constructor("foo") + public BadFoo(String foo) { + + } + + @org.osoa.sca.annotations.Constructor({"foo", "bar"}) + public BadFoo(String foo, String bar) { + + } + } + + private static class Foo { + @org.osoa.sca.annotations.Constructor("foo") + public Foo(String foo) { + + } + } + + private static class NoAnnotation { + public NoAnnotation() { + } + } + + private static class BadAnnotation { + @org.osoa.sca.annotations.Constructor("foo") + public BadAnnotation(String foo, Foo ref) { + } + } + + + public static final class Mixed { + @org.osoa.sca.annotations.Constructor + public Mixed(@Autowire String param1, + @Property(name = "foo") String param2, + @Reference(name = "bar") String param3) { + } + } + + public static final class AllAutowireNoName { + @org.osoa.sca.annotations.Constructor + public AllAutowireNoName(@Autowire String param1, @Autowire String param2, @Autowire String param3) { + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ConstructorPropertyTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ConstructorPropertyTestCase.java new file mode 100644 index 0000000000..ee461aead7 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ConstructorPropertyTestCase.java @@ -0,0 +1,171 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Constructor; +import java.util.List; + +import org.osoa.sca.annotations.Property; + +import org.apache.tuscany.spi.implementation.java.DuplicatePropertyException; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.model.OverrideOptions; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; + +/** + * @version $Rev$ $Date$ + */ +public class ConstructorPropertyTestCase extends TestCase { + + ConstructorProcessor processor = + new ConstructorProcessor(new ImplementationProcessorServiceImpl(new JavaInterfaceProcessorRegistryImpl())); + + public void testProperty() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Foo> ctor = Foo.class.getConstructor(String.class); + processor.visitConstructor(null, ctor, type, null); + JavaMappedProperty<?> property = type.getProperties().get("myProp"); + //assertTrue(property.isRequired()); + assertEquals(property.getOverride(), OverrideOptions.MAY); + assertEquals("myProp", property.getName()); + } + + public void testTwoPropertiesSameType() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Foo> ctor = Foo.class.getConstructor(String.class, String.class); + processor.visitConstructor(null, ctor, type, null); + assertNotNull(type.getProperties().get("myProp1")); + assertNotNull(type.getProperties().get("myProp2")); + } + + public void testDuplicateProperty() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<BadFoo> ctor = BadFoo.class.getConstructor(String.class, String.class); + try { + processor.visitConstructor(null, ctor, type, null); + fail(); + } catch (DuplicatePropertyException e) { + // expected + } + } + + public void testNoName() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<BadFoo> ctor = BadFoo.class.getConstructor(String.class); + try { + processor.visitConstructor(null, ctor, type, null); + fail(); + } catch (InvalidPropertyException e) { + // expected + } + } + + public void testNamesOnConstructor() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Foo> ctor = Foo.class.getConstructor(Integer.class); + processor.visitConstructor(null, ctor, type, null); + assertNotNull(type.getProperties().get("myProp")); + } + + public void testInvalidNumberOfNames() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<BadFoo> ctor = BadFoo.class.getConstructor(Integer.class, Integer.class); + try { + processor.visitConstructor(null, ctor, type, null); + fail(); + } catch (InvalidPropertyException e) { + // expected + } + } + + public void testNoMatchingNames() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<BadFoo> ctor = BadFoo.class.getConstructor(List.class, List.class); + try { + processor.visitConstructor(null, ctor, type, null); + fail(); + } catch (InvalidConstructorException e) { + // expected + } + } + +// public void testMultiplicityRequired() throws Exception { + // TODO multiplicity +// } + + private static class Foo { + + @org.osoa.sca.annotations.Constructor() + public Foo(@Property(name = "myProp", override = "may") String prop) { + + } + + @org.osoa.sca.annotations.Constructor("myProp") + public Foo(@Property Integer prop) { + + } + + @org.osoa.sca.annotations.Constructor() + public Foo(@Property(name = "myProp1") String prop1, @Property(name = "myProp2") String prop2) { + + } + + @org.osoa.sca.annotations.Constructor() + public Foo(@Property List prop) { + + } + } + + private static class BadFoo { + + @org.osoa.sca.annotations.Constructor() + public BadFoo(@Property(name = "myProp") String prop1, @Property(name = "myProp") String prop2) { + + } + + @org.osoa.sca.annotations.Constructor() + public BadFoo(@Property String prop) { + + } + + @org.osoa.sca.annotations.Constructor("myProp") + public BadFoo(@Property Integer prop, @Property Integer prop2) { + + } + + @org.osoa.sca.annotations.Constructor({"myRef", "myRef2"}) + public BadFoo(@Property List ref, @Property(name = "myOtherRef") List ref2) { + + } + + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ConstructorReferenceTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ConstructorReferenceTestCase.java new file mode 100644 index 0000000000..687c95e860 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ConstructorReferenceTestCase.java @@ -0,0 +1,173 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Constructor; +import java.util.List; + +import org.osoa.sca.annotations.Reference; + +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; + +/** + * @version $Rev$ $Date$ + */ +public class ConstructorReferenceTestCase extends TestCase { + + ConstructorProcessor processor; + + public void testReference() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Foo> ctor = Foo.class.getConstructor(String.class); + processor.visitConstructor(null, ctor, type, null); + JavaMappedReference reference = type.getReferences().get("myRef"); + assertTrue(reference.isRequired()); + assertEquals("myRef", reference.getName()); + } + + public void testTwoReferencesSameType() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Foo> ctor = Foo.class.getConstructor(String.class, String.class); + processor.visitConstructor(null, ctor, type, null); + assertNotNull(type.getReferences().get("myRef1")); + assertNotNull(type.getReferences().get("myRef2")); + } + + public void testDuplicateProperty() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<BadFoo> ctor = BadFoo.class.getConstructor(String.class, String.class); + try { + processor.visitConstructor(null, ctor, type, null); + fail(); + } catch (DuplicateReferenceException e) { + // expected + } + } + + public void testNoName() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<BadFoo> ctor = BadFoo.class.getConstructor(String.class); + try { + processor.visitConstructor(null, ctor, type, null); + fail(); + } catch (InvalidReferenceException e) { + // expected + } + } + + public void testNamesOnConstructor() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Foo> ctor = Foo.class.getConstructor(Integer.class); + processor.visitConstructor(null, ctor, type, null); + assertNotNull(type.getReferences().get("myRef")); + } + + public void testInvalidNumberOfNames() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<BadFoo> ctor = BadFoo.class.getConstructor(Integer.class, Integer.class); + try { + processor.visitConstructor(null, ctor, type, null); + fail(); + } catch (InvalidReferenceException e) { + // expected + } + } + + public void testNoMatchingNames() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<BadFoo> ctor = BadFoo.class.getConstructor(List.class, List.class); + try { + processor.visitConstructor(null, ctor, type, null); + fail(); + } catch (InvalidConstructorException e) { + // expected + } + } + + protected void setUp() throws Exception { + super.setUp(); + processor = + new ConstructorProcessor(new ImplementationProcessorServiceImpl(new JavaInterfaceProcessorRegistryImpl())); + } + +// public void testMultiplicityRequired() throws Exception { + // TODO multiplicity +// } + + private static class Foo { + + @org.osoa.sca.annotations.Constructor() + public Foo(@Reference(name = "myRef", required = true) String prop) { + + } + + @org.osoa.sca.annotations.Constructor() + public Foo(@Reference(name = "myRef1") String prop1, @Reference(name = "myRef2") String prop2) { + + } + + @org.osoa.sca.annotations.Constructor("myRef") + public Foo(@Reference Integer prop) { + + } + + @org.osoa.sca.annotations.Constructor() + public Foo(@Reference List prop) { + + } + } + + private static class BadFoo { + + @org.osoa.sca.annotations.Constructor + public BadFoo(@Reference(name = "myRef") String prop1, @Reference(name = "myRef") String prop2) { + + } + + @org.osoa.sca.annotations.Constructor + public BadFoo(@Reference String prop) { + + } + + @org.osoa.sca.annotations.Constructor("myRef") + public BadFoo(@Reference Integer ref, @Reference Integer ref2) { + + } + + @org.osoa.sca.annotations.Constructor({"myRef", "myRef2"}) + public BadFoo(@Reference List ref, @Reference(name = "myOtherRef") List ref2) { + + } + + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/DestroyProcessorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/DestroyProcessorTestCase.java new file mode 100644 index 0000000000..6929250298 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/DestroyProcessorTestCase.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Method; + +import org.osoa.sca.annotations.Destroy; + +import org.apache.tuscany.spi.implementation.java.JavaMappedService; + +import junit.framework.TestCase; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; + +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; + +/** + * @version $Rev$ $Date$ + */ +public class DestroyProcessorTestCase extends TestCase { + + public void testDestroy() throws Exception { + DestroyProcessor processor = new DestroyProcessor(); + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Method method = Foo.class.getMethod("destroy"); + processor.visitMethod(null, method, type, null); + assertNotNull(type.getDestroyMethod()); + } + + public void testBadDestroy() throws Exception { + DestroyProcessor processor = new DestroyProcessor(); + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Method method = Bar.class.getMethod("badDestroy", String.class); + try { + processor.visitMethod(null, method, type, null); + fail(); + } catch (IllegalDestructorException e) { + // expected + } + } + + public void testTwoDestroy() throws Exception { + DestroyProcessor processor = new DestroyProcessor(); + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Method method = Bar.class.getMethod("destroy"); + Method method2 = Bar.class.getMethod("destroy2"); + processor.visitMethod(null, method, type, null); + try { + processor.visitMethod(null, method2, type, null); + fail(); + } catch (DuplicateDestructorException e) { + // expected + } + } + + + private class Foo { + + @Destroy + public void destroy() { + } + } + + + private class Bar { + + @Destroy + public void destroy() { + } + + @Destroy + public void destroy2() { + } + + @Destroy + public void badDestroy(String foo) { + } + + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/HeuristicAndPropertyTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/HeuristicAndPropertyTestCase.java new file mode 100644 index 0000000000..93de605e33 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/HeuristicAndPropertyTestCase.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Constructor; + +import org.osoa.sca.annotations.Property; + +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; + +/** + * @version $Rev$ $Date$ + */ +public class HeuristicAndPropertyTestCase extends TestCase { + + private PropertyProcessor propertyProcessor; + private HeuristicPojoProcessor heuristicProcessor; + + /** + * Verifies the property and heuristic processors don't collide + */ + @SuppressWarnings("unchecked") + public void testPropertyProcessorWithHeuristicProcessor() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor ctor = Foo.class.getConstructor(String.class); + type.setConstructorDefinition(new ConstructorDefinition(ctor)); + propertyProcessor.visitConstructor(null, ctor, type, null); + heuristicProcessor.visitEnd(null, Foo.class, type, null); + assertEquals(1, type.getProperties().size()); + assertNotNull(type.getProperties().get("foo")); + } + + protected void setUp() throws Exception { + super.setUp(); + ImplementationProcessorServiceImpl service = + new ImplementationProcessorServiceImpl(new JavaInterfaceProcessorRegistryImpl()); + propertyProcessor = new PropertyProcessor(service); + heuristicProcessor = new HeuristicPojoProcessor(service); + } + + public static class Foo { + public Foo(@Property(name = "foo") String prop) { + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/HeuristicConstructorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/HeuristicConstructorTestCase.java new file mode 100644 index 0000000000..92f6d54366 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/HeuristicConstructorTestCase.java @@ -0,0 +1,330 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.osoa.sca.annotations.Property; +import org.osoa.sca.annotations.Reference; +import org.osoa.sca.annotations.Remotable; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.model.ServiceContract; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; + +/** + * @version $Rev$ $Date$ + */ +public class HeuristicConstructorTestCase extends TestCase { + + private HeuristicPojoProcessor processor = + new HeuristicPojoProcessor(new ImplementationProcessorServiceImpl(new JavaInterfaceProcessorRegistryImpl())); + + /** + * Verifies a single constructor is chosen with a parameter as the type + */ + public void testSingleConstructorWithParam() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + JavaMappedProperty<String> prop = new JavaMappedProperty<String>(); + prop.setName("foo"); + prop.setJavaType(String.class); + type.getProperties().put("foo", prop); + processor.visitEnd(null, Foo1.class, type, null); + assertNotNull(type.getConstructorDefinition().getConstructor()); + assertEquals("foo", type.getConstructorDefinition().getInjectionNames().get(0)); + } + + /** + * Verifies a single constructor is chosen with a reference as the type + */ + public void testSingleConstructorWithRef() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + JavaMappedReference ref = new JavaMappedReference(); + ref.setName("foo"); + ServiceContract contract = new JavaServiceContract(String.class); + ref.setServiceContract(contract); + type.getReferences().put("foo", ref); + processor.visitEnd(null, Foo1.class, type, null); + assertNotNull(type.getConstructorDefinition().getConstructor()); + assertEquals("foo", type.getConstructorDefinition().getInjectionNames().get(0)); + } + + /** + * Verifies a single constructor is chosen with a property and a reference as the type + */ + public void testSingleConstructorWithPropRef() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + + JavaMappedProperty<String> prop = new JavaMappedProperty<String>(); + prop.setName("foo"); + prop.setJavaType(String.class); + type.getProperties().put("foo", prop); + + JavaMappedReference ref = new JavaMappedReference(); + ref.setName("ref"); + ServiceContract contract = new JavaServiceContract(Foo1.class); + ref.setServiceContract(contract); + type.getReferences().put("ref", ref); + processor.visitEnd(null, Foo2.class, type, null); + assertNotNull(type.getConstructorDefinition().getConstructor()); + assertEquals(2, type.getConstructorDefinition().getInjectionNames().size()); + } + + + public void testSingleConstructorResolvableParam() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitEnd(null, Foo5.class, type, null); + assertEquals(String.class, type.getProperties().get("string").getJavaType()); + } + + public void testSingleConstructorResolvableRef() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitEnd(null, Foo6.class, type, null); + assertEquals(Ref.class, + type.getReferences().get("heuristicconstructortestcase$ref").getServiceContract().getInterfaceClass()); + } + + public void testSingleConstructorAmbiguousRef() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + JavaMappedReference ref = new JavaMappedReference(); + ref.setName("ref"); + ServiceContract contract = new JavaServiceContract(Foo1.class); + ref.setServiceContract(contract); + type.getReferences().put("ref", ref); + JavaMappedReference ref2 = new JavaMappedReference(); + ref2.setName("ref2"); + ref2.setServiceContract(contract); + type.getReferences().put("ref2", ref2); + try { + processor.visitEnd(null, Foo4.class, type, null); + fail(); + } catch (AmbiguousConstructorException e) { + // expected + } + } + + public void testConstructorPropertyAnnotatedParamsOnly() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitEnd(null, Foo7.class, type, null); + assertNotNull(type.getProperties().get("myProp")); + } + + public void testConstructorReferenceAnnotatedParamsOnly() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitEnd(null, Foo8.class, type, null); + assertNotNull(type.getReferences().get("myRef")); + } + + public void testConstructorAutowireAnnotatedParamsOnly() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitEnd(null, Foo9.class, type, null); + assertNotNull(type.getReferences().get("myAutowire")); + } + + @SuppressWarnings("unchecked") + public void testDefaultConstructor() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitEnd(null, Foo3.class, type, null); + assertNotNull(type.getConstructorDefinition().getConstructor()); + } + + public void testSameTypesButAnnotated() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitEnd(null, Foo12.class, type, null); + assertEquals(2, type.getProperties().size()); + assertNotNull(type.getProperties().get("prop1")); + assertNotNull(type.getProperties().get("prop2")); + } + + /** + * Verifies processing executes with additional extension annotations + */ + public void testRandomAnnotation() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitEnd(null, Foo11.class, type, null); + assertEquals(1, type.getProperties().size()); + assertNotNull(type.getProperties().get("prop1")); + } + + public void testAutowire() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitEnd(null, Foo13.class, type, null); + assertEquals(1, type.getReferences().size()); + assertNotNull(type.getReferences().get(String.class.getName() + "0")); + } + + public void testMultipleAutowire() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitEnd(null, Foo15.class, type, null); + assertEquals(2, type.getReferences().size()); + assertNotNull(type.getReferences().get(String.class.getName() + "0")); + assertNotNull(type.getReferences().get(String.class.getName() + "1")); + } + + public void testNoAutowireNameInConstructor() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitEnd(null, Foo16.class, type, null); + assertEquals(2, type.getReferences().size()); + assertNotNull(type.getReferences().get(String.class.getName() + "0")); + assertNotNull(type.getReferences().get("bar")); + assertNotNull(type.getProperties().get("foo")); + } + + public void testPrivateConstructor() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + try { + processor.visitEnd(null, Foo14.class, type, null); + fail(); + } catch (NoConstructorException e) { + // expected + } + } + + + public void testMultipleConstructors() throws Exception { + // throw new UnsupportedOperationException("Finish heuristic multiple constructors - Foo10"); + } + + + public static class Foo1 { + public Foo1(String val) { + } + } + + public static class Foo2 { + public Foo2(String val, Foo1 ref) { + } + } + + public static class Foo3 { + } + + public static class Foo4 { + public Foo4(Foo1 ref) { + } + } + + public static class Prop { + + } + + @Remotable + public static interface Ref { + + } + + public static class Foo5 { + public Foo5(String val) { + } + } + + public static class Foo6 { + public Foo6(Ref ref) { + } + } + + public static class Foo7 { + public Foo7(@Property(name = "myProp") String prop) { + } + } + + + public static class Foo8 { + public Foo8(@Reference(name = "myRef") String ref) { + } + } + + public static class Foo9 { + public Foo9(@Autowire(name = "myAutowire") String autowire) { + } + } + + public static class Foo10 { + + public Foo10() { + } + + public Foo10(String prop) { + } + + public Foo10(@Property(name = "prop1") String prop1, @Property(name = "prop2") String prop2) { + + } + } + + public static class Foo11 { + + public Foo11(@Property(name = "prop1") String prop, @Baz String baz) { + } + } + + public static class Foo12 { + + public Foo12(@Property(name = "prop1") String prop, @Property(name = "prop2") String baz) { + } + } + + public @interface Baz { + + } + + public static class Foo13 { + public Foo13(@Autowire String foo) { + } + } + + public static final class Foo14 { + private Foo14() { + } + } + + public static final class Foo15 { + public Foo15(@Autowire String param1, @Autowire String param2) { + } + } + + public static final class Foo16 { + public Foo16(@Autowire String param1, + @Property(name = "foo") String param2, + @Reference(name = "bar") String param3) { + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/HeuristicPojoProcessorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/HeuristicPojoProcessorTestCase.java new file mode 100644 index 0000000000..659cbbd115 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/HeuristicPojoProcessorTestCase.java @@ -0,0 +1,367 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Constructor; +import java.util.Collection; +import java.util.List; + +import org.osoa.sca.annotations.Property; +import org.osoa.sca.annotations.Reference; +import org.osoa.sca.annotations.Remotable; +import org.osoa.sca.annotations.Service; + +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; + +/** + * Verfies component type information is properly introspected from an unadorned POJO according to the SCA Java Client + * and Implementation Model Specification + * + * @version $Rev$ $Date$ + */ +public class HeuristicPojoProcessorTestCase extends TestCase { + + private HeuristicPojoProcessor processor = + new HeuristicPojoProcessor(new ImplementationProcessorServiceImpl(new JavaInterfaceProcessorRegistryImpl())); + + /** + * Verifies a single service interface is computed when only one interface is implemented + */ + public void testSingleInterface() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<SingleInterfaceImpl> ctor = SingleInterfaceImpl.class.getConstructor(); + type.setConstructorDefinition(new ConstructorDefinition<SingleInterfaceImpl>(ctor)); + processor.visitEnd(null, SingleInterfaceImpl.class, type, null); + assertEquals(1, type.getServices().size()); + assertEquals(PropertyInterface.class, + type.getServices().get("HeuristicPojoProcessorTestCase$PropertyInterface") + .getServiceContract().getInterfaceClass()); + assertTrue(type.getProperties().isEmpty()); + assertTrue(type.getReferences().isEmpty()); + } + + /** + * Verifies property and reference setters are computed + */ + public void testPropertyReference() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<SingleInterfaceWithPropertyReferenceImpl> ctor = + SingleInterfaceWithPropertyReferenceImpl.class.getConstructor(); + type.setConstructorDefinition(new ConstructorDefinition<SingleInterfaceWithPropertyReferenceImpl>(ctor)); + processor.visitEnd(null, SingleInterfaceWithPropertyReferenceImpl.class, type, null); + assertEquals(1, type.getServices().size()); + assertEquals(Interface1.class, + type.getServices().get("HeuristicPojoProcessorTestCase$Interface1") + .getServiceContract().getInterfaceClass()); + assertEquals(1, type.getProperties().size()); + assertEquals(ComplexProperty.class, type.getProperties().get("property").getJavaType()); + assertEquals(1, type.getReferences().size()); + assertEquals(Ref.class, type.getReferences().get("reference").getServiceContract().getInterfaceClass()); + } + + /** + * Verifies that a property setter is not introspected if an analogous operation is in the service interface + */ + public void testPropertySetterInInterface() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<SingleInterfaceImpl> ctor = SingleInterfaceImpl.class.getConstructor(); + type.setConstructorDefinition(new ConstructorDefinition<SingleInterfaceImpl>(ctor)); + processor.visitEnd(null, SingleInterfaceImpl.class, type, null); + assertEquals(0, type.getProperties().size()); + } + + /** + * Verifies that a reference setter is not introspected if an analogous operation is in the service interface + */ + public void testReferenceSetterInInterface() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<RefInterfaceImpl> ctor = RefInterfaceImpl.class.getConstructor(); + type.setConstructorDefinition(new ConstructorDefinition<RefInterfaceImpl>(ctor)); + processor.visitEnd(null, RefInterfaceImpl.class, type, null); + assertEquals(0, type.getReferences().size()); + } + + /** + * Verifies collection generic types or array types are introspected as references according to spec rules + */ + public void testReferenceCollectionType() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<ReferenceCollectionImpl> ctor = ReferenceCollectionImpl.class.getConstructor(); + type.setConstructorDefinition(new ConstructorDefinition<ReferenceCollectionImpl>(ctor)); + processor.visitEnd(null, ReferenceCollectionImpl.class, type, null); + assertEquals(0, type.getProperties().size()); + assertEquals(4, type.getReferences().size()); + } + + /** + * Verifies collection generic types or array types are introspected as properties according to spec rules + */ + public void testPropertyCollectionType() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<PropertyCollectionImpl> ctor = PropertyCollectionImpl.class.getConstructor(); + type.setConstructorDefinition(new ConstructorDefinition<PropertyCollectionImpl>(ctor)); + processor.visitEnd(null, PropertyCollectionImpl.class, type, null); + assertEquals(0, type.getReferences().size()); + assertEquals(4, type.getProperties().size()); + } + + /** + * Verifies references are calculated when the type marked with is @Remotable + */ + public void testRemotableRef() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<RemotableRefImpl> ctor = RemotableRefImpl.class.getConstructor(); + type.setConstructorDefinition(new ConstructorDefinition<RemotableRefImpl>(ctor)); + processor.visitEnd(null, RemotableRefImpl.class, type, null); + assertEquals(2, type.getReferences().size()); + assertEquals(0, type.getProperties().size()); + } + + public void testParentInterface() throws ProcessingException, NoSuchMethodException { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Child> ctor = Child.class.getConstructor(); + type.setConstructorDefinition(new ConstructorDefinition<Child>(ctor)); + processor.visitEnd(null, Child.class, type, null); + assertTrue(type.getServices().containsKey("HeuristicPojoProcessorTestCase$Interface1")); + } + + /** + * Verifies a service inteface is calculated when only props and refs are given + */ + public void testExcludedPropertyAndReference() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + JavaMappedReference ref = new JavaMappedReference(); + ref.setName("reference"); + type.add(ref); + JavaMappedReference ref2 = new JavaMappedReference(); + ref2.setName("reference2"); + type.add(ref2); + JavaMappedProperty<?> prop1 = new JavaMappedProperty(); + prop1.setName("string1"); + type.add(prop1); + JavaMappedProperty<?> prop2 = new JavaMappedProperty(); + prop2.setName("string2"); + type.add(prop2); + processor.visitEnd(null, ServiceImpl.class, type, null); + assertEquals(1, type.getServices().size()); + } + + public void testProtectedRemotableRefField() throws ProcessingException, NoSuchMethodException { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<ProtectedRemotableRefFieldImpl> ctor = ProtectedRemotableRefFieldImpl.class.getConstructor(); + type.setConstructorDefinition(new ConstructorDefinition<ProtectedRemotableRefFieldImpl>(ctor)); + processor.visitEnd(null, ProtectedRemotableRefFieldImpl.class, type, null); + assertNotNull(type.getReferences().get("otherRef")); + } + + public void testProtectedRemotableRefMethod() throws ProcessingException, NoSuchMethodException { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<ProtectedRemotableRefMethodImpl> ctor = ProtectedRemotableRefMethodImpl.class.getConstructor(); + type.setConstructorDefinition(new ConstructorDefinition<ProtectedRemotableRefMethodImpl>(ctor)); + processor.visitEnd(null, ProtectedRemotableRefMethodImpl.class, type, null); + assertNotNull(type.getReferences().get("otherRef")); + } + + private interface PropertyInterface { + void setString1(String val); + } + + private interface Interface1 { + } + + private static class Parent implements Interface1 { + + } + + private static class Child extends Parent { + public Child() { + } + + } + + private static class SingleInterfaceImpl implements PropertyInterface { + public SingleInterfaceImpl() { + } + + public void setString1(String val) { + } + + } + + private interface HeuristicServiceInterface { + void fooOperation(String ref); + void setInvalid1(); // No parameter + void setInvalid2(String str, int i); // More than one parameter + String setInvalid3(String str); // return should be void + } + + public static class ServiceImpl implements PropertyInterface, RefInterface, HeuristicServiceInterface { + + @Property + public void setString1(String val) { + } + + @Property + public void setString2(String val) { + } + + @Reference + public void setReference(Ref ref) { + } + + @Reference + public void setReference2(Ref ref) { + } + + public void fooOperation(String ref) { + + } + public void setInvalid1() { + } + + public void setInvalid2(String str, int i) { + } + + public String setInvalid3(String str) { + return null; + } + + } + + @Service + private interface Ref { + } + + private class ComplexProperty { + } + + private interface RefInterface { + void setReference(Ref ref); + } + + private static class RefInterfaceImpl implements RefInterface { + public RefInterfaceImpl() { + } + + public void setReference(Ref ref) { + } + } + + private static class SingleInterfaceWithPropertyReferenceImpl implements Interface1 { + public SingleInterfaceWithPropertyReferenceImpl() { + } + + public void setReference(Ref ref) { + } + + public void setProperty(ComplexProperty prop) { + } + } + + private static class ReferenceCollectionImpl implements Interface1 { + public ReferenceCollectionImpl() { + } + + public void setCollectionReference(Collection<Ref> ref) { + } + + public void setNonGenericCollectionReference(Collection ref) { + } + + public void setListReference(List<Ref> ref) { + } + + public void setArrayReference(Ref[] ref) { + } + } + + private static class PropertyCollectionImpl implements Interface1 { + public PropertyCollectionImpl() { + } + + public void setCollectionProperty(Collection<ComplexProperty> prop) { + } + + public void setCollectionProperty2(Collection<String> prop) { + } + + public void setArrayProperty(ComplexProperty[] prop) { + } + + public void setArrayProperty2(String[] prop) { + } + } + + @Remotable + private interface RemotableRef { + } + + private static class RemotableRefImpl implements Interface1 { + protected RemotableRef otherRef; + + public RemotableRefImpl() { + } + + public void setRef(RemotableRef ref) { + + } + } + + private static class ProtectedRemotableRefFieldImpl implements Interface1 { + protected RemotableRef otherRef; + + public ProtectedRemotableRefFieldImpl() { + } + + public ProtectedRemotableRefFieldImpl(RemotableRef otherRef) { + this.otherRef = otherRef; + } + + } + + private static class ProtectedRemotableRefMethodImpl implements Interface1 { + public ProtectedRemotableRefMethodImpl() { + } + + protected void setOtherRef(RemotableRef otherRef) { + } + + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/HeutisticExtensibleConstructorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/HeutisticExtensibleConstructorTestCase.java new file mode 100644 index 0000000000..4e6c1063d8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/HeutisticExtensibleConstructorTestCase.java @@ -0,0 +1,129 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Constructor; +import java.util.List; + +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; + +/** + * Verifies constructors that have extensible annotation types, i.e. that have parameters marked by annotations which + * are themselves processed by some other implementation processor + * + * @version $Rev$ $Date$ + */ +public class HeutisticExtensibleConstructorTestCase extends TestCase { + + private HeuristicPojoProcessor processor = + new HeuristicPojoProcessor(new ImplementationProcessorServiceImpl(new JavaInterfaceProcessorRegistryImpl())); + + /** + * Verifies heuristic processing can be called priot to an extension annotation processors being called. + */ + public void testBarAnnotationProcessedFirst() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Foo> ctor = Foo.class.getConstructor(String.class, String.class); + ConstructorDefinition<Foo> definition = new ConstructorDefinition<Foo>(ctor); + type.setConstructorDefinition(definition); + JavaMappedProperty property = new JavaMappedProperty(); + property.setName("myBar"); + definition.getInjectionNames().add("myBar"); + type.getProperties().put("myBar", property); + processor.visitEnd(null, Foo.class, type, null); + assertEquals(2, type.getProperties().size()); + } + + /** + * Verifies heuristic processing can be called before an extension annotation processors is called. + * <p/> + * For example, given: + * <pre> Foo(@Bar String prop, @org.osoa.sca.annotations.Property(name = "foo") String prop2)</pre> + * <p/> + * Heuristic evaluation of @Property can occur prior to another implementation processor evaluating @Bar + * + * @throws Exception + */ + public void testBarAnnotationProcessedLast() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitEnd(null, Foo.class, type, null); + + // now simulate process the bar impl + ConstructorDefinition<?> definition = type.getConstructorDefinition(); + List<String> injectionNames = definition.getInjectionNames(); + injectionNames.remove(0); + injectionNames.add(0, "mybar"); + type.getProperties().put("mybar", new JavaMappedProperty<String>()); + + assertEquals(2, type.getProperties().size()); + assertEquals("foo", definition.getInjectionNames().get(1)); + } + + /** + * Verifies heuristic processing can be called before an extension annotation processors is called with the + * extension parameter in a middle position. Specifically, verifies that the heuristic processor updates injection + * names and preserves their ordering. + */ + public void testBarAnnotationProcessedFirstInMiddle() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Foo2> ctor = Foo2.class.getConstructor(String.class, String.class, String.class); + ConstructorDefinition<Foo2> definition = new ConstructorDefinition<Foo2>(ctor); + type.setConstructorDefinition(definition); + // insert placeholder for first param, which would be done by a processor + definition.getInjectionNames().add(""); + JavaMappedProperty property = new JavaMappedProperty(); + property.setName("myBar"); + definition.getInjectionNames().add("myBar"); + type.getProperties().put("myBar", property); + processor.visitEnd(null, Foo2.class, type, null); + assertEquals("baz", definition.getInjectionNames().get(0)); + assertEquals(2, type.getProperties().size()); + assertEquals(1, type.getReferences().size()); + } + + public @interface Bar { + + } + + public static class Foo { + public Foo(@Bar String prop, @org.osoa.sca.annotations.Property(name = "foo") String prop2) { + } + } + + public static class Foo2 { + public Foo2(@org.osoa.sca.annotations.Reference(name = "baz") String prop1, + @Bar String prop2, + @org.osoa.sca.annotations.Property(name = "foo") String prop3) { + } + } + + +} + + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceTestCase.java new file mode 100644 index 0000000000..3fbe5a8350 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceTestCase.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.osoa.sca.annotations.Callback; +import org.osoa.sca.annotations.Remotable; +import org.osoa.sca.annotations.Scope; + +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService; +import org.apache.tuscany.spi.model.InteractionScope; +import org.apache.tuscany.spi.model.ServiceContract; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; + +/** + * @version $Rev$ $Date$ + */ +public class ImplementationProcessorServiceTestCase extends TestCase { + + private ImplementationProcessorService implService = + new ImplementationProcessorServiceImpl(new JavaInterfaceProcessorRegistryImpl()); + + public void testCreateConversationalService() throws Exception { + JavaMappedService service = implService.createService(Foo.class); + assertTrue(Foo.class.equals(service.getServiceContract().getInterfaceClass())); + assertTrue(service.isRemotable()); + assertEquals(InteractionScope.CONVERSATIONAL, service.getServiceContract().getInteractionScope()); + ServiceContract serviceContract = service.getServiceContract(); + assertTrue(Bar.class.equals(serviceContract.getCallbackClass())); + assertTrue("ImplementationProcessorServiceTestCase$Bar".equals(serviceContract.getCallbackName())); + } + + public void testCreateDefaultService() throws Exception { + JavaMappedService service = implService.createService(Baz.class); + assertTrue(Baz.class.equals(service.getServiceContract().getInterfaceClass())); + assertTrue(!service.isRemotable()); + assertEquals(InteractionScope.NONCONVERSATIONAL, service.getServiceContract().getInteractionScope()); + } + + + @Callback(Bar.class) + @Remotable + @Scope("CONVERSATIONAL") + public interface Foo { + + } + + public interface Bar { + + } + + public interface Baz { + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceUniqueTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceUniqueTestCase.java new file mode 100644 index 0000000000..da45ed2d46 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ImplementationProcessorServiceUniqueTestCase.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; + +/** + * @version $Rev$ $Date$ + */ +public class ImplementationProcessorServiceUniqueTestCase extends TestCase { + + private ImplementationProcessorService service = + new ImplementationProcessorServiceImpl(new JavaInterfaceProcessorRegistryImpl()); + + public void testUniquess1() throws Exception { + Class[] classes = new Class[2]; + classes[0] = String.class; + classes[1] = Integer.class; + assertTrue(service.areUnique(classes)); + } + + public void testUniquess2() throws Exception { + Class[] classes = new Class[2]; + classes[0] = String.class; + classes[1] = String.class; + assertFalse(service.areUnique(classes)); + } + + public void testUniquess3() throws Exception { + Class[] classes = new Class[1]; + classes[0] = String.class; + assertTrue(service.areUnique(classes)); + } + + public void testUniquess4() throws Exception { + Class[] classes = new Class[3]; + classes[0] = String.class; + classes[1] = Integer.class; + classes[2] = String.class; + assertFalse(service.areUnique(classes)); + } + + public void testUniquess5() throws Exception { + Class[] classes = new Class[0]; + assertTrue(service.areUnique(classes)); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/InitProcessorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/InitProcessorTestCase.java new file mode 100644 index 0000000000..059094f922 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/InitProcessorTestCase.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Method; + +import org.osoa.sca.annotations.Init; + +import org.apache.tuscany.spi.implementation.java.JavaMappedService; + +import junit.framework.TestCase; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; + +/** + * @version $Rev$ $Date$ + */ +public class InitProcessorTestCase extends TestCase { + + public void testInit() throws Exception { + InitProcessor processor = new InitProcessor(); + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Method method = InitProcessorTestCase.Foo.class.getMethod("init"); + processor.visitMethod(null, method, type, null); + assertNotNull(type.getInitMethod()); + assertEquals(50, type.getInitLevel()); + } + + public void testBadInit() throws Exception { + InitProcessor processor = new InitProcessor(); + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Method method = InitProcessorTestCase.Bar.class.getMethod("badInit", String.class); + try { + processor.visitMethod(null, method, type, null); + fail(); + } catch (IllegalInitException e) { + // expected + } + } + + public void testTwoInit() throws Exception { + InitProcessor processor = new InitProcessor(); + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Method method = InitProcessorTestCase.Bar.class.getMethod("init"); + Method method2 = InitProcessorTestCase.Bar.class.getMethod("init2"); + processor.visitMethod(null, method, type, null); + try { + processor.visitMethod(null, method2, type, null); + fail(); + } catch (DuplicateInitException e) { + // expected + } + } + + + private class Foo { + @Init(eager = true) + public void init() { + } + } + + + private class Bar { + @Init + public void init() { + } + + @Init + public void init2() { + } + + @Init + public void badInit(String foo) { + } + + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/MonitorProcessorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/MonitorProcessorTestCase.java new file mode 100644 index 0000000000..8982fa3991 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/MonitorProcessorTestCase.java @@ -0,0 +1,180 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Map; + +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.IllegalPropertyException; + +import junit.framework.TestCase; +import org.apache.tuscany.api.annotation.Monitor; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.injection.SingletonObjectFactory; +import org.apache.tuscany.host.MonitorFactory; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class MonitorProcessorTestCase extends TestCase { + + private MonitorProcessor processor; + private MonitorFactory monitorFactory; + + public void testSetter() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Method method = Foo.class.getMethod("setMonitor", Foo.class); + EasyMock.expect(monitorFactory.getMonitor(EasyMock.eq(Foo.class))).andReturn(null); + EasyMock.replay(monitorFactory); + processor.visitMethod(null, method, type, null); + Map<String, JavaMappedProperty<?>> properties = type.getProperties(); + assertTrue(properties.get("monitor").getDefaultValueFactory() instanceof SingletonObjectFactory); + EasyMock.verify(monitorFactory); + } + + + public void testBadSetter() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Method method = BadMonitor.class.getMethod("setMonitor"); + try { + processor.visitMethod(null, method, type, null); + fail(); + } catch (IllegalPropertyException e) { + // expected + } + } + + public void testField() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Field field = Foo.class.getDeclaredField("bar"); + EasyMock.expect(monitorFactory.getMonitor(EasyMock.eq(Foo.class))).andReturn(null); + EasyMock.replay(monitorFactory); + processor.visitField(null, field, type, null); + Map<String, JavaMappedProperty<?>> properties = type.getProperties(); + assertTrue(properties.get("bar").getDefaultValueFactory() instanceof SingletonObjectFactory); + EasyMock.verify(monitorFactory); + } + + public void testConstructor() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Bar> ctor = Bar.class.getConstructor(BazMonitor.class); + EasyMock.expect(monitorFactory.getMonitor(EasyMock.eq(BazMonitor.class))).andReturn(null); + EasyMock.replay(monitorFactory); + processor.visitConstructor(null, ctor, type, null); + Map<String, JavaMappedProperty<?>> properties = type.getProperties(); + assertTrue( + properties.get(BazMonitor.class.getName()).getDefaultValueFactory() instanceof SingletonObjectFactory); + EasyMock.verify(monitorFactory); + } + + /** + * Verifies calling the monitor processor to evaluate a constructor can be done after a property parameter is + * processed + */ + public void testConstructorAfterProperty() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Bar> ctor = Bar.class.getConstructor(String.class, BazMonitor.class); + EasyMock.expect(monitorFactory.getMonitor(EasyMock.eq(BazMonitor.class))).andReturn(null); + EasyMock.replay(monitorFactory); + ConstructorDefinition<Bar> definition = new ConstructorDefinition<Bar>(ctor); + JavaMappedProperty prop = new JavaMappedProperty(); + definition.getInjectionNames().add("prop"); + type.setConstructorDefinition(definition); + type.getProperties().put("prop", prop); + processor.visitConstructor(null, ctor, type, null); + Map<String, JavaMappedProperty<?>> properties = type.getProperties(); + assertEquals(BazMonitor.class.getName(), definition.getInjectionNames().get(1)); + assertEquals(2, type.getProperties().size()); + String name = BazMonitor.class.getName(); + assertTrue(properties.get(name).getDefaultValueFactory() instanceof SingletonObjectFactory); + EasyMock.verify(monitorFactory); + } + + /** + * Verifies calling the monitor processor to evaluate a constructor can be done before a property parameter is + * processed + */ + public void testConstructorBeforeProperty() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + Constructor<Bar> ctor = Bar.class.getConstructor(String.class, BazMonitor.class); + EasyMock.expect(monitorFactory.getMonitor(EasyMock.eq(BazMonitor.class))).andReturn(null); + EasyMock.replay(monitorFactory); + processor.visitConstructor(null, ctor, type, null); + Map<String, JavaMappedProperty<?>> properties = type.getProperties(); + ConstructorDefinition definition = type.getConstructorDefinition(); + assertEquals(2, definition.getInjectionNames().size()); + assertEquals(BazMonitor.class.getName(), definition.getInjectionNames().get(1)); + String name = BazMonitor.class.getName(); + assertTrue(properties.get(name).getDefaultValueFactory() instanceof SingletonObjectFactory); + EasyMock.verify(monitorFactory); + } + + protected void setUp() throws Exception { + super.setUp(); + monitorFactory = EasyMock.createMock(MonitorFactory.class); + JavaInterfaceProcessorRegistryImpl registry = new JavaInterfaceProcessorRegistryImpl(); + ImplementationProcessorServiceImpl processor = new ImplementationProcessorServiceImpl(registry); + this.processor = new MonitorProcessor(monitorFactory, processor); + } + + private class Foo { + + @Monitor + protected Foo bar; + + @Monitor + public void setMonitor(Foo foo) { + } + } + + + private class BadMonitor { + + @Monitor + public void setMonitor() { + } + } + + private interface BazMonitor { + + } + + private static class Bar { + + public Bar(@Monitor BazMonitor monitor) { + } + + public Bar(String prop, @Monitor BazMonitor monitor) { + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/PropertyProcessorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/PropertyProcessorTestCase.java new file mode 100644 index 0000000000..412c9f9d36 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/PropertyProcessorTestCase.java @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import static org.apache.tuscany.spi.model.OverrideOptions.MUST; +import junit.framework.TestCase; + +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.spi.implementation.java.DuplicatePropertyException; +import org.apache.tuscany.spi.implementation.java.IllegalPropertyException; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.model.OverrideOptions; +import org.osoa.sca.annotations.Property; + +/** + * @version $Rev$ $Date$ + */ +public class PropertyProcessorTestCase extends TestCase { + + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type; + PropertyProcessor processor; + + public void testMethodAnnotation() throws Exception { + processor.visitMethod(null, Foo.class.getMethod("setFoo", String.class), type, null); + assertNotNull(type.getProperties().get("foo")); + } + + public void testMethodRequired() throws Exception { + processor.visitMethod(null, Foo.class.getMethod("setFooRequired", String.class), type, null); + JavaMappedProperty prop = type.getProperties().get("fooRequired"); + assertNotNull(prop); + assertEquals(prop.getOverride(), MUST); + } + + public void testMethodName() throws Exception { + processor.visitMethod(null, Foo.class.getMethod("setBarMethod", String.class), type, null); + assertNotNull(type.getProperties().get("bar")); + } + + public void testFieldAnnotation() throws Exception { + processor.visitField(null, Foo.class.getDeclaredField("baz"), type, null); + assertNotNull(type.getProperties().get("baz")); + } + + public void testFieldRequired() throws Exception { + processor.visitField(null, Foo.class.getDeclaredField("bazRequired"), type, null); + JavaMappedProperty prop = type.getProperties().get("bazRequired"); + assertNotNull(prop); + assertEquals(prop.getOverride(), OverrideOptions.MUST); + } + + public void testFieldName() throws Exception { + processor.visitField(null, Foo.class.getDeclaredField("bazField"), type, null); + assertNotNull(type.getProperties().get("theBaz")); + } + + public void testDuplicateFields() throws Exception { + processor.visitField(null, Bar.class.getDeclaredField("dup"), type, null); + try { + processor.visitField(null, Bar.class.getDeclaredField("baz"), type, null); + fail(); + } catch (DuplicatePropertyException e) { + // expected + } + } + + public void testDuplicateMethods() throws Exception { + processor.visitMethod(null, Bar.class.getMethod("dupMethod", String.class), type, null); + try { + processor.visitMethod(null, Bar.class.getMethod("dupSomeMethod", String.class), type, null); + fail(); + } catch (DuplicatePropertyException e) { + // expected + } + } + + public void testInvalidProperty() throws Exception { + try { + processor.visitMethod(null, Bar.class.getMethod("badMethod"), type, null); + fail(); + } catch (IllegalPropertyException e) { + // expected + } + } + + protected void setUp() throws Exception { + super.setUp(); + type = new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + JavaInterfaceProcessorRegistryImpl registry = new JavaInterfaceProcessorRegistryImpl(); + processor = new PropertyProcessor(new ImplementationProcessorServiceImpl(registry)); + } + + private class Foo { + + @Property + protected String baz; + @Property(override = "must") + protected String bazRequired; + @Property(name = "theBaz") + protected String bazField; + + @Property + public void setFoo(String string) { + } + + @Property(override = "must") + public void setFooRequired(String string) { + } + + @Property(name = "bar") + public void setBarMethod(String string) { + } + + } + + private class Bar { + + @Property + protected String dup; + + @Property(name = "dup") + protected String baz; + + @Property + public void dupMethod(String s) { + } + + @Property(name = "dupMethod") + public void dupSomeMethod(String s) { + } + + @Property + public void badMethod() { + } + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ReferenceProcessorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ReferenceProcessorTestCase.java new file mode 100644 index 0000000000..e60cf58fb5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ReferenceProcessorTestCase.java @@ -0,0 +1,173 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.osoa.sca.annotations.Reference; + +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.model.ServiceContract; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; + +/** + * @version $Rev$ $Date$ + */ +public class ReferenceProcessorTestCase extends TestCase { + + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + ReferenceProcessor processor = + new ReferenceProcessor(new JavaInterfaceProcessorRegistryImpl()); + + public void testMethodAnnotation() throws Exception { + processor.visitMethod(null, ReferenceProcessorTestCase.Foo.class.getMethod("setFoo", Ref.class), type, null); + JavaMappedReference reference = type.getReferences().get("foo"); + assertNotNull(reference); + ServiceContract contract = reference.getServiceContract(); + assertEquals(Ref.class, contract.getInterfaceClass()); + assertEquals("ReferenceProcessorTestCase$Ref", contract.getInterfaceName()); + } + + public void testMethodRequired() throws Exception { + processor + .visitMethod(null, ReferenceProcessorTestCase.Foo.class.getMethod("setFooRequired", Ref.class), type, null); + JavaMappedReference prop = type.getReferences().get("fooRequired"); + assertNotNull(prop); + assertTrue(prop.isRequired()); + } + + public void testMethodName() throws Exception { + processor + .visitMethod(null, ReferenceProcessorTestCase.Foo.class.getMethod("setBarMethod", Ref.class), type, null); + assertNotNull(type.getReferences().get("bar")); + } + + public void testFieldAnnotation() throws Exception { + processor.visitField(null, ReferenceProcessorTestCase.Foo.class.getDeclaredField("baz"), type, null); + JavaMappedReference reference = type.getReferences().get("baz"); + assertNotNull(reference); + ServiceContract contract = reference.getServiceContract(); + assertEquals(Ref.class, contract.getInterfaceClass()); + assertEquals("ReferenceProcessorTestCase$Ref", contract.getInterfaceName()); + } + + public void testFieldRequired() throws Exception { + processor.visitField(null, ReferenceProcessorTestCase.Foo.class.getDeclaredField("bazRequired"), type, null); + JavaMappedReference prop = type.getReferences().get("bazRequired"); + assertNotNull(prop); + assertTrue(prop.isRequired()); + } + + public void testFieldName() throws Exception { + processor.visitField(null, ReferenceProcessorTestCase.Foo.class.getDeclaredField("bazField"), type, null); + assertNotNull(type.getReferences().get("theBaz")); + } + + public void testDuplicateFields() throws Exception { + processor.visitField(null, ReferenceProcessorTestCase.Bar.class.getDeclaredField("dup"), type, null); + try { + processor.visitField(null, ReferenceProcessorTestCase.Bar.class.getDeclaredField("baz"), type, null); + fail(); + } catch (DuplicateReferenceException e) { + //expected + } + } + + public void testDuplicateMethods() throws Exception { + processor.visitMethod(null, ReferenceProcessorTestCase.Bar.class.getMethod("dupMethod", Ref.class), type, null); + try { + processor + .visitMethod(null, ReferenceProcessorTestCase.Bar.class.getMethod("dupSomeMethod", Ref.class), type, + null); + fail(); + } catch (DuplicateReferenceException e) { + //expected + } + } + + public void testInvalidProperty() throws Exception { + try { + processor.visitMethod(null, ReferenceProcessorTestCase.Bar.class.getMethod("badMethod"), type, null); + fail(); + } catch (IllegalReferenceException e) { + //expected + } + } + + protected void setUp() throws Exception { + super.setUp(); + type = new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor = new ReferenceProcessor(new JavaInterfaceProcessorRegistryImpl()); + } + + private interface Ref { + } + + private class Foo { + + @Reference + protected Ref baz; + @Reference(required = true) + protected Ref bazRequired; + @Reference(name = "theBaz") + protected Ref bazField; + + + @Reference + public void setFoo(Ref ref) { + } + + @Reference(required = true) + public void setFooRequired(Ref ref) { + } + + @Reference(name = "bar") + public void setBarMethod(Ref ref) { + } + + } + + + private class Bar { + + @Reference + protected Ref dup; + + @Reference(name = "dup") + protected Ref baz; + + @Reference + public void dupMethod(Ref s) { + } + + @Reference(name = "dupMethod") + public void dupSomeMethod(Ref s) { + } + + @Reference + public void badMethod() { + } + + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ScopeProcessorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ScopeProcessorTestCase.java new file mode 100644 index 0000000000..09152c9009 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ScopeProcessorTestCase.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.model.Scope; + +import junit.framework.TestCase; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class ScopeProcessorTestCase extends TestCase { + + CompositeComponent parent; + + public void testModuleScope() throws ProcessingException { + ScopeProcessor processor = new ScopeProcessor(); + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + + processor.visitClass(parent, Module.class, type, null); + assertEquals(Scope.MODULE, type.getImplementationScope()); + } + + public void testSessionScope() throws ProcessingException { + ScopeProcessor processor = new ScopeProcessor(); + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitClass(parent, Session.class, type, null); + assertEquals(Scope.SESSION, type.getImplementationScope()); + } + + public void testRequestScope() throws ProcessingException { + ScopeProcessor processor = new ScopeProcessor(); + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitClass(parent, Request.class, type, null); + assertEquals(Scope.REQUEST, type.getImplementationScope()); + } + + public void testCompositeScope() throws ProcessingException { + ScopeProcessor processor = new ScopeProcessor(); + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitClass(parent, Composite.class, type, null); + assertEquals(Scope.COMPOSITE, type.getImplementationScope()); + } + + public void testStatelessScope() throws ProcessingException { + ScopeProcessor processor = new ScopeProcessor(); + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitClass(parent, Stateless.class, type, null); + assertEquals(Scope.STATELESS, type.getImplementationScope()); + } + + public void testNoScope() throws ProcessingException { + ScopeProcessor processor = new ScopeProcessor(); + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitClass(parent, None.class, type, null); + assertEquals(Scope.STATELESS, type.getImplementationScope()); + } + + protected void setUp() throws Exception { + super.setUp(); + parent = EasyMock.createNiceMock(CompositeComponent.class); + } + + @org.osoa.sca.annotations.Scope("MODULE") + private class Module { + } + + @org.osoa.sca.annotations.Scope("SESSION") + private class Session { + } + + @org.osoa.sca.annotations.Scope("REQUEST") + private class Request { + } + + @org.osoa.sca.annotations.Scope("COMPOSITE") + private class Composite { + } + + @org.osoa.sca.annotations.Scope("STATELESS") + private class Stateless { + } + + private class None { + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ServiceCallbackTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ServiceCallbackTestCase.java new file mode 100644 index 0000000000..e5b5698e23 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ServiceCallbackTestCase.java @@ -0,0 +1,166 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import org.osoa.sca.annotations.Callback; +import org.osoa.sca.annotations.Service; + +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.idl.java.IllegalCallbackException; + +/** + * @version $Rev$ $Date$ + */ +public class ServiceCallbackTestCase extends TestCase { + + ServiceProcessor processor = + new ServiceProcessor(new ImplementationProcessorServiceImpl(new JavaInterfaceProcessorRegistryImpl())); + + public void testMethodCallbackInterface() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitClass(null, FooImpl.class, type, null); + JavaMappedService service = type.getServices().get("ServiceCallbackTestCase$Foo"); + assertNotNull(service); + Method method = FooImpl.class.getMethod("setCallback", FooCallback.class); + processor.visitMethod(null, method, type, null); + assertEquals(method, service.getCallbackMember()); + } + + public void testFieldCallbackInterface() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitClass(null, FooImpl.class, type, null); + JavaMappedService service = type.getServices().get("ServiceCallbackTestCase$Foo"); + assertNotNull(service); + Field field = FooImpl.class.getDeclaredField("callback"); + processor.visitField(null, field, type, null); + assertEquals(field, service.getCallbackMember()); + } + + public void testMethodDoesNotMatchCallback() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitClass(null, BadBarImpl.class, type, null); + Method method = BadBarImpl.class.getMethod("setWrongInterfaceCallback", String.class); + try { + processor.visitMethod(null, method, type, null); + fail(); + } catch (IllegalCallbackReferenceException e) { + // expected + } + } + + public void testNoParamCallback() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitClass(null, BadBarImpl.class, type, null); + Method method = BadBarImpl.class.getMethod("setNoParamCallback"); + try { + processor.visitMethod(null, method, type, null); + fail(); + } catch (IllegalCallbackReferenceException e) { + // expected + } + } + + public void testFieldDoesNotMatchCallback() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + processor.visitClass(null, BadBarImpl.class, type, null); + Field field = BadBarImpl.class.getDeclaredField("wrongInterfaceCallback"); + try { + processor.visitField(null, field, type, null); + fail(); + } catch (IllegalCallbackReferenceException e) { + // expected + } + } + + public void testBadCallbackInterfaceAnnotation() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + try { + processor.visitClass(null, BadFooImpl.class, type, null); + fail(); + } catch (ProcessingException e) { + // expected + assertTrue(e.getCause() instanceof IllegalCallbackException); + } + } + + @Callback(FooCallback.class) + private interface Foo { + + } + + private interface FooCallback { + + } + + @Service(Foo.class) + private static class FooImpl implements Foo { + + @Callback + protected FooCallback callback; + + @Callback + public void setCallback(FooCallback cb) { + + } + } + + private static class BadBarImpl implements Foo { + @Callback + protected String wrongInterfaceCallback; + + @Callback + public void setWrongInterfaceCallback(String cb) { + + } + + @Callback + public void setNoParamCallback() { + + } + + } + + @Callback + private interface BadFoo { + + } + + @Service(BadFoo.class) + private static class BadFooImpl implements BadFoo { + + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ServiceProcessorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ServiceProcessorTestCase.java new file mode 100644 index 0000000000..f2a22fcb85 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/processor/ServiceProcessorTestCase.java @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.processor; + +import org.osoa.sca.annotations.Callback; +import org.osoa.sca.annotations.Remotable; +import org.osoa.sca.annotations.Service; + +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.model.ServiceContract; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; + +/** + * @version $Rev$ $Date$ + */ +public class ServiceProcessorTestCase extends TestCase { + + private ServiceProcessor processor; + private PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type; + + public void testMultipleInterfaces() throws Exception { + processor.visitClass(null, FooMultiple.class, type, null); + assertEquals(2, type.getServices().size()); + JavaMappedService service = type.getServices().get("ServiceProcessorTestCase$Baz"); + ServiceContract contract = service.getServiceContract(); + assertEquals(Baz.class, contract.getInterfaceClass()); + assertEquals(Bar.class, contract.getCallbackClass()); + assertEquals("ServiceProcessorTestCase$Bar", contract.getCallbackName()); + assertNotNull(type.getServices().get("ServiceProcessorTestCase$Bar")); + } + + public void testSingleInterfaces() throws Exception { + processor.visitClass(null, FooSingle.class, type, null); + assertEquals(1, type.getServices().size()); + assertNotNull(type.getServices().get("ServiceProcessorTestCase$Baz")); + } + + public void testMultipleNoService() throws Exception { + processor.visitClass(null, FooMultipleNoService.class, type, null); + assertEquals(0, type.getServices().size()); + } + + public void testRemotableNoService() throws Exception { + processor.visitClass(null, FooRemotableNoService.class, type, null); + assertEquals(1, type.getServices().size()); + JavaMappedService service = type.getServices().get("ServiceProcessorTestCase$BazRemotable"); + ServiceContract contract = service.getServiceContract(); + assertEquals(BazRemotable.class, contract.getInterfaceClass()); + } + + public void testNonInterface() throws Exception { + try { + processor.visitClass(null, BadImpl.class, type, null); + fail(); + } catch (InvalidServiceType e) { + //expected + } + } + + public void testNoInterfaces() throws Exception { + try { + processor.visitClass(null, BadDefinition.class, type, null); + fail(); + } catch (IllegalServiceDefinitionException e) { + //expected + } + } + + protected void setUp() throws Exception { + super.setUp(); + JavaInterfaceProcessorRegistryImpl registry = new JavaInterfaceProcessorRegistryImpl(); + processor = new ServiceProcessor(new ImplementationProcessorServiceImpl(registry)); + type = new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + } + + @Callback(Bar.class) + private interface Baz { + } + + private interface Bar { + } + + @Remotable + private interface BazRemotable { + } + + @Service(interfaces = {Baz.class, Bar.class}) + private class FooMultiple implements Baz, Bar { + + } + + @Service(Baz.class) + private class FooSingle implements Baz, Bar { + + } + + private class FooMultipleNoService implements Baz, Bar { + + } + + private class FooRemotableNoService implements BazRemotable, Bar { + + } + + @Service(FooSingle.class) + private class BadImpl extends FooSingle { + + } + + + @Service() + private class BadDefinition extends FooSingle { + + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/builder/SystemComponentBuilderTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/builder/SystemComponentBuilderTestCase.java new file mode 100644 index 0000000000..97d69f976e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/builder/SystemComponentBuilderTestCase.java @@ -0,0 +1,303 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.builder; + +import java.lang.reflect.Method; +import java.net.URI; + +import org.apache.tuscany.spi.annotation.Autowire; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.PropertyValue; +import org.apache.tuscany.spi.model.ReferenceTarget; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.OutboundWire; + +import junit.framework.TestCase; +import org.apache.tuscany.core.component.event.CompositeStart; +import org.apache.tuscany.core.component.event.CompositeStop; +import org.apache.tuscany.core.component.scope.ModuleScopeContainer; +import org.apache.tuscany.core.implementation.system.model.SystemImplementation; +import org.apache.tuscany.core.implementation.system.wire.SystemInboundWire; +import org.apache.tuscany.core.injection.SingletonObjectFactory; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class SystemComponentBuilderTestCase extends TestCase { + + CompositeComponent parent; + DeploymentContext deploymentContext; + SystemComponentBuilder builder = new SystemComponentBuilder(); + ModuleScopeContainer container; + + /** + * Verifies lifecycle callbacks are made + */ + public void testLifecycleBuild() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + type.setEagerInit(true); + Method initMethod = FooImpl.class.getMethod("init"); + initMethod.setAccessible(true); + type.setInitMethod(initMethod); + Method destroyMethod = FooImpl.class.getMethod("destroy"); + destroyMethod.setAccessible(true); + type.setDestroyMethod(destroyMethod); + type.setImplementationScope(Scope.MODULE); + ConstructorDefinition<FooImpl> ctorDef = new ConstructorDefinition<FooImpl>(FooImpl.class.getConstructor()); + type.setConstructorDefinition(ctorDef); + SystemImplementation impl = new SystemImplementation(); + impl.setComponentType(type); + impl.setImplementationClass(FooImpl.class); + ComponentDefinition<SystemImplementation> definition = new ComponentDefinition<SystemImplementation>(impl); + AtomicComponent component = builder.build(parent, definition, deploymentContext); + component.start(); + container.onEvent(new CompositeStart(this, null)); + FooImpl foo = (FooImpl) component.getServiceInstance(); + assertTrue(foo.initialized); + container.onEvent(new CompositeStop(this, null)); + assertTrue(foo.destroyed); + } + + /** + * Verifies properties are built properly + */ + public void testPropertyBuild() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + type.setEagerInit(true); + Method initMethod = FooImpl.class.getMethod("init"); + initMethod.setAccessible(true); + type.setInitMethod(initMethod); + Method destroyMethod = FooImpl.class.getMethod("destroy"); + destroyMethod.setAccessible(true); + type.setDestroyMethod(destroyMethod); + type.setImplementationScope(Scope.MODULE); + JavaMappedProperty mappedProp = new JavaMappedProperty(); + mappedProp.setName("prop"); + Method propMethod = FooImpl.class.getMethod("setProp", String.class); + propMethod.setAccessible(true); + mappedProp.setMember(propMethod); + type.add(mappedProp); + ConstructorDefinition<FooImpl> ctorDef = new ConstructorDefinition<FooImpl>(FooImpl.class.getConstructor()); + type.setConstructorDefinition(ctorDef); + SystemImplementation impl = new SystemImplementation(); + impl.setComponentType(type); + impl.setImplementationClass(FooImpl.class); + ComponentDefinition<SystemImplementation> definition = new ComponentDefinition<SystemImplementation>(impl); + PropertyValue<String> propVal = new PropertyValue<String>(); + propVal.setName("prop"); + propVal.setValueFactory(new SingletonObjectFactory<String>("value")); + definition.add(propVal); + AtomicComponent component = builder.build(parent, definition, deploymentContext); + component.start(); + FooImpl foo = (FooImpl) component.getServiceInstance(); + assertEquals("value", foo.prop); + container.onEvent(new CompositeStop(this, null)); + } + + /** + * Verifies references are built properly + */ + public void testRefBuild() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + type.setImplementationScope(Scope.MODULE); + JavaMappedReference mappedReference = new JavaMappedReference(); + mappedReference.setName("ref"); + Method refMethod = FooImpl.class.getMethod("setRef", Foo.class); + refMethod.setAccessible(true); + mappedReference.setMember(refMethod); + ServiceContract contract = new JavaServiceContract(Foo.class); + mappedReference.setServiceContract(contract); + type.add(mappedReference); + ConstructorDefinition<FooImpl> ctorDef = new ConstructorDefinition<FooImpl>(FooImpl.class.getConstructor()); + type.setConstructorDefinition(ctorDef); + SystemImplementation impl = new SystemImplementation(); + impl.setComponentType(type); + impl.setImplementationClass(FooImpl.class); + ComponentDefinition<SystemImplementation> definition = new ComponentDefinition<SystemImplementation>(impl); + ReferenceTarget target = new ReferenceTarget(); + target.setReferenceName("ref"); + target.addTarget(new URI("foo")); + definition.add(target); + AtomicComponent component = builder.build(parent, definition, deploymentContext); + OutboundWire wire = component.getOutboundWires().get("ref").get(0); + SystemInboundWire inbound = EasyMock.createMock(SystemInboundWire.class); + FooImpl targetFoo = new FooImpl(); + EasyMock.expect(inbound.getTargetService()).andReturn(targetFoo); + EasyMock.replay(inbound); + wire.setTargetWire(inbound); + component.start(); + FooImpl foo = (FooImpl) component.getServiceInstance(); + assertNotNull(foo.ref); + container.onEvent(new CompositeStop(this, null)); + EasyMock.verify(inbound); + } + + /** + * Verifies autowires are built properly + */ + public void testAutowireBuild() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + type.setImplementationScope(Scope.MODULE); + JavaMappedReference mappedReference = new JavaMappedReference(); + mappedReference.setName("ref"); + mappedReference.setAutowire(true); + Method refMethod = FooImpl.class.getMethod("setRef", Foo.class); + refMethod.setAccessible(true); + mappedReference.setMember(refMethod); + ServiceContract contract = new JavaServiceContract(Foo.class); + mappedReference.setServiceContract(contract); + type.add(mappedReference); + ConstructorDefinition<FooImpl> ctorDef = new ConstructorDefinition<FooImpl>(FooImpl.class.getConstructor()); + type.setConstructorDefinition(ctorDef); + SystemImplementation impl = new SystemImplementation(); + impl.setComponentType(type); + impl.setImplementationClass(FooImpl.class); + ComponentDefinition<SystemImplementation> definition = new ComponentDefinition<SystemImplementation>(impl); + CompositeComponent parent = EasyMock.createNiceMock(CompositeComponent.class); + FooImpl targetFoo = new FooImpl(); + EasyMock.expect(parent.resolveSystemInstance(EasyMock.eq(Foo.class))).andReturn(targetFoo); + EasyMock.replay(parent); + AtomicComponent component = builder.build(parent, definition, deploymentContext); + component.start(); + FooImpl foo = (FooImpl) component.getServiceInstance(); + assertNotNull(foo.ref); + container.onEvent(new CompositeStop(this, null)); + EasyMock.verify(parent); + } + + /** + * Verifies constructor-based autowiring + */ + public void testAutowireConstructorBuild() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + type.setImplementationScope(Scope.MODULE); + ConstructorDefinition<FooImpl2> ctorDef = + new ConstructorDefinition<FooImpl2>(FooImpl2.class.getConstructor(Foo.class)); + ctorDef.getInjectionNames().add("ref"); + type.setConstructorDefinition(ctorDef); + SystemImplementation impl = new SystemImplementation(); + impl.setComponentType(type); + impl.setImplementationClass(FooImpl2.class); + JavaMappedReference mappedReference = new JavaMappedReference(); + mappedReference.setName("ref"); + mappedReference.setAutowire(true); + ServiceContract contract = new JavaServiceContract(Foo.class); + mappedReference.setServiceContract(contract); + type.add(mappedReference); + ComponentDefinition<SystemImplementation> definition = new ComponentDefinition<SystemImplementation>(impl); + CompositeComponent parent = EasyMock.createNiceMock(CompositeComponent.class); + FooImpl targetFoo = new FooImpl(); + EasyMock.expect(parent.resolveSystemInstance(EasyMock.eq(Foo.class))).andReturn(targetFoo); + EasyMock.replay(parent); + AtomicComponent component = builder.build(parent, definition, deploymentContext); + component.start(); + container.onEvent(new CompositeStart(this, null)); + FooImpl2 foo = (FooImpl2) component.getServiceInstance(); + assertNotNull(foo.getRef()); + container.onEvent(new CompositeStop(this, null)); + EasyMock.verify(parent); + } + + protected void setUp() throws Exception { + super.setUp(); + parent = EasyMock.createNiceMock(CompositeComponent.class); + container = new ModuleScopeContainer(); + container.start(); + deploymentContext = EasyMock.createMock(DeploymentContext.class); + EasyMock.expect(deploymentContext.getModuleScope()).andReturn(container).atLeastOnce(); + EasyMock.replay(deploymentContext); + } + + private static interface Foo { + + } + + private static class FooImpl implements Foo { + private boolean initialized; + private boolean destroyed; + private String prop; + private Foo ref; + + public FooImpl() { + } + + public void init() { + if (initialized) { + fail(); + } + initialized = true; + } + + public void destroy() { + if (destroyed) { + fail(); + } + destroyed = true; + } + + public boolean isInitialized() { + return initialized; + } + + public String getProp() { + return prop; + } + + public void setProp(String prop) { + this.prop = prop; + } + + public Foo getRef() { + return ref; + } + + public void setRef(Foo ref) { + this.ref = ref; + } + } + + private static class FooImpl2 implements Foo { + private Foo ref; + + public FooImpl2(@Autowire Foo ref) { + this.ref = ref; + } + + public Foo getRef() { + return ref; + } + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/component/SystemAtomicComponentTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/component/SystemAtomicComponentTestCase.java new file mode 100644 index 0000000000..29c37ba47a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/component/SystemAtomicComponentTestCase.java @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.component; + +import junit.framework.TestCase; +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.core.implementation.system.wire.SystemOutboundWire; +import org.apache.tuscany.core.injection.EventInvoker; +import org.apache.tuscany.core.injection.MethodEventInvoker; +import org.apache.tuscany.core.injection.PojoObjectFactory; +import org.apache.tuscany.core.injection.SingletonObjectFactory; +import org.easymock.EasyMock; + +/** + * Verifies a system atomic component can be started and initialized + * + * @version $$Rev$$ $$Date$$ + */ +public class SystemAtomicComponentTestCase extends TestCase { + + private EventInvoker<Object> initInvoker; + + public void testDefaultCreationAndInit() throws Exception { + PojoObjectFactory<Foo> factory = new PojoObjectFactory<Foo>(Foo.class.getConstructor((Class[]) null)); + PojoConfiguration configuration = new PojoConfiguration(); + configuration.addServiceInterface(Foo.class); + configuration.setInstanceFactory(factory); + configuration.setInitInvoker(initInvoker); + SystemAtomicComponentImpl component = new SystemAtomicComponentImpl("foo", configuration); + Foo foo = (Foo) component.createInstance(); + component.init(foo); + assertTrue(foo.initialized); + } + + public void testReferenceAndPropertyConstructor() throws Exception { + PojoObjectFactory<Bar> factory = new PojoObjectFactory<Bar>(Bar.class.getConstructor(String.class, Foo.class)); + PojoConfiguration configuration = new PojoConfiguration(); + configuration.addServiceInterface(Foo.class); + configuration.setInstanceFactory(factory); + configuration.setInitInvoker(initInvoker); + configuration.addConstructorParamName("foo"); + configuration.addConstructorParamName("ref"); + SystemAtomicComponentImpl component = new SystemAtomicComponentImpl("foo", configuration); + component.addPropertyFactory("foo", new SingletonObjectFactory<String>("baz")); + Foo target = new Foo(); + SystemOutboundWire wire = EasyMock.createMock(SystemOutboundWire.class); + EasyMock.expect(wire.getTargetService()).andReturn(target); + EasyMock.expect(wire.getReferenceName()).andReturn("ref").anyTimes(); + EasyMock.replay(wire); + component.addOutboundWire(wire); + Bar bar = (Bar) component.createInstance(); + assertEquals("baz", bar.foo); + assertEquals(target, bar.ref); + EasyMock.verify(wire); + } + + protected void setUp() throws Exception { + super.setUp(); + initInvoker = new MethodEventInvoker<Object>(Foo.class.getMethod("init")); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + public static class Foo { + + private boolean initialized; + + public void init() { + initialized = true; + } + } + + public static class Bar { + + private String foo; + private Foo ref; + + public Bar(String foo, Foo ref) { + this.foo = foo; + this.ref = ref; + } + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/loader/SystemComponentTypeLoaderTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/loader/SystemComponentTypeLoaderTestCase.java new file mode 100644 index 0000000000..e4eec8cae2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/loader/SystemComponentTypeLoaderTestCase.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.core.implementation.system.loader; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ProcessingException; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.model.ReferenceDefinition; +import org.apache.tuscany.spi.model.ServiceDefinition; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.implementation.IntrospectionRegistryImpl; +import org.apache.tuscany.core.implementation.processor.ConstructorProcessor; +import org.apache.tuscany.core.implementation.processor.DestroyProcessor; +import org.apache.tuscany.core.implementation.processor.HeuristicPojoProcessor; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService; +import org.apache.tuscany.core.implementation.processor.ImplementationProcessorServiceImpl; +import org.apache.tuscany.core.implementation.processor.InitProcessor; +import org.apache.tuscany.core.implementation.processor.PropertyProcessor; +import org.apache.tuscany.core.implementation.processor.ReferenceProcessor; +import org.apache.tuscany.core.implementation.processor.ScopeProcessor; +import org.apache.tuscany.core.implementation.processor.ServiceProcessor; +import org.apache.tuscany.core.implementation.system.model.SystemImplementation; +import org.apache.tuscany.core.mock.component.BasicInterface; +import org.apache.tuscany.core.mock.component.BasicInterfaceImpl; +import org.apache.tuscany.core.monitor.NullMonitorFactory; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class SystemComponentTypeLoaderTestCase extends TestCase { + private SystemComponentTypeLoader loader; + + public void testIntrospectUnannotatedClass() throws ProcessingException { + CompositeComponent parent = EasyMock.createNiceMock(CompositeComponent.class); + SystemImplementation impl = new SystemImplementation(BasicInterfaceImpl.class); + PojoComponentType<?, ?, ?> componentType = loader.loadByIntrospection(parent, impl, null); + ServiceDefinition service = componentType.getServices().get("BasicInterface"); + assertEquals(BasicInterface.class, service.getServiceContract().getInterfaceClass()); + Property<?> property = componentType.getProperties().get("publicProperty"); + assertEquals(String.class, property.getJavaType()); + ReferenceDefinition referenceDefinition = componentType.getReferences().get("protectedReference"); + assertEquals(BasicInterface.class, referenceDefinition.getServiceContract().getInterfaceClass()); + } + + protected void setUp() throws Exception { + super.setUp(); + JavaInterfaceProcessorRegistryImpl interfaceProcessorRegistry = new JavaInterfaceProcessorRegistryImpl(); + ImplementationProcessorService service = + new ImplementationProcessorServiceImpl(interfaceProcessorRegistry); + IntrospectionRegistryImpl registry = new IntrospectionRegistryImpl(); + registry.setMonitor(new NullMonitorFactory().getMonitor(IntrospectionRegistryImpl.Monitor.class)); + registry.registerProcessor(new ConstructorProcessor(service)); + registry.registerProcessor(new DestroyProcessor()); + registry.registerProcessor(new InitProcessor()); + registry.registerProcessor(new ScopeProcessor()); + registry.registerProcessor(new PropertyProcessor(service)); + registry.registerProcessor(new ReferenceProcessor(interfaceProcessorRegistry)); + registry.registerProcessor(new ServiceProcessor(service)); + registry.registerProcessor(new HeuristicPojoProcessor(service)); + loader = new SystemComponentTypeLoader(registry); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/wire/AtomicComponentWireInvocationTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/wire/AtomicComponentWireInvocationTestCase.java new file mode 100644 index 0000000000..017274e455 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/wire/AtomicComponentWireInvocationTestCase.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.core.implementation.system.wire; + +import org.apache.tuscany.spi.QualifiedName; +import org.apache.tuscany.spi.component.SystemAtomicComponent; +import org.apache.tuscany.spi.wire.OutboundWire; + +import junit.framework.TestCase; +import org.apache.tuscany.core.component.scope.ModuleScopeContainer; +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.core.implementation.system.component.SystemAtomicComponentImpl; +import org.apache.tuscany.core.injection.PojoObjectFactory; +import org.apache.tuscany.core.mock.component.Source; +import org.apache.tuscany.core.mock.component.SourceImpl; +import org.apache.tuscany.core.mock.component.Target; +import org.apache.tuscany.core.mock.component.TargetImpl; +import org.easymock.EasyMock; + +/** + * Tests wiring from an system atomic context + * + * @version $$Rev$$ $$Date$$ + */ +public class AtomicComponentWireInvocationTestCase extends TestCase { + + public void testWireResolution() throws NoSuchMethodException { + ModuleScopeContainer scope = new ModuleScopeContainer(null); + scope.start(); + Target target = new TargetImpl(); + SystemInboundWire inboundWire = EasyMock.createMock(SystemInboundWire.class); + EasyMock.expect(inboundWire.getTargetService()).andReturn(target); + EasyMock.replay(inboundWire); + + PojoConfiguration configuration = new PojoConfiguration(); + configuration.setScopeContainer(scope); + configuration.addReferenceSite("setTarget", SourceImpl.class.getMethod("setTarget", Target.class)); + configuration.addServiceInterface(Source.class); + configuration.setInstanceFactory(new PojoObjectFactory<SourceImpl>(SourceImpl.class.getConstructor())); + SystemAtomicComponent sourceContext = new SystemAtomicComponentImpl("source", configuration); + QualifiedName qName = new QualifiedName("service"); + OutboundWire outboundWire = new SystemOutboundWireImpl("setTarget", qName, Target.class); + outboundWire.setTargetWire(inboundWire); + sourceContext.addOutboundWire(outboundWire); + sourceContext.start(); + assertSame(((Source) sourceContext.getServiceInstance()).getTarget(), target); + // wires should pass back direct ref + EasyMock.verify(inboundWire); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/wire/SystemInboundtoOutboundTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/wire/SystemInboundtoOutboundTestCase.java new file mode 100644 index 0000000000..ed89fb6aae --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/wire/SystemInboundtoOutboundTestCase.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.core.implementation.system.wire; + +import junit.framework.TestCase; +import org.apache.tuscany.core.mock.component.Target; +import org.apache.tuscany.core.mock.component.TargetImpl; +import org.easymock.EasyMock; + +/** + * Tests connecting an inbound system wire to an outbound system wire + * + * @version $$Rev$$ $$Date$$ + */ +public class SystemInboundtoOutboundTestCase extends TestCase { + + public void testWire() throws NoSuchMethodException { + Target target = new TargetImpl(); + SystemOutboundWire outboundWire = EasyMock.createMock(SystemOutboundWire.class); + EasyMock.expect(outboundWire.getTargetService()).andReturn(target); + EasyMock.replay(outboundWire); + SystemInboundWire inboundWire = new SystemInboundWireImpl("service", Target.class); + inboundWire.setTargetWire(outboundWire); + assertSame(inboundWire.getTargetService(), target); + EasyMock.verify(outboundWire); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/wire/SystemOutboundAutowireTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/wire/SystemOutboundAutowireTestCase.java new file mode 100644 index 0000000000..8c00af6e9e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/wire/SystemOutboundAutowireTestCase.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.implementation.system.wire; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.TargetNotFoundException; + +import junit.framework.TestCase; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * @version $Rev$ $Date$ + */ +public class SystemOutboundAutowireTestCase extends TestCase { + + public void testAutowire() { + CompositeComponent component = createMock(CompositeComponent.class); + expect(component.resolveSystemInstance(Object.class)).andReturn(new Object()); + replay(component); + SystemOutboundAutowire wire = new SystemOutboundAutowire("foo", Object.class, component, false); + assertNotNull(wire.getTargetService()); + verify(component); + } + + + public void testNonExistentAutowire() { + CompositeComponent component = createMock(CompositeComponent.class); + expect(component.resolveSystemInstance(Object.class)).andReturn(null); + replay(component); + SystemOutboundAutowire wire = new SystemOutboundAutowire("foo", Object.class, component, true); + try { + wire.getTargetService(); + fail(); + } catch (TargetNotFoundException e) { + // expected + } + verify(component); + } + + + public void testNonExistentAutowireNotRequired() { + CompositeComponent component = createMock(CompositeComponent.class); + expect(component.resolveSystemInstance(Object.class)).andReturn(null); + replay(component); + SystemOutboundAutowire wire = new SystemOutboundAutowire("foo", Object.class, component, false); + try { + assertNull(wire.getTargetService()); + } catch (TargetNotFoundException e) { + fail(); + } + verify(component); + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/wire/SystemOutboundToInboundTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/wire/SystemOutboundToInboundTestCase.java new file mode 100644 index 0000000000..8f41a33c12 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/wire/SystemOutboundToInboundTestCase.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.core.implementation.system.wire; + +import org.apache.tuscany.spi.QualifiedName; + +import junit.framework.TestCase; +import org.apache.tuscany.core.mock.component.Target; +import org.apache.tuscany.core.mock.component.TargetImpl; +import org.easymock.EasyMock; + +/** + * Tests connecting an outbound system wire to an inbound system wire + * + * @version $$Rev$$ $$Date$$ + */ +public class SystemOutboundToInboundTestCase extends TestCase { + + public void testWire() throws NoSuchMethodException { + Target target = new TargetImpl(); + SystemInboundWire inboundWire = EasyMock.createMock(SystemInboundWire.class); + EasyMock.expect(inboundWire.getTargetService()).andReturn(target); + EasyMock.replay(inboundWire); + QualifiedName qName = new QualifiedName("service"); + SystemOutboundWire outboundWire = new SystemOutboundWireImpl("setTarget", qName, Target.class); + outboundWire.setTargetWire(inboundWire); + assertSame(outboundWire.getTargetService(), target); + EasyMock.verify(inboundWire); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/wire/SystemServiceComponentWireTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/wire/SystemServiceComponentWireTestCase.java new file mode 100644 index 0000000000..222b02f6a1 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/implementation/system/wire/SystemServiceComponentWireTestCase.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.core.implementation.system.wire; + +import junit.framework.TestCase; +import org.apache.tuscany.core.implementation.system.component.SystemService; +import org.apache.tuscany.core.implementation.system.component.SystemServiceImpl; +import org.apache.tuscany.core.mock.component.Target; +import org.apache.tuscany.core.mock.component.TargetImpl; +import org.easymock.EasyMock; + +/** + * Verifies that a system context interacts correctly with configured, connected inbound and outbound system wires + * + * @version $$Rev$$ $$Date$$ + */ +public class SystemServiceComponentWireTestCase extends TestCase { + + public void testServiceContext() throws NoSuchMethodException { + Target target = new TargetImpl(); + SystemOutboundWire outboundWire = EasyMock.createMock(SystemOutboundWire.class); + EasyMock.expect(outboundWire.getTargetService()).andReturn(target); + EasyMock.replay(outboundWire); + SystemInboundWire wire = new SystemInboundWireImpl("Target", Target.class); + SystemService serviceContext = new SystemServiceImpl("service", null); + serviceContext.setInboundWire(wire); + serviceContext.setOutboundWire(outboundWire); + wire.setTargetWire(outboundWire); + assertSame(target, serviceContext.getServiceInstance()); + EasyMock.verify(outboundWire); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/CallbackWireObjectFactoryTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/CallbackWireObjectFactoryTestCase.java new file mode 100644 index 0000000000..8c3aea9dd3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/CallbackWireObjectFactoryTestCase.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.core.injection; + +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.wire.WireService; + +import junit.framework.TestCase; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * @version $Rev$ $Date$ + */ +public class CallbackWireObjectFactoryTestCase extends TestCase { + + public void testCreateInstance() throws Exception { + JavaServiceContract contract = new JavaServiceContract(); + contract.setCallbackClass(Foo.class); + WireService service = createMock(WireService.class); + service.createCallbackProxy(contract, null); + expectLastCall().andReturn(null); + replay(service); + CallbackWireObjectFactory factory = new CallbackWireObjectFactory(contract, service, null); + factory.getInstance(); + verify(service); + } + + private interface Foo { + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/FieldInjectorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/FieldInjectorTestCase.java new file mode 100644 index 0000000000..d31347f7e6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/FieldInjectorTestCase.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.core.injection; + +import java.lang.reflect.Field; + +import junit.framework.TestCase; + +/** + * @version $Rev$ $Date$ + */ +public class FieldInjectorTestCase extends TestCase { + + protected Field protectedField; + + 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); + } + + + protected void setUp() throws Exception { + super.setUp(); + protectedField = Foo.class.getDeclaredField("hidden"); + } + + private class Foo { + private String hidden; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/JNDIObjectFactoryTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/JNDIObjectFactoryTestCase.java new file mode 100644 index 0000000000..91214fd02d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/JNDIObjectFactoryTestCase.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import javax.naming.Context; +import javax.naming.NamingException; + +import org.apache.tuscany.spi.ObjectCreationException; + +import junit.framework.TestCase; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class JNDIObjectFactoryTestCase extends TestCase { + + public void testGetInstance() throws Exception { + Context ctx = EasyMock.createMock(Context.class); + EasyMock.expect(ctx.lookup(EasyMock.eq("foo"))).andReturn(new Foo()); + EasyMock.replay(ctx); + JNDIObjectFactory<Foo> factory = new JNDIObjectFactory<Foo>(ctx, "foo"); + assertTrue(factory.getInstance() instanceof Foo); // must do an instanceof b/c of type erasure + EasyMock.verify(ctx); + } + + public void testGetInstanceError() throws Exception { + Context ctx = EasyMock.createMock(Context.class); + EasyMock.expect(ctx.lookup(EasyMock.eq("foo"))).andThrow(new NamingException()); + EasyMock.replay(ctx); + JNDIObjectFactory<Foo> factory = new JNDIObjectFactory<Foo>(ctx, "foo"); + try { + factory.getInstance(); + fail(); + } catch (ObjectCreationException e) { + //expected + } + EasyMock.verify(ctx); + } + + + private class Foo { + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/MethodEventInvokerTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/MethodEventInvokerTestCase.java new file mode 100644 index 0000000000..3bb882da2d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/MethodEventInvokerTestCase.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.core.injection; + +import java.lang.reflect.Method; + +import junit.framework.TestCase; + +/** + * @version $Rev$ $Date$ + */ +public class MethodEventInvokerTestCase extends TestCase { + private Method privateMethod; + private Method exceptionMethod; + + public void testIllegalAccess() throws Exception { + MethodEventInvoker<MethodEventInvokerTestCase.Foo> injector = new MethodEventInvoker<Foo>(privateMethod); + try { + injector.invokeEvent(new Foo()); + fail(); + } catch (AssertionError e) { + // expected + } + } + + public void testException() throws Exception { + MethodEventInvoker<MethodEventInvokerTestCase.Foo> injector = new MethodEventInvoker<Foo>(exceptionMethod); + try { + injector.invokeEvent(new Foo()); + fail(); + } catch (RuntimeException e) { + // expected + } + } + + protected void setUp() throws Exception { + super.setUp(); + privateMethod = MethodEventInvokerTestCase.Foo.class.getDeclaredMethod("hidden"); + exceptionMethod = MethodEventInvokerTestCase.Foo.class.getDeclaredMethod("exception"); + + } + + private class Foo { + + public void foo() { + } + + private void hidden() { + } + + public void exception() { + throw new RuntimeException(); + } + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/MethodInjectorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/MethodInjectorTestCase.java new file mode 100644 index 0000000000..b21ba4ccfa --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/MethodInjectorTestCase.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.core.injection; + +import java.lang.reflect.Method; + +import org.apache.tuscany.spi.ObjectCreationException; +import org.apache.tuscany.spi.ObjectFactory; + +import junit.framework.TestCase; + +/** + * @version $Rev$ $Date$ + */ +public class MethodInjectorTestCase extends TestCase { + private Method fooMethod; + private Method privateMethod; + private Method exceptionMethod; + + 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 + } + } + + 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 + } + } + + protected void setUp() throws Exception { + super.setUp(); + 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-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/PojoObjectFactoryTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/PojoObjectFactoryTestCase.java new file mode 100644 index 0000000000..7aba6dbab3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/PojoObjectFactoryTestCase.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.injection; + +import java.lang.reflect.Constructor; +import java.util.List; +import java.util.ArrayList; + +import org.apache.tuscany.spi.ObjectFactory; + +import junit.framework.TestCase; + +/** + * @version $Rev$ $Date$ + */ +public class PojoObjectFactoryTestCase extends TestCase { + + private Constructor<Foo> ctor; + + public void testConstructorInjection() throws Exception { + List<ObjectFactory> initializers = new ArrayList<ObjectFactory>(); + initializers.add(new SingletonObjectFactory<String>("foo")); + PojoObjectFactory<Foo> factory = new PojoObjectFactory<Foo>(ctor, initializers); + Foo foo = factory.getInstance(); + assertEquals("foo", foo.foo); + } + + public void testConstructorInitializerInjection() throws Exception { + PojoObjectFactory<Foo> factory = new PojoObjectFactory<Foo>(ctor); + factory.setInitializerFactory(0, new SingletonObjectFactory<String>("foo")); + Foo foo = factory.getInstance(); + assertEquals("foo", foo.foo); + } + + protected void setUp() throws Exception { + super.setUp(); + 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-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/SingletonObjectFactoryTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/SingletonObjectFactoryTestCase.java new file mode 100644 index 0000000000..876e68d5b3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/SingletonObjectFactoryTestCase.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.core.injection; + +import junit.framework.TestCase; + +/** + * @version $Rev$ $Date$ + */ +public class SingletonObjectFactoryTestCase extends TestCase { + + 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-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/WireObjectFactoryTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/WireObjectFactoryTestCase.java new file mode 100644 index 0000000000..e6e531dba7 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/injection/WireObjectFactoryTestCase.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.core.injection; + +import org.apache.tuscany.spi.wire.RuntimeWire; +import org.apache.tuscany.spi.wire.WireService; + +import junit.framework.TestCase; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * @version $Rev$ $Date$ + */ +public class WireObjectFactoryTestCase extends TestCase { + + public void testCreateInstance() throws Exception { + RuntimeWire wire = createMock(RuntimeWire.class); + WireService service = createMock(WireService.class); + service.createProxy(wire); + expectLastCall().andReturn(null); + replay(service); + WireObjectFactory factory = new WireObjectFactory(wire, service); + factory.getInstance(); + verify(service); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/integration/implementation/IntrospectionRegistryIntegrationTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/integration/implementation/IntrospectionRegistryIntegrationTestCase.java new file mode 100644 index 0000000000..a9b1353cdd --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/integration/implementation/IntrospectionRegistryIntegrationTestCase.java @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.integration.implementation; + +import org.osoa.sca.annotations.Destroy; +import org.osoa.sca.annotations.Init; +import org.osoa.sca.annotations.Property; +import org.osoa.sca.annotations.Reference; +import org.osoa.sca.annotations.Scope; + +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.implementation.java.ImplementationProcessorService; +import static org.apache.tuscany.spi.model.Scope.MODULE; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.implementation.IntrospectionRegistryImpl; +import org.apache.tuscany.core.implementation.processor.DestroyProcessor; +import org.apache.tuscany.core.implementation.processor.ImplementationProcessorServiceImpl; +import org.apache.tuscany.core.implementation.processor.InitProcessor; +import org.apache.tuscany.core.implementation.processor.PropertyProcessor; +import org.apache.tuscany.core.implementation.processor.ReferenceProcessor; +import org.apache.tuscany.core.implementation.processor.ScopeProcessor; +import org.apache.tuscany.core.monitor.NullMonitorFactory; + +/** + * Sanity check of the <code>IntegrationRegistry</code> to verify operation with processors + * + * @version $Rev$ $Date$ + */ +public class IntrospectionRegistryIntegrationTestCase extends TestCase { + + private IntrospectionRegistryImpl registry; + + public void testSimpleComponentTypeParsing() throws Exception { + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> type = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + registry.introspect(null, Foo.class, type, null); + assertEquals(Foo.class.getMethod("init"), type.getInitMethod()); + assertEquals(Foo.class.getMethod("destroy"), type.getDestroyMethod()); + assertEquals(MODULE, type.getImplementationScope()); + assertEquals(Foo.class.getMethod("setBar", String.class), type.getProperties().get("bar").getMember()); + assertEquals(Foo.class.getMethod("setTarget", Foo.class), type.getReferences().get("target").getMember()); + } + + protected void setUp() throws Exception { + super.setUp(); + registry = new IntrospectionRegistryImpl(); + registry.setMonitor(new NullMonitorFactory().getMonitor(IntrospectionRegistryImpl.Monitor.class)); + registry.registerProcessor(new DestroyProcessor()); + registry.registerProcessor(new InitProcessor()); + registry.registerProcessor(new ScopeProcessor()); + JavaInterfaceProcessorRegistryImpl interfaceProcessorRegistry = new JavaInterfaceProcessorRegistryImpl(); + ImplementationProcessorService service = new ImplementationProcessorServiceImpl(interfaceProcessorRegistry); + registry.registerProcessor(new PropertyProcessor(service)); + registry.registerProcessor(new ReferenceProcessor(interfaceProcessorRegistry)); + } + + @Scope("MODULE") + private static class Foo { + protected Foo target; + protected String bar; + + private boolean initialized; + private boolean destroyed; + + + @Init + public void init() { + if (initialized) { + fail(); + } + initialized = true; + } + + @Destroy + public void destroy() { + if (destroyed) { + fail(); + } + destroyed = true; + } + + public Foo getTarget() { + return target; + } + + @Reference + public void setTarget(Foo target) { + this.target = target; + } + + public String getBar() { + return bar; + } + + @Property + public void setBar(String bar) { + this.bar = bar; + } + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/integration/implementation/java/builder/JavaBuilderPropertyTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/integration/implementation/java/builder/JavaBuilderPropertyTestCase.java new file mode 100644 index 0000000000..a173dda98e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/integration/implementation/java/builder/JavaBuilderPropertyTestCase.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.integration.implementation.java.builder; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.ScopeRegistry; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.PropertyValue; +import org.apache.tuscany.spi.model.ReferenceDefinition; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.model.ServiceDefinition; + +import junit.framework.TestCase; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.component.scope.ScopeRegistryImpl; +import org.apache.tuscany.core.component.scope.StatelessScopeObjectFactory; +import org.apache.tuscany.core.deployer.RootDeploymentContext; +import org.apache.tuscany.core.implementation.java.JavaComponentBuilder; +import org.apache.tuscany.core.implementation.java.JavaImplementation; +import org.apache.tuscany.core.injection.SingletonObjectFactory; +import org.easymock.EasyMock; + +/** + * Verifies that the system builder handles configured properties correctly + * + * @version $Rev$ $Date$ + */ +public class JavaBuilderPropertyTestCase extends TestCase { + + private DeploymentContext deploymentContext; + private CompositeComponent parent; + private ScopeRegistry registry; + + public void testPropertyHandling() throws Exception { + JavaComponentBuilder builder = new JavaComponentBuilder(); + builder.setScopeRegistry(registry); + PojoComponentType<ServiceDefinition, ReferenceDefinition, JavaMappedProperty<?>> type = + new PojoComponentType<ServiceDefinition, ReferenceDefinition, JavaMappedProperty<?>>(); + JavaMappedProperty<String> property = new JavaMappedProperty<String>(); + property.setName("test"); + property.setDefaultValueFactory(new SingletonObjectFactory<String>("foo")); + property.setMember(JavaBuilderPropertyTestCase.Foo.class.getMethod("setTest", String.class)); + type.add(property); + type.setConstructorDefinition(new ConstructorDefinition<Foo>(Foo.class.getConstructor((Class[]) null))); + type.setImplementationScope(Scope.STATELESS); + JavaImplementation impl = new JavaImplementation(); + impl.setComponentType(type); + impl.setImplementationClass(Foo.class); + ComponentDefinition<JavaImplementation> definition = new ComponentDefinition<JavaImplementation>(impl); + PropertyValue propertyValue = new PropertyValue(property.getName(), property.getDefaultValueFactory()); + definition.getPropertyValues().put(property.getName(), propertyValue); + AtomicComponent component = builder.build(parent, definition, deploymentContext); + JavaBuilderPropertyTestCase.Foo foo = (JavaBuilderPropertyTestCase.Foo) component.createInstance(); + assertEquals("foo", foo.getTest()); + } + + protected void setUp() throws Exception { + super.setUp(); + deploymentContext = new RootDeploymentContext(null, null, null, null); + parent = EasyMock.createNiceMock(CompositeComponent.class); + registry = new ScopeRegistryImpl(new WorkContextImpl()); + new StatelessScopeObjectFactory(registry); + } + + private static class Foo { + private String test; + + public Foo() { + } + + public String getTest() { + return test; + } + + public void setTest(String test) { + this.test = test; + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/integration/implementation/system/builder/SystemBuilderPropertyTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/integration/implementation/system/builder/SystemBuilderPropertyTestCase.java new file mode 100644 index 0000000000..a7d580bbcb --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/integration/implementation/system/builder/SystemBuilderPropertyTestCase.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.integration.implementation.system.builder; + +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.ReferenceDefinition; +import org.apache.tuscany.spi.model.ServiceDefinition; + +import junit.framework.TestCase; +import org.apache.tuscany.core.deployer.RootDeploymentContext; +import org.apache.tuscany.core.implementation.system.builder.SystemComponentBuilder; +import org.apache.tuscany.core.implementation.system.model.SystemImplementation; +import org.apache.tuscany.core.injection.SingletonObjectFactory; +import org.easymock.EasyMock; + +/** + * Verifies that the system builder handles configured properties correctly + * + * @version $Rev$ $Date$ + */ +public class SystemBuilderPropertyTestCase extends TestCase { + + DeploymentContext deploymentContext; + CompositeComponent parent; + + @SuppressWarnings("unchecked") + public void testPropertyHandling() throws Exception { + SystemComponentBuilder builder = new SystemComponentBuilder(); + PojoComponentType<ServiceDefinition, ReferenceDefinition, JavaMappedProperty<?>> type = + new PojoComponentType<ServiceDefinition, ReferenceDefinition, JavaMappedProperty<?>>(); + type.setConstructorDefinition(new ConstructorDefinition<Foo>(Foo.class.getConstructor((Class[]) null))); + JavaMappedProperty<String> property = new JavaMappedProperty<String>(); + property.setName("test"); + property.setDefaultValueFactory(new SingletonObjectFactory<String>("foo")); + property.setMember(Foo.class.getMethod("setTest", String.class)); + type.add(property); + SystemImplementation impl = new SystemImplementation(); + impl.setComponentType(type); + impl.setImplementationClass(Foo.class); + ComponentDefinition<SystemImplementation> definition = new ComponentDefinition<SystemImplementation>(impl); + AtomicComponent component = builder.build(parent, definition, deploymentContext); + Foo foo = (Foo) component.createInstance(); + assertEquals("foo", foo.getTest()); + } + + protected void setUp() throws Exception { + super.setUp(); + deploymentContext = new RootDeploymentContext(null, null, null, null); + parent = EasyMock.createNiceMock(CompositeComponent.class); + } + + private static class Foo { + private String test; + + public Foo() { + } + + public String getTest() { + return test; + } + + public void setTest(String test) { + this.test = test; + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/integration/implementation/system/builder/SystemBuilderWireTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/integration/implementation/system/builder/SystemBuilderWireTestCase.java new file mode 100644 index 0000000000..761d2bb650 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/integration/implementation/system/builder/SystemBuilderWireTestCase.java @@ -0,0 +1,183 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.integration.implementation.system.builder; + +import org.apache.tuscany.spi.builder.Connector; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.component.Reference; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.component.Service; +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.model.BoundReferenceDefinition; +import org.apache.tuscany.spi.model.BoundServiceDefinition; +import org.apache.tuscany.spi.model.ComponentDefinition; + +import junit.framework.TestCase; +import org.apache.tuscany.core.builder.ConnectorImpl; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.component.event.CompositeStart; +import org.apache.tuscany.core.component.event.CompositeStop; +import org.apache.tuscany.core.component.scope.ModuleScopeContainer; +import org.apache.tuscany.core.deployer.RootDeploymentContext; +import org.apache.tuscany.core.implementation.composite.CompositeComponentImpl; +import org.apache.tuscany.core.implementation.system.builder.SystemBindingBuilder; +import org.apache.tuscany.core.implementation.system.builder.SystemComponentBuilder; +import org.apache.tuscany.core.implementation.system.model.SystemBinding; +import org.apache.tuscany.core.implementation.system.model.SystemImplementation; +import org.apache.tuscany.core.mock.component.Source; +import org.apache.tuscany.core.mock.component.Target; +import org.apache.tuscany.core.mock.factories.MockComponentFactory; + +/** + * Validates that system builders and the default connector create properly wired contexts + * + * @version $$Rev$$ $$Date$$ + */ +public class SystemBuilderWireTestCase extends TestCase { + private DeploymentContext deploymentContext; + + /** + * Validates building a wire from an atomic context to an atomic context + */ + public void testAtomicWireBuild() throws Exception { + WorkContext work = new WorkContextImpl(); + ScopeContainer scope = new ModuleScopeContainer(work); + scope.start(); + + Connector connector = new ConnectorImpl(); + SystemComponentBuilder builder = new SystemComponentBuilder(); + + CompositeComponent parent = new CompositeComponentImpl(null, null, connector, null); + + ComponentDefinition<SystemImplementation> targetComponentDefinition = MockComponentFactory.createTarget(); + ComponentDefinition<SystemImplementation> sourceComponentDefinition = + MockComponentFactory.createSourceWithTargetReference(); + + AtomicComponent sourceComponent = builder.build(parent, sourceComponentDefinition, deploymentContext); + AtomicComponent targetComponent = builder.build(parent, targetComponentDefinition, deploymentContext); + + parent.register(sourceComponent); + parent.register(targetComponent); + parent.prepare(); + parent.start(); + scope.onEvent(new CompositeStart(this, parent)); + Source source = (Source) parent.getSystemChild("source").getServiceInstance(); + assertNotNull(source); + Target target = (Target) parent.getSystemChild("target").getServiceInstance(); + assertNotNull(target); + assertSame(target, source.getTarget()); + scope.onEvent(new CompositeStop(this, parent)); + parent.stop(); + scope.stop(); + } + + /** + * Validates building a wire from an atomic context to a reference context + */ + public void testAtomicToReferenceWireBuild() throws Exception { + WorkContext work = new WorkContextImpl(); + ScopeContainer scope = new ModuleScopeContainer(work); + scope.start(); + + Connector connector = new ConnectorImpl(); + SystemComponentBuilder builder = new SystemComponentBuilder(); + SystemBindingBuilder bindingBuilder = new SystemBindingBuilder(); + + CompositeComponent grandParent = new CompositeComponentImpl("grandparent", null, null, null); + CompositeComponent parent = new CompositeComponentImpl("parent", grandParent, null, null); + + // create a context in the grandparent that the reference will be autowired to + ComponentDefinition<SystemImplementation> targetComponentDefinition = MockComponentFactory.createTarget(); + AtomicComponent targetComponentComponent = builder.build(parent, targetComponentDefinition, deploymentContext); + grandParent.register(targetComponentComponent); + + BoundReferenceDefinition<SystemBinding> targetReferenceDefinition = MockComponentFactory.createBoundReference(); + ComponentDefinition<SystemImplementation> sourceComponentDefinition = + MockComponentFactory.createSourceWithTargetReference(); + + AtomicComponent sourceComponent = builder.build(parent, sourceComponentDefinition, deploymentContext); + Reference reference = bindingBuilder.build(parent, targetReferenceDefinition, deploymentContext); + + parent.register(sourceComponent); + parent.register(reference); + connector.connect(reference.getInboundWire(), reference.getOutboundWire(), true); + connector.connect(sourceComponent); + grandParent.register(parent); + grandParent.start(); + scope.onEvent(new CompositeStart(this, parent)); + Source source = (Source) parent.getSystemChild("source").getServiceInstance(); + assertNotNull(source); + Target target = (Target) parent.getSystemChild("target").getServiceInstance(); + assertNotNull(target); + assertSame(target, source.getTarget()); + scope.onEvent(new CompositeStop(this, parent)); + grandParent.stop(); + scope.stop(); + } + + + /** + * Validates building a wire from a service context to an atomic context + */ + public void testServiceToAtomicWireBuild() throws Exception { + WorkContext work = new WorkContextImpl(); + ScopeContainer scope = new ModuleScopeContainer(work); + scope.start(); + + ConnectorImpl connector = new ConnectorImpl(); + SystemComponentBuilder builder = new SystemComponentBuilder(); + SystemBindingBuilder bindingBuilder = new SystemBindingBuilder(); + + CompositeComponent parent = new CompositeComponentImpl(null, null, null, null); + + BoundServiceDefinition<SystemBinding> serviceDefinition = MockComponentFactory.createBoundService(); + ComponentDefinition<SystemImplementation> componentDefinition = MockComponentFactory.createTarget(); + + AtomicComponent sourceComponent = builder.build(parent, componentDefinition, deploymentContext); + parent.register(sourceComponent); + + Service service = bindingBuilder.build(parent, serviceDefinition, deploymentContext); + parent.register(service); + + connector.connect(sourceComponent); + connector.connect(service); + + parent.start(); + scope.onEvent(new CompositeStart(this, parent)); + Target target = (Target) parent.getSystemChild("serviceDefinition").getServiceInstance(); + assertNotNull(target); + Target target2 = (Target) parent.getSystemChild("target").getServiceInstance(); + assertNotNull(target); + assertSame(target, target2); + scope.onEvent(new CompositeStop(this, parent)); + parent.stop(); + scope.stop(); + + } + + protected void setUp() throws Exception { + super.setUp(); + ModuleScopeContainer moduleScope = new ModuleScopeContainer(); + moduleScope.start(); + deploymentContext = new RootDeploymentContext(null, null, moduleScope, null); + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/ComponentLoaderTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/ComponentLoaderTestCase.java new file mode 100644 index 0000000000..7fbda2baf9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/ComponentLoaderTestCase.java @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.osoa.sca.Version.XML_NAMESPACE_1_0; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import junit.framework.TestCase; + +import org.apache.tuscany.core.implementation.java.JavaImplementation; +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.PropertyObjectFactory; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.Implementation; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.model.ReferenceDefinition; +import org.apache.tuscany.spi.model.ServiceDefinition; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class ComponentLoaderTestCase extends TestCase { + private static final QName COMPONENT = new QName(XML_NAMESPACE_1_0, "component"); + private static final String NAME = "testComponent"; + private static final Implementation IMPL = new JavaImplementation(); + + private XMLStreamReader mockReader; + private LoaderRegistry mockRegistry; + private PropertyObjectFactory mockPropertyFactory; + private ComponentLoader loader; + + public void testEmptyComponent() throws LoaderException, XMLStreamException { + EasyMock.expect(mockReader.getName()).andReturn(COMPONENT).atLeastOnce(); + EasyMock.expect(mockReader.getAttributeValue((String) EasyMock.isNull(), EasyMock.isA(String.class))) + .andReturn(NAME); + EasyMock.expect(mockReader.getAttributeValue((String) EasyMock.isNull(), EasyMock.eq("initLevel"))) + .andReturn(null); + EasyMock.expect(mockReader.getAttributeValue(EasyMock.isA(String.class), EasyMock.isA(String.class))) + .andReturn(null); + EasyMock.expect(mockReader.nextTag()).andReturn(0); + EasyMock.expect(mockReader.next()).andReturn(XMLStreamConstants.END_ELEMENT); + EasyMock.replay(mockReader); + mockRegistry.loadComponentType(EasyMock.isA(CompositeComponent.class), + EasyMock.isA(Implementation.class), + EasyMock.isA(DeploymentContext.class)); + + EasyMock.expect(mockRegistry.load(EasyMock.isA(CompositeComponent.class), + EasyMock.eq(mockReader), + EasyMock.isA(DeploymentContext.class))).andReturn(IMPL); + EasyMock.replay(mockRegistry); + ComponentDefinition component = loader.load(EasyMock.createNiceMock(CompositeComponent.class), + mockReader, + EasyMock.createNiceMock(DeploymentContext.class)); + assertEquals(NAME, component.getName()); + assertNull(component.getInitLevel()); + } + + public void testInitValue20() throws LoaderException, XMLStreamException { + EasyMock.expect(mockReader.getName()).andReturn(COMPONENT).atLeastOnce(); + EasyMock.expect(mockReader.getAttributeValue((String) EasyMock.isNull(), EasyMock.isA(String.class))) + .andReturn(NAME); + EasyMock.expect(mockReader.getAttributeValue((String) EasyMock.isNull(), EasyMock.eq("initLevel"))) + .andReturn("20"); + EasyMock.expect(mockReader.nextTag()).andReturn(0); + EasyMock.expect(mockReader.next()).andReturn(XMLStreamConstants.END_ELEMENT); + EasyMock.replay(mockReader); + + mockRegistry.loadComponentType(EasyMock.isA(CompositeComponent.class), + EasyMock.isA(Implementation.class), + EasyMock.isA(DeploymentContext.class)); + EasyMock.expect(mockRegistry.load(EasyMock.isA(CompositeComponent.class), + EasyMock.eq(mockReader), + EasyMock.isA(DeploymentContext.class))).andReturn(IMPL); + EasyMock.replay(mockRegistry); + ComponentDefinition component = loader.load(EasyMock.createNiceMock(CompositeComponent.class), + mockReader, + EasyMock.createNiceMock(DeploymentContext.class)); + assertEquals(NAME, component.getName()); + assertEquals(Integer.valueOf(20), component.getInitLevel()); + } + + public void testLoadPropertyWithSource() throws LoaderException, XMLStreamException { + PojoComponentType<?, ?, Property<?>> type = + new PojoComponentType<ServiceDefinition, ReferenceDefinition, Property<?>>(); + Property property = new Property(); + property.setName("name"); + type.add(property); + JavaImplementation impl = new JavaImplementation(); + impl.setComponentType(type); + ComponentDefinition<?> defn = new ComponentDefinition<JavaImplementation>(impl); + XMLStreamReader reader = createMock(XMLStreamReader.class); + expect(reader.getAttributeValue(null, "name")).andReturn("name"); + expect(reader.getAttributeValue(null, "source")).andReturn("$source"); + expect(reader.getAttributeValue(null, "file")).andReturn(null); + expect(reader.next()).andReturn(XMLStreamConstants.END_ELEMENT); + replay(reader); + loader.loadProperty(reader, null, defn); + assertEquals("$source", defn.getPropertyValues().get("name").getSource()); + EasyMock.verify(reader); + } + + protected void setUp() throws Exception { + super.setUp(); + mockReader = EasyMock.createMock(XMLStreamReader.class); + mockRegistry = EasyMock.createMock(LoaderRegistry.class); + mockPropertyFactory = EasyMock.createMock(PropertyObjectFactory.class); + loader = new ComponentLoader(mockRegistry, mockPropertyFactory); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/IncludeLoaderTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/IncludeLoaderTestCase.java new file mode 100644 index 0000000000..38f1122004 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/IncludeLoaderTestCase.java @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import java.net.URL; +import javax.xml.namespace.QName; +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import junit.framework.TestCase; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.isNull; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import org.osoa.sca.Version; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.loader.MissingIncludeException; +import org.apache.tuscany.spi.model.CompositeComponentType; +import org.apache.tuscany.spi.model.Include; + +/** + * @version $Rev$ $Date$ + */ +public class IncludeLoaderTestCase extends TestCase { + private static final QName INCLUDE = new QName(Version.XML_NAMESPACE_1_0, "include"); + + private LoaderRegistry registry; + private IncludeLoader loader; + private XMLStreamReader reader; + private DeploymentContext context; + private URL base; + private URL includeURL; + private ClassLoader cl; + + public void testNoLocation() throws LoaderException, XMLStreamException { + String name = "foo"; + expect(reader.getName()).andReturn(INCLUDE); + expect(reader.getAttributeValue(null, "name")).andReturn(name); + expect(reader.getAttributeValue(null, "scdlLocation")).andReturn(null); + expect(reader.getAttributeValue(null, "scdlResource")).andReturn(null); + expect(reader.next()).andReturn(END_ELEMENT); + + expect(context.getClassLoader()).andReturn(cl); + replay(registry, reader, context); + + try { + loader.load(null, reader, context); + fail(); + } catch (MissingIncludeException e) { + // OK expected + } + verify(registry, reader, context); + } + + public void testWithAbsoluteScdlLocation() throws LoaderException, XMLStreamException { + String name = "foo"; + expect(reader.getName()).andReturn(INCLUDE); + expect(reader.getAttributeValue(null, "name")).andReturn(name); + expect(reader.getAttributeValue(null, "scdlLocation")).andReturn("http://example.com/include.scdl"); + expect(reader.getAttributeValue(null, "scdlResource")).andReturn(null); + expect(reader.next()).andReturn(END_ELEMENT); + + expect(context.getScdlLocation()).andReturn(base); + expect(context.getClassLoader()).andReturn(cl); + + expect(registry.load((CompositeComponent) isNull(), + eq(includeURL), + eq(CompositeComponentType.class), + isA(DeploymentContext.class))) + .andReturn(null); + replay(registry, reader, context); + + Include include = loader.load(null, reader, context); + assertEquals(name, include.getName()); + assertEquals(includeURL, include.getScdlLocation()); + verify(registry, reader, context); + } + + public void testWithRelativeScdlLocation() throws LoaderException, XMLStreamException { + String name = "foo"; + expect(reader.getName()).andReturn(INCLUDE); + expect(reader.getAttributeValue(null, "name")).andReturn(name); + expect(reader.getAttributeValue(null, "scdlLocation")).andReturn("include.scdl"); + expect(reader.getAttributeValue(null, "scdlResource")).andReturn(null); + expect(reader.next()).andReturn(END_ELEMENT); + + expect(context.getScdlLocation()).andReturn(base); + expect(context.getClassLoader()).andReturn(cl); + + expect(registry.load((CompositeComponent) isNull(), + eq(includeURL), + eq(CompositeComponentType.class), + isA(DeploymentContext.class))) + .andReturn(null); + replay(registry, reader, context); + + Include include = loader.load(null, reader, context); + assertEquals(name, include.getName()); + assertEquals(includeURL, include.getScdlLocation()); + verify(registry, reader, context); + } + + public void testWithScdlResource() throws LoaderException, XMLStreamException { + String name = "foo"; + String resource = "org/apache/tuscany/core/loader/test-include.scdl"; + includeURL = cl.getResource(resource); + assertNotNull(includeURL); + + expect(reader.getName()).andReturn(INCLUDE); + expect(reader.getAttributeValue(null, "name")).andReturn(name); + expect(reader.getAttributeValue(null, "scdlLocation")).andReturn(null); + expect(reader.getAttributeValue(null, "scdlResource")).andReturn(resource); + expect(reader.next()).andReturn(END_ELEMENT); + + expect(context.getClassLoader()).andReturn(cl); + + expect(registry.load((CompositeComponent) isNull(), + eq(includeURL), + eq(CompositeComponentType.class), + isA(DeploymentContext.class))) + .andReturn(null); + replay(registry, reader, context); + + Include include = loader.load(null, reader, context); + assertEquals(name, include.getName()); + assertEquals(includeURL, include.getScdlLocation()); + verify(registry, reader, context); + } + + protected void setUp() throws Exception { + super.setUp(); + registry = createMock(LoaderRegistry.class); + reader = createMock(XMLStreamReader.class); + context = createMock(DeploymentContext.class); + cl = getClass().getClassLoader(); + base = new URL("http://example.com/test.scdl"); + includeURL = new URL("http://example.com/include.scdl"); + loader = new IncludeLoader(registry); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/JNDIPropertyFactoryTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/JNDIPropertyFactoryTestCase.java new file mode 100644 index 0000000000..fb5bfd32d3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/JNDIPropertyFactoryTestCase.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import java.lang.reflect.Type; +import java.util.Hashtable; +import javax.naming.Context; +import javax.naming.NamingException; +import javax.naming.spi.InitialContextFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.apache.tuscany.spi.model.PropertyValue; + +import junit.framework.TestCase; +import org.apache.tuscany.core.injection.JNDIObjectFactory; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class JNDIPropertyFactoryTestCase extends TestCase { + + public void testCreate() throws Exception { + String old = System.getProperty(Context.INITIAL_CONTEXT_FACTORY); + try { + System.setProperty(Context.INITIAL_CONTEXT_FACTORY, MockInitialContextFactory.class.getName()); + JNDIPropertyFactory factory = new JNDIPropertyFactory(); + Element element = EasyMock.createMock(Element.class); + EasyMock.expect(element.getTextContent()).andReturn("foo"); + EasyMock.replay(element); + Document doc = EasyMock.createMock(Document.class); + EasyMock.expect(doc.getDocumentElement()).andReturn(element); + EasyMock.replay(doc); + PropertyValue<?> value = new MockPropertyValue<Type>(); + value.setValue(doc); + JNDIObjectFactory<?> jndiFactory = (JNDIObjectFactory<?>) factory.createObjectFactory(null, value); + assertEquals("bar", jndiFactory.getInstance()); + } finally { + System.clearProperty(Context.INITIAL_CONTEXT_FACTORY); + if (old != null) { + System.setProperty(Context.INITIAL_CONTEXT_FACTORY, old); + } + } + + } + + private class MockPropertyValue<T> extends PropertyValue<T> { + + } + + public static class MockInitialContextFactory implements InitialContextFactory { + public MockInitialContextFactory() { + } + + public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException { + Context context = EasyMock.createMock(Context.class); + EasyMock.expect(context.lookup("foo")).andReturn("bar"); + EasyMock.replay(context); + return context; + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/PropertyParsingTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/PropertyParsingTestCase.java new file mode 100644 index 0000000000..080bc25039 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/PropertyParsingTestCase.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import java.io.StringReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamException; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.DocumentBuilder; + +import junit.framework.TestCase; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +/** + * @version $Rev$ $Date$ + */ +public class PropertyParsingTestCase extends TestCase { + private XMLInputFactory xmlFactory; + private DocumentBuilder docBuilder; + private Element root; + + public void testComplexProperty() throws XMLStreamException { + String xml = "<property xmlns:foo='http://foo.com'>" + + "<foo:a>aValue</foo:a>" + + "<foo:b>InterestingURI</foo:b>" + + "</property>"; + + XMLStreamReader reader = getReader(xml); + StAXUtil.loadPropertyValue(reader, root); + NodeList childNodes = root.getChildNodes(); + assertEquals(2, childNodes.getLength()); + + Element e = (Element) childNodes.item(0); + assertEquals("http://foo.com", e.getNamespaceURI()); + assertEquals("a", e.getLocalName()); + assertEquals("aValue", e.getTextContent()); + e = (Element) childNodes.item(1); + assertEquals("http://foo.com", e.getNamespaceURI()); + assertEquals("b", e.getLocalName()); + assertEquals("InterestingURI", e.getTextContent()); + } + + public XMLStreamReader getReader(String xml) throws XMLStreamException { + XMLStreamReader reader = xmlFactory.createXMLStreamReader(new StringReader(xml)); + reader.next(); + return reader; + } + + protected void setUp() throws Exception { + super.setUp(); + xmlFactory = XMLInputFactory.newInstance(); + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + docBuilder = docFactory.newDocumentBuilder(); + Document doc = docBuilder.newDocument(); + root = doc.createElement("value"); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/ServiceLoaderTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/ServiceLoaderTestCase.java new file mode 100644 index 0000000000..bcf153290a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/ServiceLoaderTestCase.java @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import javax.xml.namespace.QName; +import static javax.xml.stream.XMLStreamConstants.END_ELEMENT; +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import static org.osoa.sca.Version.XML_NAMESPACE_1_0; + +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.LoaderRegistry; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.model.ServiceDefinition; + +import junit.framework.TestCase; +import org.apache.tuscany.core.deployer.RootDeploymentContext; +import org.easymock.EasyMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; + +/** + * Verifies loading of a service definition from an XML-based assembly + * + * @version $Rev$ $Date$ + */ +public class ServiceLoaderTestCase extends TestCase { + private static final QName SERVICE = new QName(XML_NAMESPACE_1_0, "service"); + private static final QName REFERENCE = new QName(XML_NAMESPACE_1_0, "reference"); + private static final QName INTERFACE_JAVA = new QName(XML_NAMESPACE_1_0, "interface.java"); + + private ServiceLoader loader; + private DeploymentContext deploymentContext; + private XMLStreamReader mockReader; + private LoaderRegistry mockRegistry; + + public void testWithNoInterface() throws LoaderException, XMLStreamException { + String name = "serviceDefinition"; +// String target = "target"; + expect(mockReader.getName()).andReturn(SERVICE).anyTimes(); + expect(mockReader.getAttributeValue(null, "name")).andReturn(name); + expect(mockReader.next()).andReturn(END_ELEMENT); + expect(mockReader.getName()).andReturn(SERVICE).anyTimes(); + replay(mockReader); + ServiceDefinition serviceDefinition = loader.load(null, mockReader, null); + assertNotNull(serviceDefinition); + assertEquals(name, serviceDefinition.getName()); + } + + public void testWithInterface() throws LoaderException, XMLStreamException { + String name = "serviceDefinition"; + String target = "target"; + ServiceContract sc = new ServiceContract() { + }; + expect(mockReader.getName()).andReturn(SERVICE).anyTimes(); + expect(mockReader.getAttributeValue(null, "name")).andReturn(name); + expect(mockReader.next()).andReturn(START_ELEMENT); + expect(mockReader.getName()).andReturn(INTERFACE_JAVA); + expect(mockRegistry.load(null, mockReader, deploymentContext)).andReturn(sc); + expect(mockReader.next()).andReturn(START_ELEMENT); + expect(mockReader.getName()).andReturn(REFERENCE); + expect(mockReader.getElementText()).andReturn(target); + expect(mockReader.next()).andReturn(END_ELEMENT); + expect(mockReader.getName()).andReturn(REFERENCE); + expect(mockReader.next()).andReturn(END_ELEMENT); + expect(mockReader.getName()).andReturn(SERVICE); + + replay(mockReader); + replay(mockRegistry); + + ServiceDefinition serviceDefinition = loader.load(null, mockReader, deploymentContext); + assertNotNull(serviceDefinition); + assertEquals(name, serviceDefinition.getName()); + assertSame(sc, serviceDefinition.getServiceContract()); + } + + protected void setUp() throws Exception { + super.setUp(); + mockReader = EasyMock.createStrictMock(XMLStreamReader.class); + mockRegistry = EasyMock.createMock(LoaderRegistry.class); + loader = new ServiceLoader(mockRegistry); + deploymentContext = new RootDeploymentContext(null, null, null, null); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/StAXLoaderRegistryImplTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/StAXLoaderRegistryImplTestCase.java new file mode 100644 index 0000000000..0d7c47774e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/StAXLoaderRegistryImplTestCase.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.spi.component.CompositeComponent; +import org.apache.tuscany.spi.deployer.DeploymentContext; +import org.apache.tuscany.spi.loader.LoaderException; +import org.apache.tuscany.spi.loader.StAXElementLoader; +import org.apache.tuscany.spi.loader.UnrecognizedElementException; +import org.apache.tuscany.spi.model.ModelObject; + +import junit.framework.TestCase; +import org.apache.tuscany.core.deployer.RootDeploymentContext; +import org.easymock.classextension.EasyMock; + +/** + * Verifies the default loader registry + * + * @version $Rev$ $Date$ + */ +public class StAXLoaderRegistryImplTestCase extends TestCase { + private LoaderRegistryImpl registry; + private QName name; + private LoaderRegistryImpl.Monitor mockMonitor; + private StAXElementLoader<ModelObject> mockLoader; + private XMLStreamReader mockReader; + private DeploymentContext deploymentContext; + private ModelObject modelObject; + + public void testLoaderRegistration() { + mockMonitor.registeringLoader(EasyMock.eq(name)); + EasyMock.replay(mockMonitor); + registry.registerLoader(name, mockLoader); + EasyMock.verify(mockMonitor); + } + + public void testLoaderUnregistration() { + mockMonitor.unregisteringLoader(EasyMock.eq(name)); + EasyMock.replay(mockMonitor); + registry.unregisterLoader(name, (StAXElementLoader<ModelObject>) mockLoader); + EasyMock.verify(mockMonitor); + } + + public void testSuccessfulDispatch() throws LoaderException, XMLStreamException { + EasyMock.expect(mockReader.getName()).andReturn(name); + EasyMock.replay(mockReader); + mockMonitor.registeringLoader(EasyMock.eq(name)); + mockMonitor.elementLoad(EasyMock.eq(name)); + EasyMock.replay(mockMonitor); + EasyMock.expect(mockLoader.load(EasyMock.isA(CompositeComponent.class), + EasyMock.eq(mockReader), + EasyMock.eq(deploymentContext))).andReturn(modelObject); + EasyMock.replay(mockLoader); + registry.registerLoader(name, (StAXElementLoader<ModelObject>) mockLoader); + CompositeComponent parent = EasyMock.createNiceMock(CompositeComponent.class); + assertSame(modelObject, registry.load(parent, mockReader, deploymentContext)); + EasyMock.verify(mockLoader); + EasyMock.verify(mockMonitor); + EasyMock.verify(mockReader); + + } + + public void testUnsuccessfulDispatch() throws LoaderException, XMLStreamException { + EasyMock.expect(mockReader.getName()).andReturn(name); + EasyMock.replay(mockReader); + mockMonitor.elementLoad(EasyMock.eq(name)); + EasyMock.replay(mockMonitor); + try { + registry.load(null, mockReader, deploymentContext); + fail(); + } catch (UnrecognizedElementException e) { + assertSame(name, e.getElement()); + } + EasyMock.verify(mockReader); + EasyMock.verify(mockMonitor); + } + + @SuppressWarnings("unchecked") + protected void setUp() throws Exception { + super.setUp(); + name = new QName("http://mock", "test"); + deploymentContext = new RootDeploymentContext(null, null, null, null); + registry = new LoaderRegistryImpl(); + mockMonitor = EasyMock.createMock(LoaderRegistryImpl.Monitor.class); + registry.setMonitor(mockMonitor); + + mockLoader = EasyMock.createMock(StAXElementLoader.class); + mockReader = EasyMock.createMock(XMLStreamReader.class); + modelObject = new ModelObject() { + }; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/StringParserPropertyFactoryTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/StringParserPropertyFactoryTestCase.java new file mode 100644 index 0000000000..4445dfad2c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/loader/StringParserPropertyFactoryTestCase.java @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.loader; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.model.PropertyValue; + +import junit.framework.TestCase; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class StringParserPropertyFactoryTestCase extends TestCase { + + private <T> PropertyValue<T> mock(String value) { + Document document = EasyMock.createMock(Document.class); + Element element = EasyMock.createMock(Element.class); + EasyMock.expect(document.getDocumentElement()).andReturn(element); + EasyMock.expect(element.getTextContent()).andReturn(value); + EasyMock.replay(document, element); + return new PropertyValue<T>(null, document); + } + + public void testInteger() throws Exception { + + StringParserPropertyFactory factory = new StringParserPropertyFactory(); + Property<Integer> property = new Property<Integer>(); + property.setJavaType(Integer.class); + PropertyValue<Integer> propertyValue = mock("1"); + ObjectFactory<Integer> oFactory = factory.createObjectFactory(property, propertyValue); + assertEquals(1, oFactory.getInstance().intValue()); + } + + public void testPrimitiveInt() throws Exception { + StringParserPropertyFactory factory = new StringParserPropertyFactory(); + Property<Integer> property = new Property<Integer>(); + property.setJavaType(Integer.TYPE); + PropertyValue<Integer> propertyValue = mock("1"); + ObjectFactory<Integer> oFactory = factory.createObjectFactory(property, propertyValue); + assertEquals(1, oFactory.getInstance().intValue()); + } + + public void testString() throws Exception { + StringParserPropertyFactory factory = new StringParserPropertyFactory(); + Property<String> property = new Property<String>(); + property.setJavaType(String.class); + PropertyValue<String> propertyValue = mock("1"); + ObjectFactory<String> oFactory = factory.createObjectFactory(property, propertyValue); + assertEquals("1", oFactory.getInstance()); + } + + public void testByteArray() throws Exception { + StringParserPropertyFactory factory = new StringParserPropertyFactory(); + Property<byte[]> property = new Property<byte[]>(); + property.setJavaType(byte[].class); + PropertyValue<byte[]> propertyValue = mock("1"); + ObjectFactory<byte[]> oFactory = factory.createObjectFactory(property, propertyValue); + byte[] result = oFactory.getInstance(); + byte[] expected = "1".getBytes(); + for (int i = 0; i < result.length; i++) { + byte b = result[i]; + if (b != expected[i]) { + fail(); + } + } + } + + public void testBoolean() throws Exception { + StringParserPropertyFactory factory = new StringParserPropertyFactory(); + Property<Boolean> property = new Property<Boolean>(); + property.setJavaType(Boolean.class); + PropertyValue<Boolean> propertyValue = mock("true"); + ObjectFactory<Boolean> oFactory = factory.createObjectFactory(property, propertyValue); + assertTrue(oFactory.getInstance()); + } + + public void testPrimitiveBoolean() throws Exception { + StringParserPropertyFactory factory = new StringParserPropertyFactory(); + Property<Boolean> property = new Property<Boolean>(); + property.setJavaType(Boolean.TYPE); + PropertyValue<Boolean> propertyValue = mock("true"); + ObjectFactory<Boolean> oFactory = factory.createObjectFactory(property, propertyValue); + assertTrue(oFactory.getInstance()); + } + + public void testStringConstructor() throws Exception { + StringParserPropertyFactory factory = new StringParserPropertyFactory(); + Property<Foo> property = new Property<Foo>(); + property.setJavaType(Foo.class); + PropertyValue<Foo> propertyValue = mock("test"); + ObjectFactory<Foo> oFactory = factory.createObjectFactory(property, propertyValue); + assertEquals("test", oFactory.getInstance().getFoo()); + } + + private static class Foo { + private String foo; + + public Foo(String foo) { + this.foo = foo; + } + + public String getFoo() { + return foo; + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/BadContextPojo.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/BadContextPojo.java new file mode 100644 index 0000000000..214378b2c9 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/BadContextPojo.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +import org.osoa.sca.annotations.Context; + +public class BadContextPojo { + + @Context + String moduleContext; + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/BadNamePojo.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/BadNamePojo.java new file mode 100644 index 0000000000..77ec37f9e4 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/BadNamePojo.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +import org.osoa.sca.annotations.ComponentName; + +public class BadNamePojo { + @ComponentName + private int name; +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/BasicInterface.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/BasicInterface.java new file mode 100644 index 0000000000..b7921c248f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/BasicInterface.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +/** + * @version $Rev$ $Date$ + */ +public interface BasicInterface { + String returnsProperty(); + + BasicInterface returnsReference(); + + int returnsInt(); +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/BasicInterfaceImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/BasicInterfaceImpl.java new file mode 100644 index 0000000000..c2ca45ec17 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/BasicInterfaceImpl.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +import org.osoa.sca.annotations.Property; +import org.osoa.sca.annotations.Reference; + +/** + * @version $Rev$ $Date$ + */ +public class BasicInterfaceImpl implements BasicInterface { + + @Property + public String publicProperty; + @Reference + public BasicInterface publicReference; + @Property + protected String protectedProperty; + @Reference + protected BasicInterface protectedReference; + private String privateProperty; + private BasicInterface privateReference; + + @Property + public void setPrivateProperty(String privateProperty) { + this.privateProperty = privateProperty; + } + + @Reference + public void setPrivateReference(BasicInterface privateReference) { + this.privateReference = privateReference; + } + + public String returnsProperty() { + return privateProperty; + } + + public BasicInterface returnsReference() { + return privateReference; + } + + public int returnsInt() { + return 0; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeComponent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeComponent.java new file mode 100644 index 0000000000..5b63caf286 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeComponent.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +import org.osoa.sca.annotations.Scope; + +/** + * @version $Rev$ $Date$ + */ +@Scope("MODULE") +public interface ModuleScopeComponent { + + //public boolean isInit(); +} + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeComponentImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeComponentImpl.java new file mode 100644 index 0000000000..5febc32ce6 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeComponentImpl.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.core.mock.component; + +import org.osoa.sca.annotations.Scope; + + +/** + * @version $Rev$ $Date$ + */ +@Scope("MODULE") +public class ModuleScopeComponentImpl implements + ModuleScopeComponent { + + private String foo; + + public void setFoo(String foo) { + this.foo = foo; + } + + public String getFoo() { + return foo; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeDestroyOnlyComponent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeDestroyOnlyComponent.java new file mode 100644 index 0000000000..886f3586f8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeDestroyOnlyComponent.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.core.mock.component; + +import org.osoa.sca.annotations.Destroy; + +public class ModuleScopeDestroyOnlyComponent extends ModuleScopeComponentImpl { + + boolean destroyed; + + public boolean isDestroyed() { + return destroyed; + } + + @Destroy + public void destroy() { + destroyed = true; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeEagerInitComponent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeEagerInitComponent.java new file mode 100644 index 0000000000..a4cf75e8cb --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeEagerInitComponent.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.core.mock.component; + +import org.osoa.sca.annotations.Init; + +public class ModuleScopeEagerInitComponent extends ModuleScopeComponentImpl { + + boolean initialized; + // this value tests to ensure introspection can find the init() method even + // if a field is named the same. Ultimately, this should be in the + // introspection tests + private boolean init; + + public boolean isInitialized() { + return initialized; + } + + @Init(eager = true) + public void init() { + initialized = true; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeEagerInitDestroyComponent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeEagerInitDestroyComponent.java new file mode 100644 index 0000000000..4cb219958d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeEagerInitDestroyComponent.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +import org.osoa.sca.annotations.Destroy; + +public class ModuleScopeEagerInitDestroyComponent extends ModuleScopeEagerInitComponent { + + boolean destroyed; + + public boolean isDestroyed() { + return destroyed; + } + + @Destroy + public void destroy() { + destroyed = true; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeInitDestroyComponent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeInitDestroyComponent.java new file mode 100644 index 0000000000..323ebc636f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeInitDestroyComponent.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.core.mock.component; + +import org.osoa.sca.annotations.Destroy; + +public class ModuleScopeInitDestroyComponent extends ModuleScopeInitOnlyComponent { + + boolean destroyed; + + public boolean isDestroyed() { + return destroyed; + } + + @Destroy + public void destroy() { + if (destroyed) { + throw new AssertionError("Destroy called more than once"); + } + destroyed = true; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeInitOnlyComponent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeInitOnlyComponent.java new file mode 100644 index 0000000000..723ee18fac --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/ModuleScopeInitOnlyComponent.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +import org.osoa.sca.annotations.Init; + +public class ModuleScopeInitOnlyComponent extends ModuleScopeComponentImpl { + + private boolean initialized; + // this value tests to ensure introspection can find the init() method even + // if a field is named the same. Ultimately, this should be in the introspection tests + private boolean init; + + public boolean isInitialized() { + return initialized; + } + + @Init + public void init() { + if (initialized) { + throw new AssertionError("Init called more than once"); + } + initialized = true; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/OrderException.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/OrderException.java new file mode 100644 index 0000000000..af257c226d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/OrderException.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.core.mock.component; + +public class OrderException extends Exception { + + public OrderException() { + super(); + } + + public OrderException(String message) { + super(message); + } + + public OrderException(String message, Throwable cause) { + super(message, cause); + } + + public OrderException(Throwable cause) { + super(cause); + } + +} + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/OrderedDependentPojo.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/OrderedDependentPojo.java new file mode 100644 index 0000000000..2033f0eca5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/OrderedDependentPojo.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +/** + * @version $$Rev$$ $$Date$$ + */ +public interface OrderedDependentPojo extends OrderedInitPojo { + + OrderedInitPojo getPojo(); + + void setPojo(OrderedInitPojo pojo); +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/OrderedDependentPojoImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/OrderedDependentPojoImpl.java new file mode 100644 index 0000000000..439c3d143c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/OrderedDependentPojoImpl.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.core.mock.component; + +/** + * @version $$Rev$$ $$Date$$ + */ +public class OrderedDependentPojoImpl extends OrderedInitPojoImpl implements OrderedDependentPojo { + + private OrderedInitPojo pojo; + + public OrderedInitPojo getPojo() { + return pojo; + } + + public void setPojo(OrderedInitPojo pojo) { + this.pojo = pojo; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/OrderedEagerInitPojo.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/OrderedEagerInitPojo.java new file mode 100644 index 0000000000..815d9d6b12 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/OrderedEagerInitPojo.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +import org.osoa.sca.annotations.Destroy; +import org.osoa.sca.annotations.Init; +import org.osoa.sca.annotations.Scope; + +@Scope("MODULE") +public class OrderedEagerInitPojo { + + private static final Object LOCK = new Object(); + private static int numberInstantied; + private int initOrder; + + @Init(eager = true) + public void init() { + synchronized (LOCK) { + ++numberInstantied; + initOrder = numberInstantied; + } + } + + @Destroy + public void destroy() throws OrderException { + synchronized (LOCK) { + if (initOrder != numberInstantied) { + throw new OrderException("Instance shutdown done out of order"); + } + --numberInstantied; + } + } + + public int getNumberInstantiated() { + return numberInstantied; + } + + public int getInitOrder() { + return initOrder; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/OrderedInitPojo.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/OrderedInitPojo.java new file mode 100644 index 0000000000..0b891cfa42 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/OrderedInitPojo.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +/** + * @version $$Rev$$ $$Date$$ + */ +public interface OrderedInitPojo { + int getNumberInstantiated(); + + int getInitOrder(); +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/OrderedInitPojoImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/OrderedInitPojoImpl.java new file mode 100644 index 0000000000..53338f5613 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/OrderedInitPojoImpl.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +import org.osoa.sca.annotations.Destroy; +import org.osoa.sca.annotations.Init; +import org.osoa.sca.annotations.Scope; + +@Scope("MODULE") +public class OrderedInitPojoImpl implements OrderedInitPojo { + + private static final Object LOCK = new Object(); + private static int numberInstantied; + private int initOrder; + + @Init + public void init() { + synchronized (LOCK) { + ++numberInstantied; + initOrder = numberInstantied; + } + } + + @Destroy + public void destroy() throws OrderException { + synchronized (LOCK) { + if (initOrder != numberInstantied) { + throw new OrderException("Instance shutdown done out of order"); + } + --numberInstantied; + } + } + + public int getNumberInstantiated() { + return numberInstantied; + } + + public int getInitOrder() { + return initOrder; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/RequestScopeComponent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/RequestScopeComponent.java new file mode 100644 index 0000000000..8c7dc107ee --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/RequestScopeComponent.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +import org.osoa.sca.annotations.Scope; + +/** + * @version $Rev$ $Date$ + */ +@Scope("REQUEST") +public interface RequestScopeComponent { + +} + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/RequestScopeDestroyOnlyComponent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/RequestScopeDestroyOnlyComponent.java new file mode 100644 index 0000000000..5224ceda5f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/RequestScopeDestroyOnlyComponent.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +import org.osoa.sca.annotations.Destroy; +import org.osoa.sca.annotations.Scope; + +@Scope("REQUEST") +public class RequestScopeDestroyOnlyComponent extends SessionScopeComponentImpl { + + boolean destroyed; + + public boolean isDestroyed() { + return destroyed; + } + + @Destroy + public void destroy() { + destroyed = true; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/RequestScopeInitDestroyComponent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/RequestScopeInitDestroyComponent.java new file mode 100644 index 0000000000..38b188a4b5 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/RequestScopeInitDestroyComponent.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +import org.osoa.sca.annotations.Destroy; +import org.osoa.sca.annotations.Scope; + +@Scope("REQUEST") +public class RequestScopeInitDestroyComponent extends SessionScopeInitOnlyComponent { + + boolean destroyed; + + public boolean isDestroyed() { + return destroyed; + } + + @Destroy + public void destroy() { + destroyed = true; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/RequestScopeInitOnlyComponent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/RequestScopeInitOnlyComponent.java new file mode 100644 index 0000000000..707f8ab50f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/RequestScopeInitOnlyComponent.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.core.mock.component; + +import org.osoa.sca.annotations.Init; +import org.osoa.sca.annotations.Scope; + +@Scope("REQUEST") +public class RequestScopeInitOnlyComponent extends SessionScopeComponentImpl { + + private boolean initialized; + + public boolean isInitialized() { + return initialized; + } + + @Init + public void init() { + initialized = true; + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SessionScopeComponent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SessionScopeComponent.java new file mode 100644 index 0000000000..827ba804f2 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SessionScopeComponent.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +import org.osoa.sca.annotations.Scope; + +/** + * @version $Rev$ $Date$ + */ +@Scope("SESSION") +public interface SessionScopeComponent { + +} + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SessionScopeComponentImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SessionScopeComponentImpl.java new file mode 100644 index 0000000000..e547bf6113 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SessionScopeComponentImpl.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +import org.osoa.sca.annotations.Scope; + +/** + * @version $Rev$ $Date$ + */ +@Scope("SESSION") +public class SessionScopeComponentImpl implements + SessionScopeComponent { + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SessionScopeInitDestroyComponent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SessionScopeInitDestroyComponent.java new file mode 100644 index 0000000000..c11bd1bd49 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SessionScopeInitDestroyComponent.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.core.mock.component; + +import org.osoa.sca.annotations.Destroy; + +public class SessionScopeInitDestroyComponent extends SessionScopeInitOnlyComponent { + + private boolean destroyed; + + public boolean isDestroyed() { + return destroyed; + } + + @Destroy + public void destroy() { + destroyed = true; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SessionScopeInitOnlyComponent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SessionScopeInitOnlyComponent.java new file mode 100644 index 0000000000..095cc916ec --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SessionScopeInitOnlyComponent.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +import org.osoa.sca.annotations.Init; + +public class SessionScopeInitOnlyComponent extends SessionScopeComponentImpl { + + private boolean initialized; + + public boolean isInitialized() { + return initialized; + } + + @Init + public void init() { + initialized = true; + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SimpleTarget.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SimpleTarget.java new file mode 100644 index 0000000000..c78ba00a7a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SimpleTarget.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +public interface SimpleTarget { + + String hello(String message) throws Exception; + + String goodbye(String message) throws Exception; + + String echo(String message) throws Exception; + +} + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SimpleTargetImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SimpleTargetImpl.java new file mode 100644 index 0000000000..634a07a401 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SimpleTargetImpl.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +public class SimpleTargetImpl implements SimpleTarget { + + public SimpleTargetImpl() { + super(); + } + + public String hello(String message) throws Exception { + return message; + } + + public String goodbye(String message) throws Exception { + return message; + } + + public String echo(String message) throws Exception { + return message; + } + + +} + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/Source.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/Source.java new file mode 100644 index 0000000000..f7969f748b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/Source.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +import java.util.List; + +/** + * Implementations are used in wiring tests + * + * @version $Rev$ $Date$ + */ +public interface Source { + + Target getTarget(); + + List<Target> getTargets(); + + List<Target> getTargetsThroughField(); + +} + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SourceImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SourceImpl.java new file mode 100644 index 0000000000..187e33b2bd --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/SourceImpl.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +import java.util.List; + +/** + * Mock system component implementation used in wiring tests + * + * @version $Rev$ $Date$ + */ +public class SourceImpl implements Source { + + private Target target; + private List<Target> targets; + private List<Target> targetsThroughField; + private Target[] targetsArray; + + public void setTarget(Target target) { + this.target = target; + } + + public Target getTarget() { + return target; + } + + public List<Target> getTargets() { + return targets; + } + + public void setTargets(List<Target> targets) { + this.targets = targets; + } + + public List<Target> getTargetsThroughField() { + return targetsThroughField; + } + + public Target[] getArrayOfTargets() { + return targetsArray; + } + + public void setArrayOfTargets(Target[] targets) { + targetsArray = targets; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/StatelessComponent.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/StatelessComponent.java new file mode 100644 index 0000000000..c16ac942a3 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/StatelessComponent.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +import org.osoa.sca.annotations.Scope; + +/** + * @version $Rev$ $Date$ + */ +@Scope("STATELESS") +public interface StatelessComponent { + +} + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/StatelessComponentImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/StatelessComponentImpl.java new file mode 100644 index 0000000000..64a23c12c8 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/StatelessComponentImpl.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +/** + * @version $Rev$ $Date$ + */ +public class StatelessComponentImpl implements + StatelessComponent { + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/Target.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/Target.java new file mode 100644 index 0000000000..778c14665d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/Target.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.core.mock.component; + +/** + * Implementations are used in wiring tests + * + * @version $Rev$ $Date$ + */ +public interface Target { + + String getString(); + + void setString(String val); +} + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/TargetImpl.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/TargetImpl.java new file mode 100644 index 0000000000..037dd3a37c --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/component/TargetImpl.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.component; + +/** + * Mock system component implementation used in wiring tests + * + * @version $Rev$ $Date$ + */ +public class TargetImpl implements Target { + + private String theString; + + public String getString() { + return theString; + } + + public void setString(String val) { + theString = val; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/factories/MockComponentFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/factories/MockComponentFactory.java new file mode 100644 index 0000000000..e6f1611d40 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/factories/MockComponentFactory.java @@ -0,0 +1,180 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.factories; + +import java.net.URI; +import java.net.URISyntaxException; + +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.implementation.java.ConstructorDefinition; +import org.apache.tuscany.spi.implementation.java.JavaMappedProperty; +import org.apache.tuscany.spi.implementation.java.JavaMappedReference; +import org.apache.tuscany.spi.implementation.java.JavaMappedService; +import org.apache.tuscany.spi.implementation.java.PojoComponentType; +import org.apache.tuscany.spi.model.BoundReferenceDefinition; +import org.apache.tuscany.spi.model.BoundServiceDefinition; +import org.apache.tuscany.spi.model.ComponentDefinition; +import org.apache.tuscany.spi.model.ReferenceTarget; +import org.apache.tuscany.spi.model.Scope; +import org.apache.tuscany.spi.model.ServiceContract; + +import org.apache.tuscany.core.implementation.system.model.SystemBinding; +import org.apache.tuscany.core.implementation.system.model.SystemImplementation; +import org.apache.tuscany.core.mock.component.SourceImpl; +import org.apache.tuscany.core.mock.component.Target; +import org.apache.tuscany.core.mock.component.TargetImpl; + +/** + * @version $$Rev$$ $$Date$$ + */ +public final class MockComponentFactory { + + private MockComponentFactory() { + } + + /** + * Creates a component named "source" with a reference to target/Target + */ + public static ComponentDefinition<SystemImplementation> createSourceWithTargetReference() + throws NoSuchMethodException { + SystemImplementation impl = new SystemImplementation(); + PojoComponentType componentType = new PojoComponentType(); + componentType.setImplementationScope(Scope.MODULE); + componentType + .setConstructorDefinition( + new ConstructorDefinition<SourceImpl>(SourceImpl.class.getConstructor((Class[]) null))); + JavaMappedReference reference; + try { + reference = new JavaMappedReference(); + reference.setName("target"); + reference.setMember(SourceImpl.class.getMethod("setTarget", Target.class)); + JavaServiceContract contract = new JavaServiceContract(); + contract.setInterfaceClass(Target.class); + reference.setServiceContract(contract); + componentType.add(reference); + } catch (NoSuchMethodException e) { + throw new AssertionError(e); + } + impl.setComponentType(componentType); + impl.setImplementationClass(SourceImpl.class); + ComponentDefinition<SystemImplementation> sourceComponentDefinition = + new ComponentDefinition<SystemImplementation>(impl); + sourceComponentDefinition.setName("source"); + + ReferenceTarget referenceTarget = new ReferenceTarget(); + referenceTarget.setReferenceName("target"); + try { + referenceTarget.addTarget(new URI("target/Target")); + } catch (URISyntaxException e) { + throw new AssertionError(e); + } + sourceComponentDefinition.add(referenceTarget); + return sourceComponentDefinition; + } + + /** + * Creates a component named "source" with an autowire reference to {@link Target} + */ + public static ComponentDefinition<SystemImplementation> createSourceWithTargetAutowire() { + SystemImplementation impl = new SystemImplementation(); + PojoComponentType componentType = new PojoComponentType(); + componentType.setImplementationScope(Scope.MODULE); + JavaMappedReference reference; + try { + reference = new JavaMappedReference(); + reference.setName("target"); + reference.setMember(SourceImpl.class.getMethod("setTarget", Target.class)); + reference.setAutowire(true); + ServiceContract<?> contract = new JavaServiceContract(); + contract.setInterfaceClass(Target.class); + reference.setServiceContract(contract); + componentType.add(reference); + } catch (NoSuchMethodException e) { + throw new AssertionError(e); + } + impl.setComponentType(componentType); + impl.setImplementationClass(SourceImpl.class); + ComponentDefinition<SystemImplementation> sourceComponentDefinition = + new ComponentDefinition<SystemImplementation>(impl); + sourceComponentDefinition.setName("source"); + + ReferenceTarget referenceTarget = new ReferenceTarget(); + referenceTarget.setReferenceName("target"); + sourceComponentDefinition.add(referenceTarget); + return sourceComponentDefinition; + } + + /** + * Creates a component named "target" with a service named "Target" + */ + public static ComponentDefinition<SystemImplementation> createTarget() throws NoSuchMethodException { + SystemImplementation impl = new SystemImplementation(); + PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>> componentType = + new PojoComponentType<JavaMappedService, JavaMappedReference, JavaMappedProperty<?>>(); + componentType.setImplementationScope(Scope.MODULE); + componentType + .setConstructorDefinition( + new ConstructorDefinition<TargetImpl>(TargetImpl.class.getConstructor((Class[]) null))); + JavaMappedService targetServiceDefinition = new JavaMappedService(); + targetServiceDefinition.setName("Target"); + ServiceContract<?> contract = new JavaServiceContract(); + contract.setInterfaceClass(Target.class); + targetServiceDefinition.setServiceContract(contract); + componentType.add(targetServiceDefinition); + impl.setComponentType(componentType); + impl.setImplementationClass(TargetImpl.class); + ComponentDefinition<SystemImplementation> targetComponentDefinition = + new ComponentDefinition<SystemImplementation>(impl); + targetComponentDefinition.setName("target"); + return targetComponentDefinition; + } + + + public static BoundReferenceDefinition<SystemBinding> createBoundReference() { + SystemBinding binding = new SystemBinding(); + BoundReferenceDefinition<SystemBinding> referenceDefinition = new BoundReferenceDefinition<SystemBinding>(); + referenceDefinition.setBinding(binding); + referenceDefinition.setName("target"); + ServiceContract<?> contract = new JavaServiceContract(); + contract.setInterfaceClass(Target.class); + referenceDefinition.setServiceContract(contract); + return referenceDefinition; + } + + /** + * Creates a bound service with the name "service" that is configured to be wired to a target named "target/Target" + */ + public static BoundServiceDefinition<SystemBinding> createBoundService() { + SystemBinding binding = new SystemBinding(); + BoundServiceDefinition<SystemBinding> serviceDefinition = new BoundServiceDefinition<SystemBinding>(); + serviceDefinition.setBinding(binding); + serviceDefinition.setName("serviceDefinition"); + ServiceContract<?> contract = new JavaServiceContract(); + contract.setInterfaceClass(Target.class); + serviceDefinition.setServiceContract(contract); + try { + serviceDefinition.setTarget(new URI("target/Target")); + } catch (URISyntaxException e) { + throw new AssertionError(e); + } + return serviceDefinition; + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/factories/MockFactory.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/factories/MockFactory.java new file mode 100644 index 0000000000..c06633c4f7 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/factories/MockFactory.java @@ -0,0 +1,184 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.factories; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.osoa.sca.annotations.Destroy; +import org.osoa.sca.annotations.Init; + +import org.apache.tuscany.spi.QualifiedName; +import org.apache.tuscany.spi.component.AtomicComponent; +import org.apache.tuscany.spi.component.ScopeContainer; +import org.apache.tuscany.spi.component.SystemAtomicComponent; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.idl.java.JavaServiceContract; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; + +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.implementation.PojoConfiguration; +import org.apache.tuscany.core.implementation.system.component.SystemAtomicComponentImpl; +import org.apache.tuscany.core.implementation.system.wire.SystemInboundWireImpl; +import org.apache.tuscany.core.implementation.system.wire.SystemOutboundWire; +import org.apache.tuscany.core.implementation.system.wire.SystemOutboundWireImpl; +import org.apache.tuscany.core.injection.MethodEventInvoker; +import org.apache.tuscany.core.injection.PojoObjectFactory; +import org.apache.tuscany.core.wire.InboundInvocationChainImpl; +import org.apache.tuscany.core.wire.InboundWireImpl; +import org.apache.tuscany.core.wire.InvokerInterceptor; + +/** + * @version $$Rev$$ $$Date$$ + */ +public final class MockFactory { + + private MockFactory() { + } + + public static Map<String, AtomicComponent> createWiredComponents(String source, + Class<?> sourceClass, + ScopeContainer sourceScopeContainer, + String target, + Class<?> targetClass, + ScopeContainer targetScopeContainer) + throws NoSuchMethodException { + List<Class<?>> sourceClasses = new ArrayList<Class<?>>(); + sourceClasses.add(sourceClass); + return createWiredComponents(source, sourceClasses, sourceClass, sourceScopeContainer, target, targetClass, + targetScopeContainer); + } + + /** + * Creates source and target {@link AtomicComponent}s whose instances are wired together. The wiring algorithm + * searches for the first method on the source with a single parameter type matching an interface implemented by the + * target. + * + * @throws NoSuchMethodException + */ + @SuppressWarnings("unchecked") + public static Map<String, AtomicComponent> createWiredComponents(String source, + List<Class<?>> sourceInterfaces, + Class<?> sourceClass, + ScopeContainer sourceScopeContainer, + String target, + Class<?> targetClass, + ScopeContainer targetScopeContainer) + throws NoSuchMethodException { + + Map<String, AtomicComponent> contexts = new HashMap<String, AtomicComponent>(); + SystemAtomicComponent targetComponent = createAtomicComponent(target, targetScopeContainer, targetClass); + PojoConfiguration sourceConfig = new PojoConfiguration(); + sourceConfig.getServiceInterfaces().addAll(sourceInterfaces); + sourceConfig.setScopeContainer(sourceScopeContainer); + sourceConfig.setInstanceFactory(new PojoObjectFactory(sourceClass.getConstructor())); + + //create target wire + Method[] sourceMethods = sourceClass.getMethods(); + Class[] interfaces = targetClass.getInterfaces(); + Method setter = null; + for (Class interfaze : interfaces) { + for (Method method : sourceMethods) { + if (method.getParameterTypes().length == 1) { + if (interfaze.isAssignableFrom(method.getParameterTypes()[0])) { + setter = method; + } + } + Init init; + if ((init = method.getAnnotation(Init.class)) != null) { + sourceConfig.setInitLevel(init.eager() ? 50 : 0); + sourceConfig.setInitInvoker(new MethodEventInvoker<Object>(method)); + + } else if (method.getAnnotation(Destroy.class) != null) { + sourceConfig.setDestroyInvoker(new MethodEventInvoker<Object>(method)); + } + } + + } + if (setter == null) { + throw new IllegalArgumentException("No setter found on source for target"); + } + + sourceConfig.addReferenceSite(setter.getName(), setter); + SystemAtomicComponent sourceCtx = new SystemAtomicComponentImpl(source, sourceConfig); + QualifiedName targetName = new QualifiedName(target); + SystemOutboundWire wire = new SystemOutboundWireImpl(setter.getName(), targetName, targetClass); + InboundWire inboundWire = new SystemInboundWireImpl(targetName.getPortName(), targetClass, targetComponent); + wire.setTargetWire(inboundWire); + + sourceCtx.addOutboundWire(wire); + contexts.put(source, sourceCtx); + contexts.put(target, targetComponent); + return contexts; + } + + @SuppressWarnings("unchecked") + public static SystemAtomicComponent createAtomicComponent(String name, ScopeContainer container, Class<?> clazz) + throws NoSuchMethodException { + PojoConfiguration configuration = new PojoConfiguration(); + configuration.setScopeContainer(container); + configuration.addServiceInterface(clazz); + configuration.setInstanceFactory(new PojoObjectFactory(clazz.getConstructor())); + Method[] methods = clazz.getMethods(); + for (Method method : methods) { + Init init; + if ((init = method.getAnnotation(Init.class)) != null) { + configuration.setInitLevel(init.eager() ? 50 : 0); + configuration.setInitInvoker(new MethodEventInvoker<Object>(method)); + + } else if (method.getAnnotation(Destroy.class) != null) { + configuration.setDestroyInvoker(new MethodEventInvoker<Object>(method)); + } + } + return new SystemAtomicComponentImpl(name, configuration); + } + + public static <T> InboundWire createTargetWireFactory(String serviceName, Class<T> interfaze) + throws InvalidServiceContractException { + InboundWire wire = new InboundWireImpl(); + wire.setServiceName(serviceName); + JavaServiceContract contract = new JavaServiceContract(interfaze); + wire.setServiceContract(contract); + wire.addInvocationChains(createInboundChains(interfaze)); + return wire; + } + + public static Map<Operation<?>, InboundInvocationChain> createInboundChains(Class<?> interfaze) + throws InvalidServiceContractException { + JavaInterfaceProcessorRegistry registry = new JavaInterfaceProcessorRegistryImpl(); + Map<Operation<?>, InboundInvocationChain> invocations = new HashMap<Operation<?>, InboundInvocationChain>(); + ServiceContract<?> contract = registry.introspect(interfaze); + + for (Operation<?> operation : contract.getOperations().values()) { + InboundInvocationChain chain = new InboundInvocationChainImpl(operation); + // add tail interceptor + chain.addInterceptor(new InvokerInterceptor()); + invocations.put(operation, chain); + } + return invocations; + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/wire/MockStaticInvoker.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/wire/MockStaticInvoker.java new file mode 100644 index 0000000000..85afda9b08 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/wire/MockStaticInvoker.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.wire; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.InvocationRuntimeException; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.TargetInvoker; + +/** + * Caches component instances that do not need to be resolved for every wire, e.g. an wire originating from a lesser + * scope intended for a target with a wider scope + * + * @version $Rev$ $Date$ + */ +public class MockStaticInvoker implements TargetInvoker { + + private Object instance; + private Method operation; + private boolean cacheable; + + + public MockStaticInvoker(Method operation, Object instance) { + this.operation = operation; + this.instance = instance; + } + + public boolean isCacheable() { + return cacheable; + } + + public void setCacheable(boolean cacheable) { + this.cacheable = cacheable; + } + + public boolean isOptimizable() { + return isCacheable(); + } + + public Object invokeTarget(final Object payload) throws InvocationTargetException { + try { + if (payload != null && !payload.getClass().isArray()) { + return operation.invoke(instance, payload); + } else { + return operation.invoke(instance, (Object[]) payload); + } + } catch (IllegalAccessException e) { + throw new InvocationRuntimeException(e); + } + } + + public Message invoke(Message msg) throws InvocationRuntimeException { + try { + Object resp = invokeTarget(msg.getBody()); + msg.setBody(resp); + } catch (InvocationTargetException e) { + msg.setBodyWithFault(e.getCause()); + } catch (Throwable e) { + msg.setBodyWithFault(e); + } + return msg; + } + + public void setNext(Interceptor next) { + throw new IllegalStateException("This interceptor must be the last interceptor in an interceptor chain"); + } + + public Object clone() throws CloneNotSupportedException { + try { + MockStaticInvoker invoker = (MockStaticInvoker) super.clone(); + invoker.instance = this.instance; + invoker.operation = this.operation; + return invoker; + } catch (CloneNotSupportedException e) { + return null; // will not happen + } + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/wire/MockSyncInterceptor.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/wire/MockSyncInterceptor.java new file mode 100644 index 0000000000..1fe2c027ab --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/mock/wire/MockSyncInterceptor.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.mock.wire; + +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.Message; + +public class MockSyncInterceptor implements Interceptor { + + private int count; + + private Interceptor next; + + public MockSyncInterceptor() { + } + + public Message invoke(Message msg) { + ++count; + return next.invoke(msg); + } + + public int getCount() { + return count; + } + + public void setNext(Interceptor next) { + this.next = next; + } + + public Interceptor getNext() { + return next; + } + + public boolean isOptimizable() { + return false; + } + +} + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/monitor/JavaLoggingTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/monitor/JavaLoggingTestCase.java new file mode 100644 index 0000000000..ee452d34fa --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/monitor/JavaLoggingTestCase.java @@ -0,0 +1,165 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.monitor; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +import org.apache.tuscany.api.annotation.LogLevel; +import org.apache.tuscany.host.MonitorFactory; + +import junit.framework.TestCase; + +/** + * Test case for the JavaLoggingMonitorFactory. + * + * @version $Rev$ $Date$ + */ +public class JavaLoggingTestCase extends TestCase { + private static final Logger LOGGER = Logger.getLogger(Monitor.class.getName()); + private static final MockHandler HANDLER = new MockHandler(); + + private MonitorFactory factory; + + /** + * Smoke test to ensure the LOGGER is working. + */ + public void testLogger() { + LOGGER.info("test"); + assertEquals(1, HANDLER.logs.size()); + } + + /** + * Test that no record is logged. + */ + public void testUnloggedEvent() { + Monitor mon = factory.getMonitor(Monitor.class); + mon.eventNotToLog(); + assertEquals(0, HANDLER.logs.size()); + } + + /** + * Test the correct record is written for an event with no arguments. + */ + public void testEventWithNoArgs() { + Monitor mon = factory.getMonitor(Monitor.class); + mon.eventWithNoArgs(); + assertEquals(1, HANDLER.logs.size()); + LogRecord record = HANDLER.logs.get(0); + assertEquals(Level.INFO, record.getLevel()); + assertEquals(LOGGER.getName(), record.getLoggerName()); + assertEquals(Monitor.class.getName() + "#eventWithNoArgs", record.getMessage()); + } + + /** + * Test the correct record is written for an event defined by annotation. + */ + public void testEventWithAnnotation() { + Monitor mon = factory.getMonitor(Monitor.class); + mon.eventWithAnnotation(); + assertEquals(1, HANDLER.logs.size()); + LogRecord record = HANDLER.logs.get(0); + assertEquals(Level.INFO, record.getLevel()); + assertEquals(LOGGER.getName(), record.getLoggerName()); + assertEquals(Monitor.class.getName() + "#eventWithAnnotation", record.getMessage()); + } + + /** + * Test a Throwable is logged when passed to an event. + */ + public void testEventWithThrowable() { + Exception e = new Exception(); + Monitor mon = factory.getMonitor(Monitor.class); + mon.eventWithThrowable(e); + assertEquals(1, HANDLER.logs.size()); + LogRecord record = HANDLER.logs.get(0); + assertEquals(Level.WARNING, record.getLevel()); + assertEquals(LOGGER.getName(), record.getLoggerName()); + assertEquals(Monitor.class.getName() + "#eventWithThrowable", record.getMessage()); + assertSame(e, record.getThrown()); + } + + /** + * Test the argument is logged. + */ + public void testEventWithOneArg() { + Monitor mon = factory.getMonitor(Monitor.class); + mon.eventWithOneArg("ARG"); + assertEquals(1, HANDLER.logs.size()); + LogRecord record = HANDLER.logs.get(0); + assertEquals(Monitor.class.getName() + "#eventWithOneArg", record.getMessage()); + } + + protected void setUp() throws Exception { + super.setUp(); + LOGGER.setUseParentHandlers(false); + LOGGER.addHandler(HANDLER); + HANDLER.flush(); + + String sourceClass = Monitor.class.getName(); + Properties levels = new Properties(); + levels.setProperty(sourceClass + "#eventWithNoArgs", "INFO"); + levels.setProperty(sourceClass + "#eventWithOneArg", "INFO"); + levels.setProperty(sourceClass + "#eventWithThrowable", "WARNING"); + factory = new JavaLoggingMonitorFactory(levels, Level.FINE, "TestMessages"); + } + + protected void tearDown() throws Exception { + LOGGER.removeHandler(HANDLER); + HANDLER.flush(); + super.tearDown(); + } + + /** + * Mock log HANDLER to capture records. + */ + public static class MockHandler extends Handler { + List<LogRecord> logs = new ArrayList<LogRecord>(); + + public void publish(LogRecord record) { + logs.add(record); + } + + public void flush() { + logs.clear(); + } + + public void close() throws SecurityException { + } + } + + @SuppressWarnings({"JavaDoc"}) + public static interface Monitor { + void eventNotToLog(); + + void eventWithNoArgs(); + + void eventWithOneArg(String msg); + + void eventWithThrowable(Exception e); + + @LogLevel("INFO") + void eventWithAnnotation(); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/property/PropertyHelperTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/property/PropertyHelperTestCase.java new file mode 100644 index 0000000000..4f2e2fbf42 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/property/PropertyHelperTestCase.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.tuscany.core.property; + +import java.net.URL; +import javax.xml.namespace.NamespaceContext; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import org.apache.tuscany.spi.deployer.DeploymentContext; + +import junit.framework.TestCase; +import org.apache.tuscany.core.databinding.xml.String2Node; +import org.easymock.EasyMock; + +/** + * + */ +public class PropertyHelperTestCase extends TestCase { + private static final String IPO_XML = + "<?xml version=\"1.0\"?>" + "<ipo:purchaseOrder" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + + " xmlns:ipo=\"http://www.example.com/IPO\"" + + " xsi:schemaLocation=\"http://www.example.com/IPO ipo.xsd\"" + + " orderDate=\"1999-12-01\">" + + " <shipTo exportCode=\"1\" xsi:type=\"ipo:UKAddress\">" + + " <name>Helen Zoe</name>" + + " <street>47 Eden Street</street>" + + " <city>Cambridge</city>" + + " <postcode>CB1 1JR</postcode>" + + " </shipTo>" + + " <billTo xsi:type=\"ipo:USAddress\">" + + " <name>Robert Smith</name>" + + " <street>8 Oak Avenue</street>" + + " <city>Old Town</city>" + + " <state>PA</state>" + + " <zip>95819</zip>" + + " </billTo>" + + " <items>" + + " <item partNum=\"833-AA\">" + + " <productName>Lapis necklace</productName>" + + " <quantity>1</quantity>" + + " <USPrice>99.95</USPrice>" + + " <ipo:comment>Want this for the holidays</ipo:comment>" + + " <shipDate>1999-12-05</shipDate>" + + " </item>" + + " </items>" + + "</ipo:purchaseOrder>"; + + /** + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception { + super.setUp(); + } + + public void testXPath() throws Exception { + String2Node t = new String2Node(); + Node node = t.transform(IPO_XML, null); + + Document doc = PropertyHelper.evaluate(null, node, "/ipo:purchaseOrder/billTo"); + assertNotNull(doc); + + NamespaceContext context = EasyMock.createMock(NamespaceContext.class); + EasyMock.expect(context.getNamespaceURI("ipo")).andReturn("http://www.example.com/IPO").anyTimes(); + EasyMock.replay(context); + doc = PropertyHelper.evaluate(context, node, "/ipo:purchaseOrder/items"); + assertNotNull(doc); + doc = PropertyHelper.evaluate(context, node, "/ipo:purchaseOrder/billTo"); + assertNotNull(doc); + doc = PropertyHelper.evaluate(context, node, "/"); + assertNotNull(doc); + doc = PropertyHelper.evaluate(context, node, "/ipo:purchaseOrder/billTo1"); + assertNull(doc); + } + + public void testFile() throws Exception { + URL url = getClass().getResource("ipo.xml"); + Document doc = PropertyHelper.loadFromFile(url.toExternalForm(), null); + assertNotNull(doc); + + DeploymentContext context = EasyMock.createMock(DeploymentContext.class); + EasyMock.expect(context.getClassLoader()).andReturn(getClass().getClassLoader()); + EasyMock.replay(context); + doc = PropertyHelper.loadFromFile("org/apache/tuscany/core/property/ipo.xml", context); + assertNotNull(doc); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/property/SimplePropertyObjectFactoryTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/property/SimplePropertyObjectFactoryTestCase.java new file mode 100644 index 0000000000..9ef1faccfe --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/property/SimplePropertyObjectFactoryTestCase.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.property; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.apache.tuscany.spi.ObjectFactory; +import org.apache.tuscany.spi.model.Property; +import org.apache.tuscany.spi.model.PropertyValue; + +import junit.framework.TestCase; +import org.easymock.EasyMock; + +/** + * @version $Rev$ $Date$ + */ +public class SimplePropertyObjectFactoryTestCase extends TestCase { + + private <T> PropertyValue<T> mock(String value) { + Document document = EasyMock.createMock(Document.class); + Element element = EasyMock.createMock(Element.class); + EasyMock.expect(document.getDocumentElement()).andReturn(element); + EasyMock.expect(element.getTextContent()).andReturn(value); + EasyMock.replay(document, element); + return new PropertyValue<T>(null, document); + } + + public void testInteger() throws Exception { + + PropertyObjectFactoryImpl factory = new PropertyObjectFactoryImpl(); + Property<Integer> property = new Property<Integer>(); + property.setJavaType(Integer.class); + PropertyValue<Integer> propertyValue = mock("1"); + ObjectFactory<Integer> oFactory = factory.createObjectFactory(property, propertyValue); + assertEquals(1, oFactory.getInstance().intValue()); + } + + public void testPrimitiveInt() throws Exception { + PropertyObjectFactoryImpl factory = new PropertyObjectFactoryImpl(); + Property<Integer> property = new Property<Integer>(); + property.setJavaType(Integer.TYPE); + PropertyValue<Integer> propertyValue = mock("1"); + ObjectFactory<Integer> oFactory = factory.createObjectFactory(property, propertyValue); + assertEquals(1, oFactory.getInstance().intValue()); + } + + public void testString() throws Exception { + PropertyObjectFactoryImpl factory = new PropertyObjectFactoryImpl(); + Property<String> property = new Property<String>(); + property.setJavaType(String.class); + PropertyValue<String> propertyValue = mock("1"); + ObjectFactory<String> oFactory = factory.createObjectFactory(property, propertyValue); + assertEquals("1", oFactory.getInstance()); + } + + public void testByteArray() throws Exception { + PropertyObjectFactoryImpl factory = new PropertyObjectFactoryImpl(); + Property<byte[]> property = new Property<byte[]>(); + property.setJavaType(byte[].class); + PropertyValue<byte[]> propertyValue = mock("TWFu"); // BASE64 for "Man" + ObjectFactory<byte[]> oFactory = factory.createObjectFactory(property, propertyValue); + byte[] result = oFactory.getInstance(); + byte[] expected = "Man".getBytes(); + for (int i = 0; i < result.length; i++) { + byte b = result[i]; + if (b != expected[i]) { + fail(); + } + } + } + + public void testBoolean() throws Exception { + PropertyObjectFactoryImpl factory = new PropertyObjectFactoryImpl(); + Property<Boolean> property = new Property<Boolean>(); + property.setJavaType(Boolean.class); + PropertyValue<Boolean> propertyValue = mock("true"); + ObjectFactory<Boolean> oFactory = factory.createObjectFactory(property, propertyValue); + assertTrue(oFactory.getInstance()); + } + + public void testPrimitiveBoolean() throws Exception { + PropertyObjectFactoryImpl factory = new PropertyObjectFactoryImpl(); + Property<Boolean> property = new Property<Boolean>(); + property.setJavaType(Boolean.TYPE); + PropertyValue<Boolean> propertyValue = mock("true"); + ObjectFactory<Boolean> oFactory = factory.createObjectFactory(property, propertyValue); + assertTrue(oFactory.getInstance()); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/services/artifact/LocalMavenRepositoryTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/services/artifact/LocalMavenRepositoryTestCase.java new file mode 100644 index 0000000000..0efecb9302 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/services/artifact/LocalMavenRepositoryTestCase.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.core.services.artifact; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; + +import junit.framework.TestCase; + +import org.apache.tuscany.spi.services.artifact.Artifact; + +/** + * This testcase assumes that there is a maven repo in the default location. + * + * @version $Rev$ $Date$ + */ +public class LocalMavenRepositoryTestCase extends TestCase { + private static final String VERSION = "3.8.1"; + private LocalMavenRepository repo; + private Artifact artifact; + private String path; + + public void testPathWithNoClassifier() { + assertEquals(path, repo.getPath(artifact)); + } + + public void testPathWithClassifier() { + artifact.setClassifier("x86"); + path = "junit/junit/" + VERSION + "/junit-" + VERSION + "-x86.jar"; + assertEquals(path, repo.getPath(artifact)); + } + + public void testArtifactFoundInRepo() throws MalformedURLException, UnsupportedEncodingException { + String home = System.getProperty("user.home"); + File file = new File(home + "/.m2/repository", path); + repo.resolve(artifact); + assertEquals(file.toURI().toURL(), artifact.getUrl()); + } + + public void testArtifactNotFoundInRepo() throws MalformedURLException { + artifact.setClassifier("x86"); + repo.resolve(artifact); + assertNull(artifact.getUrl()); + } + + public void testNonNullURLIsUnmodified() throws MalformedURLException { + URL url = new URL("http://www.apache.org"); + artifact.setUrl(url); + repo.resolve(artifact); + assertSame(url, artifact.getUrl()); + } + + protected void setUp() throws Exception { + super.setUp(); + repo = new LocalMavenRepository(".m2/repository"); + + artifact = new Artifact(); + artifact.setGroup("junit"); + artifact.setName("junit"); + artifact.setVersion(VERSION); + artifact.setType("jar"); + path = "junit/junit/" + VERSION + "/junit-" + VERSION + ".jar"; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkSchedulerTest.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkSchedulerTest.java new file mode 100644 index 0000000000..1a5cb4ebe1 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkSchedulerTest.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.work.jsr237; + +import org.apache.tuscany.spi.services.work.NotificationListener; +import org.apache.tuscany.spi.services.work.WorkScheduler; + +import commonj.work.WorkManager; +import junit.framework.TestCase; +import org.apache.tuscany.core.services.work.jsr237.workmanager.ThreadPoolWorkManager; + +public class Jsr237WorkSchedulerTest extends TestCase { + + /* + * Test method for 'org.apache.tuscany.core.services.work.jsr237.Jsr237WorkScheduler.scheduleWork(T) <T>' + */ + public void testScheduleWorkT() { + + + WorkManager workManager = new ThreadPoolWorkManager(1); + WorkScheduler workScheduler = new Jsr237WorkScheduler(workManager); + + workScheduler.scheduleWork(new MyRunnable(), new MyNotificationListener()); + + } + + /* + * Test method for 'org.apache.tuscany.core.services.work.jsr237.Jsr237WorkScheduler.scheduleWork(T, + * NotificationListener<T>) <T>' + */ + public void testScheduleWorkTNotificationListenerOfT() { + + } + + private class MyRunnable implements Runnable { + public void run() { + System.err.println("Test executed"); + } + } + + private class MyNotificationListener implements NotificationListener<MyRunnable> { + + public void workAccepted(MyRunnable work) { + System.err.println("Work accepted"); + } + + public void workCompleted(MyRunnable work) { + System.err.println("Work completed"); + } + + public void workStarted(MyRunnable work) { + System.err.println("Work started"); + } + + public void workRejected(MyRunnable work) { + System.err.println("Work rejected"); + } + + public void workFailed(MyRunnable work, Throwable error) { + System.err.println("Work failed"); + } + + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkSchedulerTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkSchedulerTestCase.java new file mode 100644 index 0000000000..3966f65683 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/services/work/jsr237/Jsr237WorkSchedulerTestCase.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.work.jsr237; + +import org.apache.tuscany.spi.services.work.NotificationListener; +import org.apache.tuscany.spi.services.work.WorkSchedulerException; + +import commonj.work.Work; +import commonj.work.WorkItem; +import commonj.work.WorkListener; +import commonj.work.WorkManager; +import commonj.work.WorkRejectedException; +import junit.framework.TestCase; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +/** + * @version $Rev$ $Date$ + */ +public class Jsr237WorkSchedulerTestCase extends TestCase { + + public void testSchedule() throws Exception { + WorkItem item = createMock(WorkItem.class); + WorkManager mgr = createMock(WorkManager.class); + mgr.schedule(isA(Work.class)); + expectLastCall().andReturn(item); + replay(mgr); + Jsr237WorkScheduler scheduler = new Jsr237WorkScheduler(mgr); + Work work = createMock(Work.class); + scheduler.scheduleWork(work); + verify(mgr); + } + + @SuppressWarnings("unchecked") + public void testListener() throws Exception { + WorkItem item = createMock(WorkItem.class); + WorkManager mgr = createMock(WorkManager.class); + mgr.schedule(isA(Work.class), isA(WorkListener.class)); + expectLastCall().andReturn(item); + replay(mgr); + Jsr237WorkScheduler scheduler = new Jsr237WorkScheduler(mgr); + Work work = createMock(Work.class); + NotificationListener<Runnable> listener = createMock(NotificationListener.class); + scheduler.scheduleWork(work, listener); + verify(mgr); + } + + @SuppressWarnings("unchecked") + public void testWorkRejectedListener() throws Exception { + WorkManager mgr = createMock(WorkManager.class); + mgr.schedule(isA(Work.class), isA(WorkListener.class)); + expectLastCall().andThrow(new WorkRejectedException()); + replay(mgr); + Jsr237WorkScheduler scheduler = new Jsr237WorkScheduler(mgr); + Work work = createMock(Work.class); + NotificationListener<Runnable> listener = createMock(NotificationListener.class); + listener.workRejected(isA(Runnable.class)); + expectLastCall(); + replay(listener); + scheduler.scheduleWork(work, listener); + verify(mgr); + } + + @SuppressWarnings("unchecked") + public void testWorkRejectedNoListener() throws Exception { + WorkManager mgr = createMock(WorkManager.class); + mgr.schedule(isA(Work.class)); + expectLastCall().andThrow(new WorkRejectedException()); + replay(mgr); + Jsr237WorkScheduler scheduler = new Jsr237WorkScheduler(mgr); + Work work = createMock(Work.class); + try { + scheduler.scheduleWork(work); + fail(); + } catch (WorkSchedulerException e) { + // expected + } + verify(mgr); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/services/work/jsr237/workmanager/ThreadPoolWorkManagerTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/services/work/jsr237/workmanager/ThreadPoolWorkManagerTestCase.java new file mode 100644 index 0000000000..33ecd66fdc --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/services/work/jsr237/workmanager/ThreadPoolWorkManagerTestCase.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.services.work.jsr237.workmanager; + +import java.util.concurrent.CountDownLatch; + +import commonj.work.Work; +import commonj.work.WorkEvent; +import commonj.work.WorkListener; +import junit.framework.TestCase; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.createStrictMock; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import org.easymock.IAnswer; + +/** + * @version $Rev$ $Date$ + */ +public class ThreadPoolWorkManagerTestCase extends TestCase { + + public void testSchedule() throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + Work work = createMock(Work.class); + work.run(); + expectLastCall().andStubAnswer(new IAnswer<Object>() { + public Object answer() throws Throwable { + latch.countDown(); + return null; + } + }); + replay(work); + ThreadPoolWorkManager mgr = new ThreadPoolWorkManager(1); + mgr.schedule(work); + latch.await(); + verify(work); + } + + public void testListener() throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + WorkListener listener = createStrictMock(WorkListener.class); + listener.workAccepted(isA(WorkEvent.class)); + listener.workStarted(isA(WorkEvent.class)); + listener.workCompleted(isA(WorkEvent.class)); + expectLastCall(); + replay(listener); + Work work = createMock(Work.class); + work.run(); + expectLastCall().andStubAnswer(new IAnswer<Object>() { + public Object answer() throws Throwable { + latch.countDown(); + return null; + } + }); + replay(work); + ThreadPoolWorkManager mgr = new ThreadPoolWorkManager(1); + mgr.schedule(work, listener); + latch.await(); + verify(work); + } + + public void testDelayListener() throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + final CountDownLatch latch2 = new CountDownLatch(1); + WorkListener listener = createStrictMock(WorkListener.class); + listener.workAccepted(isA(WorkEvent.class)); + listener.workStarted(isA(WorkEvent.class)); + listener.workCompleted(isA(WorkEvent.class)); + expectLastCall().andStubAnswer(new IAnswer<Object>() { + public Object answer() throws Throwable { + latch2.countDown(); + return null; + } + }); + replay(listener); + Work work = createMock(Work.class); + work.run(); + expectLastCall().andStubAnswer(new IAnswer<Object>() { + public Object answer() throws Throwable { + latch.await(); + return null; + } + }); + replay(work); + ThreadPoolWorkManager mgr = new ThreadPoolWorkManager(1); + mgr.schedule(work, listener); + latch.countDown(); + verify(work); + } + + public void testErrorListener() throws Exception { + final CountDownLatch latch = new CountDownLatch(1); + WorkListener listener = createStrictMock(WorkListener.class); + listener.workAccepted(isA(WorkEvent.class)); + listener.workStarted(isA(WorkEvent.class)); + listener.workCompleted(isA(WorkEvent.class)); + replay(listener); + Work work = createMock(Work.class); + work.run(); + expectLastCall().andStubAnswer(new IAnswer<Object>() { + public Object answer() throws Throwable { + latch.countDown(); + throw new RuntimeException(); + } + }); + replay(work); + ThreadPoolWorkManager mgr = new ThreadPoolWorkManager(1); + mgr.schedule(work, listener); + latch.await(); + verify(work); + } + +} + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/util/Bean1.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/util/Bean1.java new file mode 100644 index 0000000000..79fad549aa --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/util/Bean1.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.core.util; + + +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) { + } + + public void override(String param) throws Exception { + } + + + public void noOverride(String param) throws Exception { + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/util/Bean2.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/util/Bean2.java new file mode 100644 index 0000000000..7f7f03da9e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/util/Bean2.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.core.util; + +import java.util.List; + +import junit.framework.AssertionFailedError; + +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 AssertionFailedError("setter inadvertantly called"); + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/util/JavaIntrospectionHelperTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/util/JavaIntrospectionHelperTestCase.java new file mode 100644 index 0000000000..797b147b54 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/util/JavaIntrospectionHelperTestCase.java @@ -0,0 +1,180 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.util; + +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 junit.framework.TestCase; +import org.apache.tuscany.core.mock.component.Target; + +public class JavaIntrospectionHelperTestCase extends TestCase { + + private List testNoGenericsList; + private List<String> testList; + private Map<String, Bean1> testMap; + private Target[] testArray; + private String[] testStringArray; + + public JavaIntrospectionHelperTestCase() { + super(); + } + + public JavaIntrospectionHelperTestCase(String arg0) { + super(arg0); + } + + public void testBean1AllPublicProtectedFields() throws Exception { + Set<Field> beanFields = JavaIntrospectionHelper.getAllPublicAndProtectedFields(Bean1.class); + assertEquals(4, beanFields.size()); //Bean1.ALL_BEAN1_PUBLIC_PROTECTED_FIELDS + } + + public void testGetSuperAllMethods() throws Exception { + Set<Method> superBeanMethods = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(SuperBean.class); + assertEquals(SuperBean.ALL_SUPER_METHODS, superBeanMethods.size()); + } + + public void testGetBean1AllMethods() throws Exception { + Set<Method> beanMethods = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(Bean1.class); + assertEquals(Bean1.ALL_BEAN1_METHODS, beanMethods.size()); + } + + public void testOverrideMethod() throws Exception { + Set<Method> beanFields = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(Bean1.class); + 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"); + } + } + + public void testNoOverrideMethod() throws Exception { + Set<Method> beanFields = JavaIntrospectionHelper.getAllUniquePublicProtectedMethods(Bean1.class); + 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"); + } + } + + public void testDefaultConstructor() throws Exception { + Constructor ctr = JavaIntrospectionHelper.getDefaultConstructor(Bean2.class); + assertEquals(ctr, Bean2.class.getConstructor()); + assertTrue(Bean2.class == ctr.newInstance((Object[]) null).getClass()); + } + + + public void testGetAllInterfaces() { + Set<Class> interfaces = JavaIntrospectionHelper.getAllInterfaces(Z.class); + assertEquals(2, interfaces.size()); + assertTrue(interfaces.contains(W.class)); + assertTrue(interfaces.contains(W2.class)); + } + + + public void testGetAllInterfacesObject() { + Set<Class> interfaces = JavaIntrospectionHelper.getAllInterfaces(Object.class); + assertEquals(0, interfaces.size()); + } + + public void testGetAllInterfacesNoInterfaces() { + Set<Class> interfaces = JavaIntrospectionHelper.getAllInterfaces(NoInterface.class); + assertEquals(0, interfaces.size()); + } + + /** + * Tests generics introspection capabilities + */ + 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(Target[] 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-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/util/SuperBean.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/util/SuperBean.java new file mode 100644 index 0000000000..83aef7fb5e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/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.core.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 { + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/BasicReferenceInvocationHandlerTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/BasicReferenceInvocationHandlerTestCase.java new file mode 100644 index 0000000000..fe7469c998 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/BasicReferenceInvocationHandlerTestCase.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import java.lang.reflect.Method; + +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; + +import junit.framework.TestCase; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.mock.component.SimpleTarget; +import org.apache.tuscany.core.mock.component.SimpleTargetImpl; +import org.apache.tuscany.core.mock.wire.MockStaticInvoker; +import org.apache.tuscany.core.mock.wire.MockSyncInterceptor; +import org.apache.tuscany.core.wire.jdk.JDKOutboundInvocationHandler; + +/** + * @version $$Rev$$ $$Date$$ + */ +public class BasicReferenceInvocationHandlerTestCase extends TestCase { + + private Method echo; + + public void testInterceptorInvoke() throws Throwable { + JavaInterfaceProcessorRegistry registry = new JavaInterfaceProcessorRegistryImpl(); + ServiceContract<?> contract = registry.introspect(SimpleTarget.class); + Operation<?> operation = contract.getOperations().get("echo"); + MockStaticInvoker invoker = new MockStaticInvoker(echo, new SimpleTargetImpl()); + OutboundInvocationChain chain = new OutboundInvocationChainImpl(operation); + MockSyncInterceptor interceptor = new MockSyncInterceptor(); + chain.addInterceptor(interceptor); + chain.setTargetInterceptor(new InvokerInterceptor()); + chain.setTargetInvoker(invoker); + chain.prepare(); + //chains.put(echo, chain); + OutboundWire wire = new OutboundWireImpl(); + wire.addInvocationChain(operation, chain); + wire.setServiceContract(contract); + JDKOutboundInvocationHandler handler = new JDKOutboundInvocationHandler(wire, new WorkContextImpl()); + assertEquals("foo", handler.invoke(null, echo, new String[]{"foo"})); + assertEquals(1, interceptor.getCount()); + } + + public void setUp() throws Exception { + super.setUp(); + echo = SimpleTarget.class.getMethod("echo", String.class); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/InboundInvocationErrorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/InboundInvocationErrorTestCase.java new file mode 100644 index 0000000000..79abec4904 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/InboundInvocationErrorTestCase.java @@ -0,0 +1,150 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; + +import junit.framework.TestCase; + +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.mock.wire.MockStaticInvoker; +import org.apache.tuscany.core.mock.wire.MockSyncInterceptor; +import org.apache.tuscany.core.wire.jdk.JDKInboundInvocationHandler; +import org.easymock.classextension.EasyMock; + +/** + * Tests handling of exceptions thrown during an inbound wire invocation + * + * @version $Rev$ $Date$ + */ +public class InboundInvocationErrorTestCase extends TestCase { + + private Method checkedMethod; + private Method runtimeMethod; + private Operation checkedOperation; + private Operation runtimeOperation; + + public InboundInvocationErrorTestCase() { + super(); + } + + public InboundInvocationErrorTestCase(String arg0) { + super(arg0); + } + + public void setUp() throws Exception { + super.setUp(); + checkedMethod = + TestBean.class.getDeclaredMethod("checkedException", (Class[]) null); + runtimeMethod = + TestBean.class.getDeclaredMethod("runtimeException", (Class[]) null); + assertNotNull(checkedMethod); + assertNotNull(runtimeMethod); + JavaInterfaceProcessorRegistry registry = new JavaInterfaceProcessorRegistryImpl(); + ServiceContract<?> contract; + try { + contract = registry.introspect(TestBean.class); + } catch (InvalidServiceContractException e) { + throw new AssertionError(); + } + + checkedOperation = contract.getOperations().get("checkedException"); + runtimeOperation = contract.getOperations().get("runtimeException"); + } + + public void testCheckedException() throws Exception { + Map<Method, InboundInvocationChain> chains = new HashMap<Method, InboundInvocationChain>(); + chains.put(checkedMethod, createChain(checkedMethod, checkedOperation)); + WorkContext workContext = EasyMock.createNiceMock(WorkContext.class); + EasyMock.replay(workContext); + JDKInboundInvocationHandler handler = new JDKInboundInvocationHandler(chains, workContext); + try { + InboundInvocationErrorTestCase.TestBean proxy = (InboundInvocationErrorTestCase.TestBean) Proxy + .newProxyInstance(Thread.currentThread().getContextClassLoader(), + new Class[]{InboundInvocationErrorTestCase.TestBean.class}, handler); + proxy.checkedException(); + } catch (InboundInvocationErrorTestCase.TestException e) { + return; + } + fail(InboundInvocationErrorTestCase.TestException.class.getName() + " should have been thrown"); + } + + public void testRuntimeException() throws Exception { + Map<Method, InboundInvocationChain> chains = new HashMap<Method, InboundInvocationChain>(); + chains.put(runtimeMethod, createChain(runtimeMethod, runtimeOperation)); + WorkContext workContext = EasyMock.createNiceMock(WorkContext.class); + EasyMock.replay(workContext); + JDKInboundInvocationHandler handler = new JDKInboundInvocationHandler(chains, workContext); + try { + InboundInvocationErrorTestCase.TestBean proxy = (InboundInvocationErrorTestCase.TestBean) Proxy + .newProxyInstance(Thread.currentThread().getContextClassLoader(), + new Class[]{InboundInvocationErrorTestCase.TestBean.class}, handler); + proxy.runtimeException(); + } catch (InboundInvocationErrorTestCase.TestRuntimeException e) { + return; + } + fail(InboundInvocationErrorTestCase.TestException.class.getName() + " should have been thrown"); + } + + private InboundInvocationChain createChain(Method m, Operation operation) { + MockStaticInvoker invoker = new MockStaticInvoker(m, new InboundInvocationErrorTestCase.TestBeanImpl()); + InboundInvocationChain chain = new InboundInvocationChainImpl(operation); + chain.addInterceptor(new MockSyncInterceptor()); + chain.setTargetInvoker(invoker); + chain.addInterceptor(new InvokerInterceptor()); + chain.prepare(); + return chain; + } + + public interface TestBean { + + void checkedException() throws InboundInvocationErrorTestCase.TestException; + + void runtimeException() throws InboundInvocationErrorTestCase.TestRuntimeException; + + } + + public class TestBeanImpl implements InboundInvocationErrorTestCase.TestBean { + + public void checkedException() throws InboundInvocationErrorTestCase.TestException { + throw new InboundInvocationErrorTestCase.TestException(); + } + + public void runtimeException() throws InboundInvocationErrorTestCase.TestRuntimeException { + throw new InboundInvocationErrorTestCase.TestRuntimeException(); + } + } + + public class TestException extends Exception { + } + + public class TestRuntimeException extends RuntimeException { + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/InvocationChainImplTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/InvocationChainImplTestCase.java new file mode 100644 index 0000000000..294e98997f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/InvocationChainImplTestCase.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import java.lang.reflect.Type; + +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.Message; + +import junit.framework.TestCase; + +/** + * @version $Rev$ $Date$ + */ +public class InvocationChainImplTestCase extends TestCase { + + public void testInsertAtPos() throws Exception { + MockChain chain = new MockChain(new Operation<Type>("foo", null, null, null)); + Interceptor inter3 = new MockInterceptor(); + Interceptor inter2 = new MockInterceptor(); + Interceptor inter1 = new MockInterceptor(); + chain.addInterceptor(inter3); + chain.addInterceptor(0, inter1); + chain.addInterceptor(1, inter2); + Interceptor head = chain.getHeadInterceptor(); + assertEquals(inter1, head); + assertEquals(inter2, head.getNext()); + assertEquals(inter3, head.getNext().getNext()); + } + + public void testInsertAtEnd() throws Exception { + MockChain chain = new MockChain(new Operation<Type>("foo", null, null, null)); + Interceptor inter2 = new MockInterceptor(); + Interceptor inter1 = new MockInterceptor(); + chain.addInterceptor(0, inter1); + chain.addInterceptor(1, inter2); + Interceptor head = chain.getHeadInterceptor(); + assertEquals(inter1, head); + assertEquals(inter2, head.getNext()); + assertEquals(inter2, chain.getTailInterceptor()); + + } + + private class MockChain extends InvocationChainImpl { + + public MockChain(Operation operation) { + super(operation); + } + + public void prepare() { + + } + } + + private class MockInterceptor implements Interceptor { + + private Interceptor next; + + public Message invoke(Message msg) { + return null; + } + + public void setNext(Interceptor next) { + this.next = next; + } + + public Interceptor getNext() { + return next; + } + + public boolean isOptimizable() { + return false; + } + } + + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/InvocationConfigurationErrorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/InvocationConfigurationErrorTestCase.java new file mode 100644 index 0000000000..aca68a0f25 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/InvocationConfigurationErrorTestCase.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import java.lang.reflect.Method; + +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.MessageImpl; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.mock.component.SimpleTarget; +import org.apache.tuscany.core.mock.component.SimpleTargetImpl; +import org.apache.tuscany.core.mock.wire.MockStaticInvoker; +import org.apache.tuscany.core.mock.wire.MockSyncInterceptor; + +/** + * Tests error propagation through an innvocation + * + * @version $Rev$ $Date$ + */ +public class InvocationConfigurationErrorTestCase extends TestCase { + + private ServiceContract<?> contract; + private Method hello; + + public InvocationConfigurationErrorTestCase() { + super(); + } + + public InvocationConfigurationErrorTestCase(String arg0) { + super(arg0); + } + + public void setUp() throws Exception { + super.setUp(); + JavaInterfaceProcessorRegistry registry = new JavaInterfaceProcessorRegistryImpl(); + contract = registry.introspect(SimpleTarget.class); + hello = SimpleTarget.class.getMethod("hello", String.class); + } + + /** + * Tests basic wiring of a source to a target, including handlers and interceptors + */ + public void testInvokeWithInterceptors() throws Exception { + Operation operation = contract.getOperations().get("hello"); + OutboundInvocationChain source = new OutboundInvocationChainImpl(operation); + MockSyncInterceptor sourceInterceptor = new MockSyncInterceptor(); + source.addInterceptor(sourceInterceptor); + + InboundInvocationChain target = new InboundInvocationChainImpl(operation); + MockSyncInterceptor targetInterceptor = new MockSyncInterceptor(); + target.addInterceptor(targetInterceptor); + target.addInterceptor(new InvokerInterceptor()); + + // connect the source to the target + source.setTargetInterceptor(target.getHeadInterceptor()); + source.prepare(); + target.prepare(); + MockStaticInvoker invoker = new MockStaticInvoker(hello, new SimpleTargetImpl()); + source.setTargetInvoker(invoker); + + Message msg = new MessageImpl(); + msg.setTargetInvoker(invoker); + Message response = source.getHeadInterceptor().invoke(msg); + assertTrue(response.isFault()); + assertTrue(response.getBody() instanceof IllegalArgumentException); + assertEquals(1, sourceInterceptor.getCount()); + assertEquals(1, targetInterceptor.getCount()); + + } + +} + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/InvocationConfigurationTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/InvocationConfigurationTestCase.java new file mode 100644 index 0000000000..62df732a9e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/InvocationConfigurationTestCase.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import java.lang.reflect.Method; + +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.MessageImpl; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; + +import junit.framework.TestCase; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.mock.component.SimpleTarget; +import org.apache.tuscany.core.mock.component.SimpleTargetImpl; +import org.apache.tuscany.core.mock.wire.MockStaticInvoker; +import org.apache.tuscany.core.mock.wire.MockSyncInterceptor; + +public class InvocationConfigurationTestCase extends TestCase { + + private Method hello; + private Operation operation; + + + public InvocationConfigurationTestCase() { + super(); + } + + public InvocationConfigurationTestCase(String arg0) { + super(arg0); + } + + public void setUp() throws Exception { + super.setUp(); + JavaInterfaceProcessorRegistry registry = new JavaInterfaceProcessorRegistryImpl(); + ServiceContract<?> contract; + try { + contract = registry.introspect(SimpleTarget.class); + } catch (InvalidServiceContractException e) { + throw new AssertionError(); + } + + operation = contract.getOperations().get("echo"); + hello = SimpleTarget.class.getMethod("hello", String.class); + } + + /** + * Tests basic wiring of a source to a target, including handlers and interceptors + */ + public void testInvokeWithInterceptors() throws Exception { + OutboundInvocationChain source = new OutboundInvocationChainImpl(operation); + MockSyncInterceptor sourceInterceptor = new MockSyncInterceptor(); + source.addInterceptor(sourceInterceptor); + + InboundInvocationChain target = new InboundInvocationChainImpl(operation); + MockSyncInterceptor targetInterceptor = new MockSyncInterceptor(); + target.addInterceptor(targetInterceptor); + target.addInterceptor(new InvokerInterceptor()); + + // connect the source to the target + source.setTargetInterceptor(target.getHeadInterceptor()); + source.prepare(); + target.prepare(); + MockStaticInvoker invoker = new MockStaticInvoker(hello, new SimpleTargetImpl()); + source.setTargetInvoker(invoker); + + Message msg = new MessageImpl(); + msg.setBody("foo"); + msg.setTargetInvoker(invoker); + Message response = source.getHeadInterceptor().invoke(msg); + assertEquals("foo", response.getBody()); + assertEquals(1, sourceInterceptor.getCount()); + assertEquals(1, targetInterceptor.getCount()); + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/MediationTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/MediationTestCase.java new file mode 100644 index 0000000000..a81e955a20 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/MediationTestCase.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.core.wire; + +import java.lang.reflect.Method; + +import junit.framework.Assert; +import junit.framework.TestCase; +import org.apache.tuscany.core.mock.component.SimpleTargetImpl; + +/** + * Tests invoking on a different interface from the one actually implemented by the target + * + * @version $Rev$ $Date$ + */ +public class MediationTestCase extends TestCase { + + private Method hello; + + public void setUp() throws Exception { + hello = Hello.class.getMethod("hello", String.class); + } + + public void testMediation() throws Exception { + StaticPojoTargetInvoker invoker = new StaticPojoTargetInvoker(hello, new SimpleTargetImpl()); + Assert.assertEquals("foo", invoker.invokeTarget("foo")); + } + + public interface Hello { + + String hello(String message) throws Exception; + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/NonBlockingBridgingInterceptorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/NonBlockingBridgingInterceptorTestCase.java new file mode 100644 index 0000000000..a8b1eaf36f --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/NonBlockingBridgingInterceptorTestCase.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.services.work.WorkScheduler; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.MessageImpl; + +import junit.framework.TestCase; +import org.easymock.EasyMock; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.getCurrentArguments; +import static org.easymock.EasyMock.isA; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import org.easymock.IAnswer; + +/** + * @version $Rev$ $Date$ + */ +public class NonBlockingBridgingInterceptorTestCase extends TestCase { + + public void testInvoke() throws Exception { + WorkScheduler scheduler = createMock(WorkScheduler.class); + scheduler.scheduleWork(isA(Runnable.class)); + expectLastCall().andStubAnswer(new IAnswer<Object>() { + public Object answer() throws Throwable { + Runnable runnable = (Runnable) getCurrentArguments()[0]; + runnable.run(); + return null; + } + }); + replay(scheduler); + WorkContext context = createMock(WorkContext.class); + Message msg = new MessageImpl(); + Interceptor next = EasyMock.createMock(Interceptor.class); + EasyMock.expect(next.invoke(EasyMock.eq(msg))).andReturn(msg); + EasyMock.replay(next); + Interceptor interceptor = new NonBlockingBridgingInterceptor(scheduler, context, next); + interceptor.invoke(msg); + verify(next); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/OutboundInvocationErrorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/OutboundInvocationErrorTestCase.java new file mode 100644 index 0000000000..6313f14220 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/OutboundInvocationErrorTestCase.java @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; + +import junit.framework.TestCase; + +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.mock.wire.MockStaticInvoker; +import org.apache.tuscany.core.mock.wire.MockSyncInterceptor; +import org.apache.tuscany.core.wire.jdk.JDKOutboundInvocationHandler; + +/** + * Tests handling of exceptions thrown during an outbound wire invocation + * + * @version $Rev$ $Date$ + */ +public class OutboundInvocationErrorTestCase extends TestCase { + + private Method checkedMethod; + private Method runtimeMethod; + private JavaInterfaceProcessorRegistry registry = new JavaInterfaceProcessorRegistryImpl(); + + public OutboundInvocationErrorTestCase() { + super(); + } + + public OutboundInvocationErrorTestCase(String arg0) { + super(arg0); + } + + public void setUp() throws Exception { + super.setUp(); + checkedMethod = TestBean.class.getDeclaredMethod("checkedException", (Class[]) null); + runtimeMethod = TestBean.class.getDeclaredMethod("runtimeException", (Class[]) null); + assertNotNull(checkedMethod); + assertNotNull(runtimeMethod); + } + + public void testCheckedException() throws Exception { + OutboundWire wire = new OutboundWireImpl(); + ServiceContract<?> contract = registry.introspect(TestBean.class); + wire.setServiceContract(contract); + Operation operation = contract.getOperations().get("checkedException"); + wire.addInvocationChain(operation, createChain(checkedMethod, operation)); + JDKOutboundInvocationHandler handler = new JDKOutboundInvocationHandler(wire, new WorkContextImpl()); + try { + TestBean proxy = (TestBean) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), + new Class[]{TestBean.class}, handler); + proxy.checkedException(); + } catch (TestException e) { + return; + } + fail(TestException.class.getName() + " should have been thrown"); + } + + public void testRuntimeException() throws Exception { + OutboundWire wire = new OutboundWireImpl(); + ServiceContract<?> contract = registry.introspect(TestBean.class); + wire.setServiceContract(contract); + Operation operation = contract.getOperations().get("runtimeException"); + OutboundInvocationChain chain = createChain(runtimeMethod, operation); + wire.addInvocationChain(operation, chain); + JDKOutboundInvocationHandler handler = new JDKOutboundInvocationHandler(wire, new WorkContextImpl()); + try { + TestBean proxy = (TestBean) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), + new Class[]{TestBean.class}, handler); + proxy.runtimeException(); + } catch (TestRuntimeException e) { + return; + } + fail(TestException.class.getName() + " should have been thrown"); + } + + private OutboundInvocationChain createChain(Method m, Operation operation) { + MockStaticInvoker invoker = new MockStaticInvoker(m, new TestBeanImpl()); + OutboundInvocationChain chain = new OutboundInvocationChainImpl(operation); + chain.addInterceptor(new MockSyncInterceptor()); + chain.setTargetInvoker(invoker); + chain.setTargetInterceptor(new InvokerInterceptor()); + chain.prepare(); + return chain; + } + + public interface TestBean { + + void checkedException() throws TestException; + + void runtimeException() throws TestRuntimeException; + + } + + public class TestBeanImpl implements TestBean { + + public void checkedException() throws TestException { + throw new TestException(); + } + + public void runtimeException() throws TestRuntimeException { + throw new TestRuntimeException(); + } + } + + public class TestException extends Exception { + } + + public class TestRuntimeException extends RuntimeException { + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/OutboundInvocationHandlerTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/OutboundInvocationHandlerTestCase.java new file mode 100644 index 0000000000..11e2a78d56 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/OutboundInvocationHandlerTestCase.java @@ -0,0 +1,133 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import java.lang.reflect.Method; + +import org.apache.tuscany.spi.idl.java.JavaIDLUtils; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; + +import junit.framework.TestCase; +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.mock.component.SimpleTarget; +import org.apache.tuscany.core.mock.component.SimpleTargetImpl; +import org.apache.tuscany.core.mock.wire.MockStaticInvoker; +import org.apache.tuscany.core.mock.wire.MockSyncInterceptor; +import org.apache.tuscany.core.wire.jdk.JDKOutboundInvocationHandler; + +public class OutboundInvocationHandlerTestCase extends TestCase { + + private Method hello; + private ServiceContract<?> contract; + + public OutboundInvocationHandlerTestCase() { + super(); + } + + public OutboundInvocationHandlerTestCase(String arg0) { + super(arg0); + } + + public void setUp() throws Exception { + super.setUp(); + JavaInterfaceProcessorRegistry registry = new JavaInterfaceProcessorRegistryImpl(); + contract = registry.introspect(SimpleTarget.class); + hello = SimpleTarget.class.getMethod("hello", String.class); + } + + public void testBasicInvoke() throws Throwable { + OutboundWire wire = new OutboundWireImpl(); + Operation operation = contract.getOperations().get("hello"); + wire.addInvocationChain(operation, createChain(operation)); + wire.setServiceContract(contract); + JDKOutboundInvocationHandler handler = new JDKOutboundInvocationHandler(wire, new WorkContextImpl()); + assertEquals("foo", handler.invoke(hello, new Object[]{"foo"})); + } + + public void testErrorInvoke() throws Throwable { + OutboundWire wire = new OutboundWireImpl(); + Operation operation = contract.getOperations().get("hello"); + wire.addInvocationChain(operation, createChain(operation)); + wire.setServiceContract(contract); + JDKOutboundInvocationHandler handler = new JDKOutboundInvocationHandler(wire, new WorkContextImpl()); + try { + handler.invoke(hello, new Object[]{}); + fail("Expected " + IllegalArgumentException.class.getName()); + } catch (IllegalArgumentException e) { + // should throw + } + } + + public void testDirectErrorInvoke() throws Throwable { + Operation operation = contract.getOperations().get("hello"); + OutboundInvocationChain source = new OutboundInvocationChainImpl(operation); + MockStaticInvoker invoker = new MockStaticInvoker(hello, new SimpleTargetImpl()); + source.setTargetInvoker(invoker); + + OutboundWire wire = new OutboundWireImpl(); + wire.setServiceContract(contract); + wire.addInvocationChain(operation, source); + JDKOutboundInvocationHandler handler = new JDKOutboundInvocationHandler(wire, new WorkContextImpl()); + try { + assertEquals("foo", handler.invoke(hello, new Object[]{})); + fail("Expected " + IllegalArgumentException.class.getName()); + } catch (IllegalArgumentException e) { + // should throw + } + } + + public void testDirectInvoke() throws Throwable { + Operation operation = contract.getOperations().get("hello"); + OutboundInvocationChain source = new OutboundInvocationChainImpl(operation); + MockStaticInvoker invoker = new MockStaticInvoker(hello, new SimpleTargetImpl()); + source.setTargetInvoker(invoker); + + OutboundWire wire = new OutboundWireImpl(); + wire.setServiceContract(contract); + wire.addInvocationChain(operation, source); + JDKOutboundInvocationHandler handler = new JDKOutboundInvocationHandler(wire, new WorkContextImpl()); + assertEquals("foo", handler.invoke(hello, new Object[]{"foo"})); + } + + private OutboundInvocationChain createChain(Operation operation) { + OutboundInvocationChain source = new OutboundInvocationChainImpl(operation); + MockSyncInterceptor sourceInterceptor = new MockSyncInterceptor(); + source.addInterceptor(sourceInterceptor); + + InboundInvocationChain target = new InboundInvocationChainImpl(operation); + MockSyncInterceptor targetInterceptor = new MockSyncInterceptor(); + target.addInterceptor(targetInterceptor); + target.addInterceptor(new InvokerInterceptor()); + + // connect the source to the target + source.setTargetInterceptor(targetInterceptor); + source.prepare(); + target.prepare(); + Method method = JavaIDLUtils.findMethod(operation, SimpleTarget.class.getMethods()); + MockStaticInvoker invoker = new MockStaticInvoker(method, new SimpleTargetImpl()); + source.setTargetInvoker(invoker); + return source; + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/StaticPojoInvokerTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/StaticPojoInvokerTestCase.java new file mode 100644 index 0000000000..e9e07dfa0a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/StaticPojoInvokerTestCase.java @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import static java.lang.Integer.TYPE; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import junit.framework.Assert; +import junit.framework.TestCase; + +public class StaticPojoInvokerTestCase extends TestCase { + + private Method echoMethod; + private Method arrayMethod; + private Method nullParamMethod; + private Method primitiveMethod; + private Method checkedMethod; + private Method runtimeMethod; + + public StaticPojoInvokerTestCase() { + + } + + public StaticPojoInvokerTestCase(String arg0) { + super(arg0); + } + + public void setUp() throws Exception { + echoMethod = TestBean.class.getDeclaredMethod("echo", String.class); + arrayMethod = TestBean.class.getDeclaredMethod("arrayEcho", String[].class); + nullParamMethod = TestBean.class.getDeclaredMethod("nullParam", (Class[]) null); + primitiveMethod = TestBean.class.getDeclaredMethod("primitiveEcho", TYPE); + checkedMethod = TestBean.class.getDeclaredMethod("checkedException", (Class[]) null); + runtimeMethod = TestBean.class.getDeclaredMethod("runtimeException", (Class[]) null); + Assert.assertNotNull(echoMethod); + Assert.assertNotNull(checkedMethod); + Assert.assertNotNull(runtimeMethod); + } + + public void testObjectInvoke() throws Throwable { + TestBean bean = new TestBean(); + StaticPojoTargetInvoker invoker = new StaticPojoTargetInvoker(echoMethod, bean); + Object ret = invoker.invokeTarget("foo"); + Assert.assertEquals("foo", ret); + } + + public void testArrayInvoke() throws Throwable { + TestBean bean = new TestBean(); + StaticPojoTargetInvoker invoker = new StaticPojoTargetInvoker(arrayMethod, bean); + String[] args = new String[]{"foo", "bar"}; + Object ret = invoker.invokeTarget(new Object[]{args}); + String[] retA = (String[]) ret; + Assert.assertNotNull(retA); + Assert.assertEquals(2, retA.length); + Assert.assertEquals("foo", retA[0]); + Assert.assertEquals("bar", retA[1]); + } + + public void testNullInvoke() throws Throwable { + TestBean bean = new TestBean(); + StaticPojoTargetInvoker invoker = new StaticPojoTargetInvoker(nullParamMethod, bean); + Object ret = invoker.invokeTarget(null); + String retS = (String) ret; + Assert.assertEquals("foo", retS); + } + + public void testPrimitiveInvoke() throws Throwable { + TestBean bean = new TestBean(); + StaticPojoTargetInvoker invoker = new StaticPojoTargetInvoker(primitiveMethod, bean); + Object ret = invoker.invokeTarget(new Integer[]{1}); + Integer retI = (Integer) ret; + Assert.assertEquals(1, retI.intValue()); + } + + public void testInvokeCheckedException() throws Throwable { + TestBean bean = new TestBean(); + StaticPojoTargetInvoker invoker = new StaticPojoTargetInvoker(checkedMethod, bean); + try { + invoker.invokeTarget(null); + } catch (InvocationTargetException e) { + if (e.getCause() != null && TestException.class.equals(e.getCause().getClass())) { + return; + } + } catch (Throwable e) { + //ok + } + fail(TestException.class.getName() + " should have been thrown"); + } + + public void testInvokeRuntimeException() throws Throwable { + TestBean bean = new TestBean(); + StaticPojoTargetInvoker invoker = new StaticPojoTargetInvoker(runtimeMethod, bean); + try { + invoker.invokeTarget(null); + } catch (InvocationTargetException e) { + if (e.getCause() != null && e.getCause() instanceof TestRuntimeException) { + return; + } + } + fail(TestException.class.getName() + " should have been thrown"); + } + + private class TestBean { + + public String echo(String msg) throws Exception { + Assert.assertEquals("foo", msg); + return msg; + } + + public String[] arrayEcho(String[] msg) throws Exception { + Assert.assertNotNull(msg); + Assert.assertEquals(2, msg.length); + Assert.assertEquals("foo", msg[0]); + Assert.assertEquals("bar", msg[1]); + return msg; + } + + public String nullParam() throws Exception { + return "foo"; + } + + public int primitiveEcho(int i) throws Exception { + return i; + } + + public void checkedException() throws TestException { + throw new TestException(); + } + + public void runtimeException() throws TestRuntimeException { + throw new TestRuntimeException(); + } + } + + public class TestException extends Exception { + } + + public class TestRuntimeException extends RuntimeException { + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/SynchronousBridgingInterceptorTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/SynchronousBridgingInterceptorTestCase.java new file mode 100644 index 0000000000..f1631fc555 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/SynchronousBridgingInterceptorTestCase.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.core.wire; + +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.MessageImpl; + +import org.easymock.EasyMock; +import static org.easymock.EasyMock.verify; +import junit.framework.TestCase; + +/** + * @version $Rev$ $Date$ + */ +public class SynchronousBridgingInterceptorTestCase extends TestCase { + + public void testInvoke() throws Exception { + Message msg = new MessageImpl(); + Interceptor next = EasyMock.createMock(Interceptor.class); + EasyMock.expect(next.invoke(EasyMock.eq(msg))).andReturn(msg); + EasyMock.replay(next); + Interceptor interceptor = new SynchronousBridgingInterceptor(next); + interceptor.invoke(msg); + verify(next); + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/WireOptimizationTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/WireOptimizationTestCase.java new file mode 100644 index 0000000000..97e27d947e --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/WireOptimizationTestCase.java @@ -0,0 +1,139 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire; + +import java.lang.reflect.Method; +import java.lang.reflect.Type; + +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.wire.InboundInvocationChain; +import org.apache.tuscany.spi.wire.InboundWire; +import org.apache.tuscany.spi.wire.Interceptor; +import org.apache.tuscany.spi.wire.Message; +import org.apache.tuscany.spi.wire.OutboundInvocationChain; +import org.apache.tuscany.spi.wire.OutboundWire; +import org.apache.tuscany.spi.wire.TargetInvoker; + +import junit.framework.TestCase; + +/** + * Verifies wire optimization analysis + * + * @version $$Rev$$ $$Date$$ + */ +public class WireOptimizationTestCase extends TestCase { + + private Operation operation; + private Method m; + + public void foo() { + } + + public void testSourceWireInterceptorOptimization() throws Exception { + OutboundWire wire = new OutboundWireImpl(); + OutboundInvocationChain chain = new OutboundInvocationChainImpl(operation); + chain.addInterceptor(new OptimizableInterceptor()); + wire.addInvocationChain(operation, chain); + assertTrue(wire.isOptimizable()); + } + + public void testSourceWireNonInterceptorOptimization() throws Exception { + OutboundWire wire = new OutboundWireImpl(); + OutboundInvocationChain chain = new OutboundInvocationChainImpl(operation); + chain.addInterceptor(new NonOptimizableInterceptor()); + wire.addInvocationChain(operation, chain); + assertFalse(wire.isOptimizable()); + } + + public void testTargetWireInterceptorOptimization() throws Exception { + InboundWire wire = new InboundWireImpl(); + InboundInvocationChain chain = new InboundInvocationChainImpl(operation); + chain.addInterceptor(new OptimizableInterceptor()); + wire.addInvocationChain(operation, chain); + assertTrue(wire.isOptimizable()); + } + + public void testTargetWireNonInterceptorOptimization() throws Exception { + InboundWire wire = new InboundWireImpl(); + InboundInvocationChain chain = new InboundInvocationChainImpl(operation); + chain.addInterceptor(new NonOptimizableInterceptor()); + wire.addInvocationChain(operation, chain); + assertFalse(wire.isOptimizable()); + } + + public void testTargetWireNonTargetInvokerOptimization() throws Exception { + InboundWire wire = new InboundWireImpl(); + InboundInvocationChain chain = new InboundInvocationChainImpl(operation); + TargetInvoker invoker = new StaticPojoTargetInvoker(m, new Object()); + invoker.setCacheable(false); + chain.setTargetInvoker(invoker); + wire.addInvocationChain(operation, chain); + assertFalse(wire.isOptimizable()); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + protected void setUp() throws Exception { + super.setUp(); + m = getClass().getMethod("foo", (Class[]) null); + operation = new Operation<Type>("foo", null, null, null, false, null); + + } + + private class OptimizableInterceptor implements Interceptor { + + public Message invoke(Message msg) { + return null; + } + + public void setNext(Interceptor next) { + + } + + public Interceptor getNext() { + return null; + } + + public boolean isOptimizable() { + return true; + } + } + + private class NonOptimizableInterceptor implements Interceptor { + + public Message invoke(Message msg) { + return null; + } + + public void setNext(Interceptor next) { + + } + + public Interceptor getNext() { + return null; + } + + public boolean isOptimizable() { + return false; + } + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/jdk/JDKInboundInvocationHandlerTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/jdk/JDKInboundInvocationHandlerTestCase.java new file mode 100644 index 0000000000..d34ecd61f0 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/jdk/JDKInboundInvocationHandlerTestCase.java @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.core.wire.jdk; + +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.spi.component.WorkContext; +import org.apache.tuscany.spi.idl.InvalidServiceContractException; +import org.apache.tuscany.spi.idl.java.JavaInterfaceProcessorRegistry; +import org.apache.tuscany.spi.model.Operation; +import org.apache.tuscany.spi.model.ServiceContract; +import org.apache.tuscany.spi.wire.InboundInvocationChain; + +import junit.framework.TestCase; + +import org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl; +import org.apache.tuscany.core.mock.component.SimpleTarget; +import org.apache.tuscany.core.mock.component.SimpleTargetImpl; +import org.apache.tuscany.core.mock.wire.MockStaticInvoker; +import org.apache.tuscany.core.mock.wire.MockSyncInterceptor; +import org.apache.tuscany.core.wire.InboundInvocationChainImpl; +import org.apache.tuscany.core.wire.InvokerInterceptor; +import org.easymock.classextension.EasyMock; + +/** + * Verifies invocations on inbound wires + * + * @version $$Rev$$ $$Date$$ + */ +public class JDKInboundInvocationHandlerTestCase extends TestCase { + + private Method echo; + private Operation operation; + + public void testInterceptorInvoke() throws Throwable { + Map<Method, InboundInvocationChain> chains = new HashMap<Method, InboundInvocationChain>(); + MockStaticInvoker invoker = new MockStaticInvoker(echo, new SimpleTargetImpl()); + InboundInvocationChain chain = new InboundInvocationChainImpl(operation); + MockSyncInterceptor interceptor = new MockSyncInterceptor(); + chain.addInterceptor(interceptor); + chain.addInterceptor(new InvokerInterceptor()); + chain.setTargetInvoker(invoker); + chain.prepare(); + chains.put(echo, chain); + WorkContext workContext = EasyMock.createNiceMock(WorkContext.class); + EasyMock.replay(workContext); + JDKInboundInvocationHandler handler = new JDKInboundInvocationHandler(chains, workContext); + assertEquals("foo", handler.invoke(echo, new String[]{"foo"})); + assertEquals(1, interceptor.getCount()); + } + + + public void testDirectErrorInvoke() throws Throwable { + InboundInvocationChain source = new InboundInvocationChainImpl(operation); + MockStaticInvoker invoker = new MockStaticInvoker(echo, new SimpleTargetImpl()); + source.setTargetInvoker(invoker); + + Map<Method, InboundInvocationChain> chains = new HashMap<Method, InboundInvocationChain>(); + chains.put(echo, source); + WorkContext workContext = EasyMock.createNiceMock(WorkContext.class); + EasyMock.replay(workContext); + JDKInboundInvocationHandler handler = new JDKInboundInvocationHandler(chains, workContext); + try { + assertEquals("foo", handler.invoke(echo, new Object[]{})); + fail("Expected " + IllegalArgumentException.class.getName()); + } catch (IllegalArgumentException e) { + // should throw + } + } + + public void testDirectInvoke() throws Throwable { + InboundInvocationChain source = new InboundInvocationChainImpl(operation); + MockStaticInvoker invoker = new MockStaticInvoker(echo, new SimpleTargetImpl()); + source.setTargetInvoker(invoker); + + Map<Method, InboundInvocationChain> chains = new HashMap<Method, InboundInvocationChain>(); + chains.put(echo, source); + WorkContext workContext = EasyMock.createNiceMock(WorkContext.class); + EasyMock.replay(workContext); + JDKInboundInvocationHandler handler = new JDKInboundInvocationHandler(chains, workContext); + assertEquals("foo", handler.invoke(echo, new Object[]{"foo"})); + } + + public void testToString() { + WorkContext workContext = EasyMock.createNiceMock(WorkContext.class); + EasyMock.replay(workContext); + JDKInboundInvocationHandler handler = + new JDKInboundInvocationHandler(new HashMap<Method, InboundInvocationChain>(), workContext); + Foo foo = (Foo) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Foo.class}, handler); + assertNotNull(foo.toString()); + } + + public void testHashCode() { + WorkContext workContext = EasyMock.createNiceMock(WorkContext.class); + EasyMock.replay(workContext); + JDKInboundInvocationHandler handler = + new JDKInboundInvocationHandler(new HashMap<Method, InboundInvocationChain>(), workContext); + Foo foo = (Foo) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Foo.class}, handler); + assertNotNull(foo.hashCode()); + } + + public void setUp() throws Exception { + super.setUp(); + JavaInterfaceProcessorRegistry registry = new JavaInterfaceProcessorRegistryImpl(); + ServiceContract<?> contract; + try { + contract = registry.introspect(SimpleTarget.class); + } catch (InvalidServiceContractException e) { + throw new AssertionError(); + } + operation = contract.getOperations().get("echo"); + echo = SimpleTarget.class.getMethod("echo", String.class); + } + + private interface Foo { + + } + +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/jdk/JDKOutboundInvocationHandlerTestCase.java b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/jdk/JDKOutboundInvocationHandlerTestCase.java new file mode 100644 index 0000000000..74338c4d38 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/java/org/apache/tuscany/core/wire/jdk/JDKOutboundInvocationHandlerTestCase.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.core.wire.jdk; + +import java.lang.reflect.Proxy; + +import org.apache.tuscany.spi.idl.java.JavaServiceContract; + +import junit.framework.TestCase; + +import org.apache.tuscany.core.component.WorkContextImpl; +import org.apache.tuscany.core.wire.OutboundWireImpl; + +/** + * @version $Rev$ $Date$ + */ +public class JDKOutboundInvocationHandlerTestCase extends TestCase { + + public void testToString() { + OutboundWireImpl wire = new OutboundWireImpl(); + wire.setServiceContract(new JavaServiceContract(Foo.class)); + JDKOutboundInvocationHandler handler = new JDKOutboundInvocationHandler(wire, new WorkContextImpl()); + Foo foo = (Foo) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Foo.class}, handler); + assertNotNull(foo.toString()); + } + + public void testHashCode() { + OutboundWireImpl wire = new OutboundWireImpl(); + wire.setServiceContract(new JavaServiceContract(Foo.class)); + JDKOutboundInvocationHandler handler = new JDKOutboundInvocationHandler(wire, new WorkContextImpl()); + Foo foo = (Foo) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Foo.class}, handler); + assertNotNull(foo.hashCode()); + } + + private interface Foo { + + } +} diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/databinding/impl/ipo.xsd b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/databinding/impl/ipo.xsd new file mode 100644 index 0000000000..92a576fb98 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/databinding/impl/ipo.xsd @@ -0,0 +1,136 @@ +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<schema targetNamespace="http://www.example.com/IPO" + xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:ipo="http://www.example.com/IPO"> + + <annotation> + <documentation xml:lang="en"> + International Purchase order schema for Example.com + Copyright 2000 Example.com. All rights reserved. + </documentation> + </annotation> + + + <element name="purchaseOrder" type="ipo:PurchaseOrderType" /> + + <element name="comment" type="string" /> + + <complexType name="PurchaseOrderType"> + <sequence> + <element name="shipTo" type="ipo:Address" /> + <element name="billTo" type="ipo:Address" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="items" type="ipo:Items" /> + </sequence> + <attribute name="orderDate" type="date" /> + </complexType> + + <complexType name="Items"> + <sequence> + <element name="item" minOccurs="0" maxOccurs="unbounded"> + <complexType> + <sequence> + <element name="productName" type="string" /> + <element name="quantity"> + <simpleType> + <restriction base="positiveInteger"> + <maxExclusive value="100" /> + </restriction> + </simpleType> + </element> + <element name="USPrice" type="decimal" /> + <element ref="ipo:comment" minOccurs="0" /> + <element name="shipDate" type="date" + minOccurs="0" /> + </sequence> + <attribute name="partNum" type="ipo:SKU" + use="required" /> + </complexType> + </element> + </sequence> + </complexType> + + <simpleType name="SKU"> + <restriction base="string"> + <pattern value="\d{3}-[A-Z]{2}" /> + </restriction> + </simpleType> + + <complexType name="Address"> + <sequence> + <element name="name" type="string" /> + <element name="street" type="string" /> + <element name="city" type="string" /> + </sequence> + </complexType> + + <complexType name="USAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="state" type="ipo:USState" /> + <element name="zip" type="positiveInteger" /> + </sequence> + </extension> + </complexContent> + </complexType> + + <complexType name="UKAddress"> + <complexContent> + <extension base="ipo:Address"> + <sequence> + <element name="postcode" type="ipo:UKPostcode" /> + </sequence> + <attribute name="exportCode" type="positiveInteger" + fixed="1" /> + </extension> + </complexContent> + </complexType> + + <!-- other Address derivations for more countries --> + + <simpleType name="USState"> + <restriction base="string"> + <enumeration value="AK" /> + <enumeration value="AL" /> + <enumeration value="AR" /> + <enumeration value="CA" /> + <enumeration value="PA" /> + <!-- and so on ... --> + </restriction> + </simpleType> + + <simpleType name="Postcode"> + <restriction base="string"> + <length value="7" fixed="true" /> + </restriction> + </simpleType> + + + <simpleType name="UKPostcode"> + <restriction base="ipo:Postcode"> + <pattern value="[A-Z]{2}\d\s\d[A-Z]{2}" /> + </restriction> + </simpleType> + + + +</schema> + diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/databinding/impl/order.wsdl b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/databinding/impl/order.wsdl new file mode 100644 index 0000000000..100890e10b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/databinding/impl/order.wsdl @@ -0,0 +1,76 @@ +<?xml version="1.0"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<definitions name="StockQuote" targetNamespace="http://example.com/order.wsdl" xmlns:tns="http://example.com/order.wsdl"
+ xmlns:xsd1="http://example.com/order.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns="http://schemas.xmlsoap.org/wsdl/">
+
+ <types>
+ <schema targetNamespace="http://example.com/order.xsd" xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:ipo="http://www.example.com/IPO">
+ <import namespace="http://www.example.com/IPO" schemaLocation="ipo.xsd"/>
+ <element name="checkOrderStatus">
+ <complexType>
+ <sequence>
+ <element name="customerId" type="string" />
+ <element name="order" type="ipo:PurchaseOrderType" />
+ <element name="flag" type="int" />
+ </sequence>
+ </complexType>
+ </element>
+ <element name="checkOrderStatusResponse">
+ <complexType>
+ <sequence>
+ <element name="status" type="string" />
+ </sequence>
+ </complexType>
+ </element>
+ <element name="note" type="string" />
+ </schema>
+ </types>
+
+ <message name="CheckOrderStatusInput1">
+ <part name="body" element="xsd1:checkOrderStatus" />
+ </message>
+
+ <message name="CheckOrderStatusOutput1">
+ <part name="body" element="xsd1:checkOrderStatusResponse" />
+ </message>
+
+ <message name="CheckOrderStatusInput2">
+ <part name="p1" element="xsd1:checkOrderStatus" />
+ <part name="p2" element="xsd1:note" />
+ </message>
+
+ <message name="CheckOrderStatusOutput2">
+ <part name="p1" element="xsd1:checkOrderStatusResponse" />
+ </message>
+
+ <portType name="OrderPortType">
+ <operation name="checkOrderStatus">
+ <input message="tns:CheckOrderStatusInput1" />
+ <output message="tns:CheckOrderStatusOutput1" />
+ </operation>
+ <operation name="checkOrderStatus2">
+ <input message="tns:CheckOrderStatusInput2" />
+ <output message="tns:CheckOrderStatusOutput2" />
+ </operation>
+ </portType>
+
+</definitions>
\ No newline at end of file diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/databinding/xml/foo.xml b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/databinding/xml/foo.xml new file mode 100644 index 0000000000..0ba8ade1e0 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/databinding/xml/foo.xml @@ -0,0 +1,22 @@ +<?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. +--> +<f:foo xmlns:f="http://foo" name="foo"> + <b:bar xmlns:b="http://bar">bar</b:bar> +</f:foo>
\ No newline at end of file diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/deployer/boot1-include.scdl b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/deployer/boot1-include.scdl new file mode 100644 index 0000000000..c8b825ed5a --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/deployer/boot1-include.scdl @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" + xmlns:system="http://incubator.apache.org/tuscany/xmlns/system/1.0-incubator-M2" + name="boot1-include"> + + <component name="component2"> + <system:implementation.system class="org.apache.tuscany.core.mock.component.BasicInterfaceImpl"/> + </component> + + <service name="service2" > + <interface.java interface="org.apache.tuscany.core.mock.component.BasicInterface"/> + <system:binding.system/> + <reference>component2</reference> + </service> + +</composite> diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/deployer/boot1.scdl b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/deployer/boot1.scdl new file mode 100644 index 0000000000..f9397bcac0 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/deployer/boot1.scdl @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" + xmlns:system="http://incubator.apache.org/tuscany/xmlns/system/1.0-incubator-M2" + name="boot1"> + <service name="service" > + <interface.java interface="org.apache.tuscany.core.mock.component.BasicInterface"/> + <system:binding.system/> + <reference>component</reference> + </service> + + <component name="component"> + <system:implementation.system class="org.apache.tuscany.core.mock.component.BasicInterfaceImpl"/> + <property name="publicProperty">propval</property> + <reference name="publicReference">component2</reference> + </component> + + <include name="boot1-include" scdlLocation="boot1-include.scdl"/> +</composite> diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/deployer/boot2.scdl b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/deployer/boot2.scdl new file mode 100644 index 0000000000..bdf8061778 --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/deployer/boot2.scdl @@ -0,0 +1,132 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<!-- + A more complex example closer to a typical bootstrap configuration + $Rev$ $Date$ +--> +<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" + xmlns:system="http://incubator.apache.org/tuscany/xmlns/system/1.0-incubator-M2" + name="boot2"> + + <!-- expose Deployer API as a service --> + <service name="deployer" > + <interface.java interface="org.apache.tuscany.spi.deployer.Deployer"/> + <system:binding.system/> + <reference>deployerImpl</reference> + </service> + + <!-- Component that provides the Deployer service --> + <component name="deployerImpl"> + <system:implementation.system class="org.apache.tuscany.core.deployer.DeployerImpl"/> + </component> + + <!-- Work management --> + <component name="workContext"> + <system:implementation.system class="org.apache.tuscany.core.component.WorkContextImpl"/> + </component> + + <!-- Scope infrastructure --> + <component name="scopeRegistry"> + <system:implementation.system class="org.apache.tuscany.core.component.scope.ScopeRegistryImpl"/> + </component> + + <!-- Builder and BuilderRegistry --> + <component name="builder"> + <system:implementation.system class="org.apache.tuscany.core.builder.BuilderRegistryImpl"/> + </component> + + <!-- Loader and LoaderRegistry --> + <component name="loader"> + <system:implementation.system class="org.apache.tuscany.core.loader.LoaderRegistryImpl"/> + </component> + + <!-- Introspector and IntrospectionRegistry --> + <component name="interfaceProcessorRegistry"> + <system:implementation.system class="org.apache.tuscany.core.implementation.IntrospectionRegistryImpl"/> + </component> + + <!-- Connector infrastructure --> + <component name="connector"> + <system:implementation.system class="org.apache.tuscany.core.builder.ConnectorImpl"/> + </component> + + <!-- Foundcation element loader implementations --> + <component name="elementLoader.component"> + <system:implementation.system class="org.apache.tuscany.core.loader.ComponentLoader"/> + </component> + <component name="elementLoader.componentType"> + <system:implementation.system class="org.apache.tuscany.core.loader.ComponentTypeElementLoader"/> + </component> + <component name="elementLoader.interface.java"> + <system:implementation.system class="org.apache.tuscany.core.idl.java.InterfaceJavaLoader"/> + </component> + <component name="elementLoader.property"> + <system:implementation.system class="org.apache.tuscany.core.loader.PropertyLoader"/> + </component> + <component name="elementLoader.reference"> + <system:implementation.system class="org.apache.tuscany.core.loader.ReferenceLoader"/> + </component> + <component name="elementLoader.service"> + <system:implementation.system class="org.apache.tuscany.core.loader.ServiceLoader"/> + </component> + + <component name="wireService"> + <system:implementation.system class="org.apache.tuscany.core.wire.jdk.JDKWireService"/> + </component> + + <!-- Composite implementation type --> + <component name="composite.loader"> + <system:implementation.system class="org.apache.tuscany.core.implementation.composite.CompositeLoader"/> + </component> + + <component name="interfaceJava.interfaceProcessorRegistry"> + <system:implementation.system class="org.apache.tuscany.core.idl.java.JavaInterfaceProcessorRegistryImpl"/> + </component> + + <component name="artifactRepository"> + <system:implementation.system class="org.apache.tuscany.core.services.artifact.LocalMavenRepository"/> + <property name="repository">.m2/repository</property> + </component> + + <!-- DataBinding registry --> + <component name="databinding.registry"> + <system:implementation.system class="org.apache.tuscany.core.databinding.impl.DataBindingRegistryImpl" /> + </component> + + <!-- DataBinding registry --> + <component name="databinding.mediator"> + <system:implementation.system class="org.apache.tuscany.core.databinding.impl.MediatorImpl" /> + </component> + + <!-- Transformer registry --> + <component name="databinding.transformerRegistry" initLevel="90"> + <system:implementation.system class="org.apache.tuscany.core.databinding.impl.TransformerRegistryImpl" /> + </component> + + <component name="propertyFactory"> + <system:implementation.system class="org.apache.tuscany.core.property.PropertyObjectFactoryImpl"/> + </component> + + <component name="policyBuilderRegistry"> + <system:implementation.system class="org.apache.tuscany.core.policy.PolicyBuilderRegistryImpl"/> + </component> + + +</composite> diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/loader/test-include.scdl b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/loader/test-include.scdl new file mode 100644 index 0000000000..584846504b --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/loader/test-include.scdl @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<composite> + This file just needs to exist +</composite>
\ No newline at end of file diff --git a/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/property/ipo.xml b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/property/ipo.xml new file mode 100644 index 0000000000..df901d183d --- /dev/null +++ b/sca-java-1.x/branches/sca-java-M2/sca/kernel/core/src/test/resources/org/apache/tuscany/core/property/ipo.xml @@ -0,0 +1,51 @@ +<?xml version="1.0"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<ipo:purchaseOrder + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:ipo="http://www.example.com/IPO" + xsi:schemaLocation="http://www.example.com/IPO ipo.xsd" + orderDate="1999-12-01"> + + <shipTo exportCode="1" xsi:type="ipo:UKAddress"> + <name>Helen Zoe</name> + <street>47 Eden Street</street> + <city>Cambridge</city> + <postcode>CB1 1JR</postcode> + </shipTo> + + <billTo xsi:type="ipo:USAddress"> + <name>Robert Smith</name> + <street>8 Oak Avenue</street> + <city>Old Town</city> + <state>PA</state> + <zip>95819</zip> + </billTo> + + <items> + <item partNum="833-AA"> + <productName>Lapis necklace</productName> + <quantity>1</quantity> + <USPrice>99.95</USPrice> + <ipo:comment>Want this for the holidays</ipo:comment> + <shipDate>1999-12-05</shipDate> + </item> + </items> +</ipo:purchaseOrder> + |