summaryrefslogtreecommitdiffstats
path: root/sandbox/mobile-android/contribution
diff options
context:
space:
mode:
authordims <dims@13f79535-47bb-0310-9956-ffa450edef68>2008-06-17 00:23:01 +0000
committerdims <dims@13f79535-47bb-0310-9956-ffa450edef68>2008-06-17 00:23:01 +0000
commitbdd0a41aed7edf21ec2a65cfa17a86af2ef8c48a (patch)
tree38a92061c0793434c4be189f1d70c3458b6bc41d /sandbox/mobile-android/contribution
Move Tuscany from Incubator to top level.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@668359 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sandbox/mobile-android/contribution')
-rw-r--r--sandbox/mobile-android/contribution/.classpath16
-rw-r--r--sandbox/mobile-android/contribution/.project19
-rw-r--r--sandbox/mobile-android/contribution/.settings/org.eclipse.jdt.core.prefs5
-rw-r--r--sandbox/mobile-android/contribution/DISCLAIMER8
-rw-r--r--sandbox/mobile-android/contribution/LICENSE205
-rw-r--r--sandbox/mobile-android/contribution/NOTICE6
-rw-r--r--sandbox/mobile-android/contribution/pom.xml55
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java86
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.java40
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java116
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java52
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultContributionFactory.java32
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultModelFactoryExtensionPoint.java132
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DeployedArtifact.java29
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java47
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java56
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ModelFactoryExtensionPoint.java54
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/PackageType.java42
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ArtifactImpl.java103
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionFactoryImpl.java52
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionImpl.java154
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java48
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessorExtensionPoint.java58
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java512
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.java66
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultPackageProcessorExtensionPoint.java129
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java256
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java167
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java236
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidationSchemaExtensionPoint.java83
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensiblePackageProcessor.java75
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java185
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java122
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessor.java70
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessorExtensionPoint.java50
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java61
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java29
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java51
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java29
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java336
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidationSchemaExtensionPoint.java52
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java106
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java80
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolver.java60
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.java114
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java172
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.java69
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java52
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResourceReference.java101
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java66
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java50
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java125
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionException.java45
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListener.java58
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListenerExtensionPoint.java44
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionReadException.java94
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRepository.java128
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionResolveException.java41
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRuntimeException.java44
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionService.java141
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionWriteException.java61
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/DefaultContributionListenerExtensionPoint.java109
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ExtensibleContributionListener.java77
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/TypeDescriber.java38
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnrecognizedElementException.java48
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedContentTypeException.java42
-rw-r--r--sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedPackageTypeException.java39
-rw-r--r--sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ContributionFactory18
-rw-r--r--sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint18
-rw-r--r--sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ContributionPostProcessorExtensionPoint18
-rw-r--r--sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.PackageProcessorExtensionPoint18
-rw-r--r--sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint18
-rw-r--r--sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint18
-rw-r--r--sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchemaExtensionPoint18
-rw-r--r--sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint18
-rw-r--r--sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.scanner.ContributionScannerExtensionPoint18
-rw-r--r--sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.service.ContributionListenerExtensionPoint18
77 files changed, 6108 insertions, 0 deletions
diff --git a/sandbox/mobile-android/contribution/.classpath b/sandbox/mobile-android/contribution/.classpath
new file mode 100644
index 0000000000..732ae371c2
--- /dev/null
+++ b/sandbox/mobile-android/contribution/.classpath
@@ -0,0 +1,16 @@
+<classpath>
+ <classpathentry kind="src" path="src/main/java"/>
+ <classpathentry kind="src" path="src/main/resources" excluding="**/*.java"/>
+ <classpathentry kind="src" path="src/test/java" output="target/test-classes"/>
+ <classpathentry kind="output" path="target/classes"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="var" path="M2_REPO/junit/junit/4.2/junit-4.2.jar"/>
+ <classpathentry kind="src" path="/tuscany-assembly"/>
+ <classpathentry kind="src" path="/tuscany-policy"/>
+ <classpathentry kind="src" path="/tuscany-extensibility"/>
+ <classpathentry kind="src" path="/tuscany-interface"/>
+ <classpathentry kind="src" path="/tuscany-definitions"/>
+ <classpathentry kind="var" path="M2_REPO/org/easymock/easymock/2.2/easymock-2.2.jar"/>
+ <classpathentry kind="var" path="M2_REPO/stax/stax-api/1.0.1/stax-api-1.0.1.jar"/>
+ <classpathentry kind="var" path="M2_REPO/xml-apis/xml-apis/1.3.03/xml-apis-1.3.03.jar"/>
+</classpath> \ No newline at end of file
diff --git a/sandbox/mobile-android/contribution/.project b/sandbox/mobile-android/contribution/.project
new file mode 100644
index 0000000000..24cbaf4abb
--- /dev/null
+++ b/sandbox/mobile-android/contribution/.project
@@ -0,0 +1,19 @@
+<projectDescription>
+ <name>tuscany-contribution</name>
+ <comment>Parent POM defining settings that can be used across Tuscany</comment>
+ <projects>
+ <project>tuscany-assembly</project>
+ <project>tuscany-policy</project>
+ <project>tuscany-extensibility</project>
+ <project>tuscany-interface</project>
+ <project>tuscany-definitions</project>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription> \ No newline at end of file
diff --git a/sandbox/mobile-android/contribution/.settings/org.eclipse.jdt.core.prefs b/sandbox/mobile-android/contribution/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000..8fc9b863cf
--- /dev/null
+++ b/sandbox/mobile-android/contribution/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,5 @@
+#Thu Mar 20 19:19:33 PDT 2008
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
diff --git a/sandbox/mobile-android/contribution/DISCLAIMER b/sandbox/mobile-android/contribution/DISCLAIMER
new file mode 100644
index 0000000000..d68a410903
--- /dev/null
+++ b/sandbox/mobile-android/contribution/DISCLAIMER
@@ -0,0 +1,8 @@
+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.
+
diff --git a/sandbox/mobile-android/contribution/LICENSE b/sandbox/mobile-android/contribution/LICENSE
new file mode 100644
index 0000000000..6e529a25c4
--- /dev/null
+++ b/sandbox/mobile-android/contribution/LICENSE
@@ -0,0 +1,205 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+
diff --git a/sandbox/mobile-android/contribution/NOTICE b/sandbox/mobile-android/contribution/NOTICE
new file mode 100644
index 0000000000..1325efd8bf
--- /dev/null
+++ b/sandbox/mobile-android/contribution/NOTICE
@@ -0,0 +1,6 @@
+${pom.name}
+Copyright (c) 2005 - 2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
diff --git a/sandbox/mobile-android/contribution/pom.xml b/sandbox/mobile-android/contribution/pom.xml
new file mode 100644
index 0000000000..a09a28bd5d
--- /dev/null
+++ b/sandbox/mobile-android/contribution/pom.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-modules</artifactId>
+ <version>2.0-incubating-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>tuscany-contribution</artifactId>
+ <name>Apache Tuscany SCA Contribution Model</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-assembly</artifactId>
+ <version>2.0-incubating-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-extensibility</artifactId>
+ <version>2.0-incubating-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>stax</groupId>
+ <artifactId>stax-api</artifactId>
+ <version>1.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>xml-apis</groupId>
+ <artifactId>xml-apis</artifactId>
+ <version>1.3.03</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java
new file mode 100644
index 0000000000..ad2dbace5e
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+import org.apache.tuscany.sca.assembly.Base;
+
+
+/**
+ * Represents an artifact in an SCA contribution.
+ *
+ * @version $Rev: 618930 $ $Date: 2008-02-06 01:15:49 -0800 (Wed, 06 Feb 2008) $
+ */
+public interface Artifact extends Base {
+
+ /**
+ * Returns the URI that unique identifies the artifact inside the contribution.
+ *
+ * @return The artifact URI
+ */
+ String getURI();
+
+ /**
+ * Sets the URI that uniquely identifies the artifact inside the contribution.
+ *
+ * @param uri The artifact URI
+ */
+ void setURI(String uri);
+
+ /**
+ * Returns the location of the artifact.
+ *
+ * @return The artifact location
+ */
+ String getLocation();
+
+ /**
+ * Set the location of the artifact.
+ *
+ * @param location The artifact location
+ */
+ void setLocation(String location);
+
+
+ /**
+ * Returns the in-memory model representing the artifact.
+ *
+ * @return The model object
+ */
+ Object getModel();
+
+ /**
+ * Sets the in-memory model representing the artifact.
+ *
+ * @param model The model object
+ */
+ void setModel(Object model);
+
+ /**
+ * Returns the contents of the artifact cached here.
+ * @return the contents of the artifact
+ */
+ byte[] getContents();
+
+ /**
+ * Sets the contents of the artifact.
+ * @param contents the contents of the artifact
+ */
+ void setContents(byte[] contents);
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.java
new file mode 100644
index 0000000000..f3d2b62fc1
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+/**
+ * Constants for the main supported contribution package type.
+ *
+ * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $
+ */
+@Deprecated
+public interface ContentType {
+
+ /**
+ * Java compressed contribution package
+ */
+ String JAR = "application/x-compressed";
+
+ /**
+ * Filesystem folder contribution package
+ */
+ String FOLDER = "application/vnd.tuscany.folder";
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java
new file mode 100644
index 0000000000..1bc4cc7b9e
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.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.sca.contribution;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * The representation of an SCA contribution.
+ *
+ * @version $Rev: 639257 $ $Date: 2008-03-20 05:12:00 -0700 (Thu, 20 Mar 2008) $
+ */
+public interface Contribution extends Artifact {
+
+ /**
+ * Default location of contribution metadata in an SCA contribution.
+ */
+ String SCA_CONTRIBUTION_META = "META-INF/sca-contribution.xml";
+
+ /**
+ * Default location of a generated contribution metadata in an SCA contribution.
+ */
+ String SCA_CONTRIBUTION_GENERATED_META = "META-INF/sca-contribution-generated.xml";
+
+ /**
+ * Default location of deployable composites in an SCA contribution.
+ */
+ String SCA_CONTRIBUTION_DEPLOYABLES = "META-INF/sca-deployables/";
+
+
+ /**
+ * Returns a list of exports based on the contribution metadata.
+ *
+ * @return The list of exports in this contribution
+ */
+ List<Export> getExports();
+
+ /**
+ * Returns a list of imports based on the contribution metadata.
+ *
+ * @return The list of imports in this contribution
+ */
+ List<Import> getImports();
+
+ /**
+ * Returns the list of deployable composites in the contribution.
+ *
+ * @return The list of deployable composites
+ */
+ List<Composite> getDeployables();
+
+ /**
+ * Returns the list of artifacts in the contribution.
+ *
+ * @return The list of artifacts in the contribution
+ */
+ List<Artifact> getArtifacts();
+
+ /**
+ * Returns the model resolver for the models representing the artifacts
+ * visible in the scope of this contribution.
+ *
+ * @return The model resolver
+ */
+ ModelResolver getModelResolver();
+
+ /**
+ * Sets the model resolver for the models representing the artifacts
+ * visible in the scope of this contribution.
+ *
+ * @param modelResolver The model resolver
+ */
+ void setModelResolver(ModelResolver modelResolver);
+
+ /**
+ * Returns the ClassLoader used to load classes and resources from
+ * this contribution
+ *
+ * FIXME Remove this, the base contribution model should not depend
+ * on Java ClassLoaders.
+ *
+ * @return The contribution ClassLoader
+ */
+ ClassLoader getClassLoader();
+
+ /**
+ * Sets the ClassLoader used to load classes and resources from
+ * this contribution
+ *
+ * FIXME Remove this, the base contribution model should not depend
+ * on Java ClassLoaders.
+ *
+ * @param classLoader the contribution class loader
+ */
+ void setClassLoader(ClassLoader classLoader);
+
+} \ No newline at end of file
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java
new file mode 100644
index 0000000000..31fccb6f4c
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+
+/**
+ * A factory for the contribution model.
+ *
+ * @version $Rev: 629585 $ $Date: 2008-02-20 11:39:27 -0800 (Wed, 20 Feb 2008) $
+ */
+public interface ContributionFactory {
+
+ /**
+ * Create a contribution model object
+ *
+ * @return The new contribution model object
+ */
+ Contribution createContribution();
+
+ /**
+ * Create a deployedArtifact model object
+ *
+ * @return The new deployedArtifact model object
+ */
+ @Deprecated
+ DeployedArtifact createDeployedArtifact();
+
+ /**
+ * Create an artifact model object
+ *
+ * @return The new artifact model object
+ */
+ Artifact createArtifact();
+
+} \ No newline at end of file
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultContributionFactory.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultContributionFactory.java
new file mode 100644
index 0000000000..73df82b8b5
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultContributionFactory.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+import org.apache.tuscany.sca.contribution.impl.ContributionFactoryImpl;
+
+
+/**
+ * Default implementation of a contribution model factory.
+ *
+ * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $
+ */
+public class DefaultContributionFactory extends ContributionFactoryImpl {
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultModelFactoryExtensionPoint.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultModelFactoryExtensionPoint.java
new file mode 100644
index 0000000000..7d56f37472
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultModelFactoryExtensionPoint.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.sca.contribution;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+
+import org.apache.tuscany.sca.extensibility.ServiceDiscovery;
+
+
+/**
+ * Default implementation of a model factory extension point.
+ *
+ * @version $Rev: 632642 $ $Date: 2008-03-01 10:16:44 -0800 (Sat, 01 Mar 2008) $
+ */
+public class DefaultModelFactoryExtensionPoint implements ModelFactoryExtensionPoint {
+
+ private HashMap<Class<?>, Object> factories = new HashMap<Class<?>, Object>();
+
+ /**
+ * Constructs a new DefaultModelFactoryExtensionPoint.
+ */
+ public DefaultModelFactoryExtensionPoint() {
+ }
+
+ /**
+ * Add a model factory extension.
+ *
+ * @param factory The factory to add
+ */
+ public void addFactory(Object factory) {
+ Class<?>[] interfaces = factory.getClass().getInterfaces();
+ if (interfaces.length == 0) {
+ Class<?> sc = factory.getClass().getSuperclass();
+ if (sc != Object.class) {
+ factories.put(sc, factory);
+ }
+ } else {
+ for (int i = 0; i<interfaces.length; i++) {
+ factories.put(interfaces[i], factory);
+ }
+ }
+ }
+
+ /**
+ * Remove a model factory.
+ *
+ * @param factory The factory to remove
+ */
+ public void removeFactory(Object factory) {
+ Class<?>[] interfaces = factory.getClass().getInterfaces();
+ if (interfaces.length == 0) {
+ Class<?> sc = factory.getClass().getSuperclass();
+ if (sc != Object.class) {
+ factories.remove(sc);
+ }
+ } else {
+ for (int i = 0; i<interfaces.length; i++) {
+ factories.remove(interfaces[i]);
+ }
+ }
+ }
+
+ /**
+ * Get a factory implementing the given interface.
+ * @param factoryInterface The lookup key (factory interface)
+ * @return The factory
+ */
+ public <T> T getFactory(Class<T> factoryInterface) {
+ Object factory = factories.get(factoryInterface);
+ if (factory == null) {
+
+ if (factoryInterface.isInterface()) {
+
+ // Dynamically load a factory class declared under META-INF/services
+ try {
+ Class<?> factoryClass = ServiceDiscovery.getInstance().loadFirstServiceClass(factoryInterface);
+ if (factoryClass != null) {
+
+ try {
+ // Default empty constructor
+ Constructor<?> constructor = factoryClass.getConstructor();
+ factory = constructor.newInstance();
+ } catch (NoSuchMethodException e) {
+
+ // Constructor taking the model factory extension point
+ Constructor<?> constructor = factoryClass.getConstructor(ModelFactoryExtensionPoint.class);
+ factory = constructor.newInstance(this);
+ }
+
+ // Cache the loaded factory
+ addFactory(factory);
+ }
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e);
+ }
+ } else {
+
+ // Call the newInstance static method on the factory abstract class
+ try {
+ Method newInstanceMethod = factoryInterface.getMethod("newInstance");
+ factory = newInstanceMethod.invoke(null);
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e);
+ }
+
+ // Cache the factory
+ addFactory(factory);
+ }
+ }
+ return factoryInterface.cast(factory);
+ }
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DeployedArtifact.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DeployedArtifact.java
new file mode 100644
index 0000000000..3cde4788d7
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/DeployedArtifact.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+/**
+ * Representation of a deployed artifact
+ *
+ * @version $Rev: 615632 $ $Date: 2008-01-27 11:14:25 -0800 (Sun, 27 Jan 2008) $
+ */
+@Deprecated
+public interface DeployedArtifact extends Artifact {
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java
new file mode 100644
index 0000000000..43d2b54a3d
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * The representation of an export.
+ *
+ * @version $Rev: 615632 $ $Date: 2008-01-27 11:14:25 -0800 (Sun, 27 Jan 2008) $
+ */
+public interface Export {
+
+ /**
+ * Returns the model resolver for the models representing artifacts
+ * made available by this export.
+ *
+ * @return The model resolver
+ */
+ ModelResolver getModelResolver();
+
+ /**
+ * Sets the model resolver for the models representing artifacts
+ * made available by this export.
+ *
+ * @param modelResolver
+ */
+ void setModelResolver(ModelResolver modelResolver);
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java
new file mode 100644
index 0000000000..1f60ba8073
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+
+/**
+ * The representation of an import.
+ *
+ * @version $Rev: 631778 $ $Date: 2008-02-27 15:54:38 -0800 (Wed, 27 Feb 2008) $
+ */
+public interface Import {
+
+ /**
+ * Returns the model resolver for the models representing artifacts
+ * made available by this import.
+ *
+ * @return The model resolver
+ */
+ ModelResolver getModelResolver();
+
+ /**
+ * Sets the model resolver for the models representing artifacts
+ * made available by this import.
+ *
+ * @param modelResolver The model resolver
+ */
+ void setModelResolver(ModelResolver modelResolver);
+
+ /**
+ * Verify that a specific export actually exports what is being imported.
+ *
+ * @param export The Exported being verified
+ * @return true/false
+ */
+ boolean match(Export export);
+
+} \ No newline at end of file
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ModelFactoryExtensionPoint.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ModelFactoryExtensionPoint.java
new file mode 100644
index 0000000000..96decab6da
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/ModelFactoryExtensionPoint.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+/**
+ * An extension point for model factories. Model factories are provided to
+ * abstract the classes that represent artifacts in the assembly model away
+ * from their creation mechanism. When the runtime needs to extend the model
+ * as it reads in contributed artifacts it looks up the factory for the
+ * artifact required in this registry
+ *
+ * @version $Rev: 562796 $ $Date: 2007-08-04 18:20:28 -0700 (Sat, 04 Aug 2007) $
+ */
+public interface ModelFactoryExtensionPoint {
+
+ /**
+ * Add a model factory extension.
+ *
+ * @param factory The factory to add
+ */
+ void addFactory(Object factory);
+
+ /**
+ * Remove a model factory extension.
+ *
+ * @param factory The factory to remove
+ */
+ void removeFactory(Object factory);
+
+ /**
+ * Get a factory implementing the given interface.
+ * @param factoryInterface the lookup key (factory interface)
+ * @return The factory
+ */
+ <T> T getFactory(Class<T> factoryInterface);
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/PackageType.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/PackageType.java
new file mode 100644
index 0000000000..f1e7147959
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/PackageType.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+/**
+ * Constants for the main supported contribution package types.
+ *
+ * @version $Rev: 637139 $ $Date: 2008-03-14 09:02:49 -0700 (Fri, 14 Mar 2008) $
+ */
+public interface PackageType {
+
+ /**
+ * Java compressed contribution package
+ */
+ String JAR = "application/x-compressed";
+
+ /**
+ * Filesystem folder contribution package
+ */
+ String FOLDER = "application/vnd.tuscany.folder";
+
+
+ String BUNDLE = "application/osgi.bundle";
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ArtifactImpl.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ArtifactImpl.java
new file mode 100644
index 0000000000..43a6586815
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ArtifactImpl.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.impl;
+
+import org.apache.tuscany.sca.contribution.Artifact;
+
+
+/**
+ * The model representing an artifact in a contribution.
+ *
+ * @version $Rev: 632520 $ $Date: 2008-02-29 16:58:53 -0800 (Fri, 29 Feb 2008) $
+ */
+class ArtifactImpl implements Artifact {
+ private String uri;
+ private String location;
+ private Object model;
+ private boolean unresolved;
+ private byte[] contents;
+
+ ArtifactImpl() {
+ }
+
+ public String getLocation() {
+ return location;
+ }
+
+ public void setLocation(String location) {
+ this.location = location;
+ }
+
+ public String getURI() {
+ return uri;
+ }
+
+ public void setURI(String uri) {
+ this.uri = uri;
+ }
+
+ public Object getModel() {
+ return model;
+ }
+
+ public void setModel(Object model) {
+ this.model = model;
+ }
+
+ public byte[] getContents() {
+ return contents;
+ }
+
+ public void setContents(byte[] contents) {
+ this.contents = contents;
+ }
+
+ public boolean isUnresolved() {
+ return unresolved;
+ }
+
+ public void setUnresolved(boolean unresolved) {
+ this.unresolved = unresolved;
+ }
+
+ @Override
+ public int hashCode() {
+ return uri.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ } else {
+ if (obj instanceof Artifact) {
+ return uri.equals(((Artifact)obj).getURI());
+ } else {
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Artifact:" + uri + "\n" +
+ "at: " + location;
+ }
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionFactoryImpl.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionFactoryImpl.java
new file mode 100644
index 0000000000..c545fd6e08
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionFactoryImpl.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.impl;
+
+import org.apache.tuscany.sca.contribution.Artifact;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.ContributionFactory;
+import org.apache.tuscany.sca.contribution.DeployedArtifact;
+
+
+/**
+ * Default implementation of a contribution model factory.
+ *
+ * @version $Rev: 629585 $ $Date: 2008-02-20 11:39:27 -0800 (Wed, 20 Feb 2008) $
+ */
+public class ContributionFactoryImpl implements ContributionFactory {
+
+ public ContributionFactoryImpl() {
+ }
+
+ public Contribution createContribution() {
+ return new ContributionImpl();
+ }
+
+ public Artifact createArtifact() {
+ return new ArtifactImpl();
+ }
+
+ @Deprecated
+ public DeployedArtifact createDeployedArtifact() {
+ class DeployedArtifactImpl extends ArtifactImpl implements DeployedArtifact {
+ }
+ return new DeployedArtifactImpl();
+ }
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionImpl.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionImpl.java
new file mode 100644
index 0000000000..3239bfd003
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionImpl.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.contribution.Artifact;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.Export;
+import org.apache.tuscany.sca.contribution.Import;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * The representation of a deployed contribution
+ *
+ * @version $Rev: 639257 $ $Date: 2008-03-20 05:12:00 -0700 (Thu, 20 Mar 2008) $
+ */
+class ContributionImpl implements Contribution {
+ private String uri;
+ private String location;
+ private Object model;
+ private byte[] contents;
+ private boolean unresolved;
+ private List<Export> exports = new ArrayList<Export>();
+ private List<Import> imports = new ArrayList<Import>();
+ private List<Composite> deployables = new ArrayList<Composite>();
+ private List<Artifact> artifacts = new ArrayList<Artifact>();
+ private ModelResolver modelResolver;
+
+ // FIXME remove this dependency on Java ClassLoaders
+ private ClassLoader classLoader;
+
+ ContributionImpl() {
+ }
+
+ public String getLocation() {
+ return this.location;
+ }
+
+ public void setLocation(String location) {
+ this.location = location;
+ }
+
+ //FIXME Remove dependency on Java ClassLoaders
+ public ClassLoader getClassLoader() {
+ return classLoader;
+ }
+
+ //FIXME Remove dependency on Java ClassLoaders
+ public void setClassLoader(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+
+ public String getURI() {
+ return this.uri;
+ }
+
+ public void setURI(String uri) {
+ this.uri = uri;
+ }
+
+ public Object getModel() {
+ return model;
+ }
+
+ public void setModel(Object model) {
+ this.model = model;
+ }
+
+ public byte[] getContents() {
+ return contents;
+ }
+
+ public void setContents(byte[] contents) {
+ this.contents = contents;
+ }
+
+ public boolean isUnresolved() {
+ return unresolved;
+ }
+
+ public void setUnresolved(boolean unresolved) {
+ this.unresolved = unresolved;
+ }
+
+ public ModelResolver getModelResolver() {
+ return modelResolver;
+ }
+
+ public void setModelResolver(ModelResolver modelResolver) {
+ this.modelResolver = modelResolver;
+ }
+
+ public List<Export> getExports() {
+ return exports;
+ }
+
+ public List<Import> getImports() {
+ return imports;
+ }
+
+ public List<Composite> getDeployables() {
+ return deployables;
+ }
+
+ public List<Artifact> getArtifacts() {
+ return artifacts;
+ }
+
+ @Override
+ public int hashCode() {
+ return uri.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ } else {
+ if (obj instanceof Artifact) {
+ return uri.equals(((Artifact)obj).getURI());
+ } else {
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Contribution : " + uri + " \n" +
+ "from: " + location;
+ }
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java
new file mode 100644
index 0000000000..f9116134fa
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.service.ContributionResolveException;
+
+/**
+ * Base interface for artifact processors.
+ *
+ * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $
+ */
+public interface ArtifactProcessor<M> {
+
+ /**
+ * Resolve references from this model to other models. For example references
+ * from a composite to another one, or references from a composite to a WSDL
+ * model.
+ *
+ * @param model The model to resolve
+ * @param resolver The resolver to use to resolve referenced models
+ */
+ void resolve(M model, ModelResolver resolver) throws ContributionResolveException;
+
+ /**
+ * Returns the type of model handled by this artifact processor.
+ *
+ * @return The type of model handled by this artifact processor
+ */
+ Class<M> getModelType();
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessorExtensionPoint.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..cf5956a8e7
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessorExtensionPoint.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+/**
+ * An extension point for artifact processors.
+ *
+ * @version $Rev: 616133 $ $Date: 2008-01-28 17:45:50 -0800 (Mon, 28 Jan 2008) $
+ */
+public interface ArtifactProcessorExtensionPoint<P extends ArtifactProcessor> {
+
+ /**
+ * Add an artifact processor.
+ *
+ * @param artifactProcessor The artifact processor to add
+ */
+ void addArtifactProcessor(P artifactProcessor);
+
+ /**
+ * Remove an artifact processor.
+ *
+ * @param artifactProcessor The artifact processor to remove
+ */
+ void removeArtifactProcessor(P artifactProcessor);
+
+ /**
+ * Returns the processor associated with the given artifact type.
+ *
+ * @param artifactType An artifact type
+ * @return The processor associated with the given artifact type
+ */
+ P getProcessor(Object artifactType);
+
+ /**
+ * Returns the processor associated with the given model type.
+ *
+ * @param modelType A model type
+ * @return The processor associated with the given model type
+ */
+ P getProcessor(Class<?> modelType);
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java
new file mode 100644
index 0000000000..832a82a4f0
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java
@@ -0,0 +1,512 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+
+/**
+ * A base class with utility methods for the other artifact processors in this module.
+ *
+ * @version $Rev: 639257 $ $Date: 2008-03-20 05:12:00 -0700 (Thu, 20 Mar 2008) $
+ */
+public abstract class BaseStAXArtifactProcessor {
+
+ /**
+ * Returns a QName from a string.
+ * @param reader
+ * @param value
+ * @return
+ */
+ protected QName getQNameValue(XMLStreamReader reader, String value) {
+ if (value != null) {
+ int index = value.indexOf(':');
+ String prefix = index == -1 ? "" : value.substring(0, index);
+ String localName = index == -1 ? value : value.substring(index + 1);
+ String ns = reader.getNamespaceContext().getNamespaceURI(prefix);
+ if (ns == null) {
+ ns = "";
+ }
+ return new QName(ns, localName, prefix);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the boolean value of an attribute.
+ * @param reader
+ * @param name
+ * @return
+ */
+ protected boolean getBoolean(XMLStreamReader reader, String name) {
+ String value = reader.getAttributeValue(null, name);
+ if (value == null) {
+ return false;
+ }
+ return Boolean.valueOf(value);
+ }
+
+ /**
+ * Returns the QName value of an attribute.
+ * @param reader
+ * @param name
+ * @return
+ */
+ protected QName getQName(XMLStreamReader reader, String name) {
+ String qname = reader.getAttributeValue(null, name);
+ return getQNameValue(reader, qname);
+ }
+
+ /**
+ * Returns the value of an attribute as a list of QNames.
+ * @param reader
+ * @param name
+ * @return
+ */
+ protected List<QName> getQNames(XMLStreamReader reader, String name) {
+ String value = reader.getAttributeValue(null, name);
+ if (value != null) {
+ List<QName> qnames = new ArrayList<QName>();
+ for (StringTokenizer tokens = new StringTokenizer(value); tokens.hasMoreTokens();) {
+ qnames.add(getQName(reader, tokens.nextToken()));
+ }
+ return qnames;
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ /**
+ * Returns the string value of an attribute.
+ * @param reader
+ * @param name
+ * @return
+ */
+ protected String getString(XMLStreamReader reader, String name) {
+ return reader.getAttributeValue(null, name);
+ }
+
+ /**
+ * Test if an attribute is explicitly set
+ * @param reader
+ * @param name
+ * @return
+ */
+ protected boolean isSet(XMLStreamReader reader, String name) {
+ return reader.getAttributeValue(null, name) != null;
+ }
+
+ /**
+ * Returns the value of xsi:type attribute
+ * @param reader The XML stream reader
+ * @return The QName of the type, if the attribute is not present, null is
+ * returned.
+ */
+ protected QName getXSIType(XMLStreamReader reader) {
+ String qname = reader.getAttributeValue(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type");
+ return getQNameValue(reader, qname);
+ }
+
+ /**
+ * Parse the next child element.
+ * @param reader
+ * @return
+ * @throws XMLStreamException
+ */
+ protected boolean nextChildElement(XMLStreamReader reader) throws XMLStreamException {
+ while (reader.hasNext()) {
+ int event = reader.next();
+ if (event == END_ELEMENT) {
+ return false;
+ }
+ if (event == START_ELEMENT) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Advance the stream to the next END_ELEMENT event skipping any nested
+ * content.
+ * @param reader the reader to advance
+ * @throws XMLStreamException if there was a problem reading the stream
+ */
+ protected void skipToEndElement(XMLStreamReader reader) throws XMLStreamException {
+ int depth = 0;
+ while (reader.hasNext()) {
+ int event = reader.next();
+ if (event == XMLStreamConstants.START_ELEMENT) {
+ depth++;
+ } else if (event == XMLStreamConstants.END_ELEMENT) {
+ if (depth == 0) {
+ return;
+ }
+ depth--;
+ }
+ }
+ }
+
+ /**
+ *
+ * @param writer
+ * @param uri
+ * @throws XMLStreamException
+ */
+ private String writeElementPrefix(XMLStreamWriter writer, String uri) throws XMLStreamException {
+ if (uri == null) {
+ return null;
+ }
+ String prefix = writer.getPrefix(uri);
+ if (prefix != null) {
+ return null;
+ } else {
+
+ // Find an available prefix and bind it to the given URI
+ NamespaceContext nsc = writer.getNamespaceContext();
+ for (int i=1; ; i++) {
+ prefix = "ns" + i;
+ if (nsc.getNamespaceURI(prefix) == null) {
+ break;
+ }
+ }
+ writer.setPrefix(prefix, uri);
+ return prefix;
+ }
+
+ }
+
+ /**
+ * Start an element.
+ * @param uri
+ * @param name
+ * @param attrs
+ * @throws XMLStreamException
+ */
+ protected void writeStart(XMLStreamWriter writer, String uri, String name, XAttr... attrs) throws XMLStreamException {
+ String prefix = writeElementPrefix(writer, uri);
+ writeAttributePrefixes(writer, attrs);
+ writer.writeStartElement(uri, name);
+
+ if (prefix != null){
+ writer.writeNamespace(prefix,uri);
+ }
+ writeAttributes(writer, attrs);
+ }
+
+ /**
+ * Start an element.
+ * @param qname
+ * @param attrs
+ * @throws XMLStreamException
+ */
+ protected void writeStart(XMLStreamWriter writer, QName qname, XAttr... attrs) throws XMLStreamException {
+ writeStart(writer, qname.getNamespaceURI(), qname.getLocalPart(), attrs);
+ }
+
+ /**
+ * End an element.
+ * @param writer
+ * @throws XMLStreamException
+ */
+ protected void writeEnd(XMLStreamWriter writer) throws XMLStreamException {
+ writer.writeEndElement();
+ }
+
+ /**
+ * Start a document.
+ * @param writer
+ * @throws XMLStreamException
+ */
+ protected void writeStartDocument(XMLStreamWriter writer, String uri, String name, XAttr... attrs) throws XMLStreamException {
+ writer.writeStartDocument();
+ writer.setDefaultNamespace(uri);
+ writeStart(writer, uri, name, attrs);
+ writer.writeDefaultNamespace(uri);
+ }
+
+ /**
+ * Start a document.
+ * @param writer
+ * @param qname
+ * @param attrs
+ * @throws XMLStreamException
+ */
+ protected void writeStartDocument(XMLStreamWriter writer, QName qname, XAttr... attrs) throws XMLStreamException {
+ writeStartDocument(writer, qname.getNamespaceURI(), qname.getLocalPart(), attrs);
+ }
+
+ /**
+ * End a document.
+ * @param writer
+ * @throws XMLStreamException
+ */
+ protected void writeEndDocument(XMLStreamWriter writer) throws XMLStreamException {
+ writer.writeEndDocument();
+ }
+
+ /**
+ * Write attributes to the current element.
+ * @param writer
+ * @param attrs
+ * @throws XMLStreamException
+ */
+ protected void writeAttributes(XMLStreamWriter writer, XAttr... attrs) throws XMLStreamException {
+ for (XAttr attr : attrs) {
+ if (attr != null)
+ attr.write(writer);
+ }
+ }
+
+ /**
+ * Write attribute prefixes to the current element.
+ * @param writer
+ * @param attrs
+ * @throws XMLStreamException
+ */
+ protected void writeAttributePrefixes(XMLStreamWriter writer, XAttr... attrs) throws XMLStreamException {
+ for (XAttr attr : attrs) {
+ if (attr != null)
+ attr.writePrefix(writer);
+ }
+ }
+
+ /**
+ * Represents an XML attribute that needs to be written to a document.
+ */
+ public static class XAttr {
+
+ private static final String SCA10_NS = "http://www.osoa.org/xmlns/sca/1.0";
+
+ private String uri = SCA10_NS;
+ private String name;
+ private Object value;
+
+ public XAttr(String uri, String name, String value) {
+ this.uri = uri;
+ this.name = name;
+ this.value = value;
+ }
+
+ public XAttr(String name, String value) {
+ this(null, name, value);
+ }
+
+ public XAttr(String uri, String name, List<?> values) {
+ this.uri = uri;
+ this.name = name;
+ this.value = values;
+ }
+
+ public XAttr(String name, List<?> values) {
+ this(null, name, values);
+ }
+
+ public XAttr(String uri, String name, Boolean value) {
+ this.uri = uri;
+ this.name = name;
+ this.value = value;
+ }
+
+ public XAttr(String name, Boolean value) {
+ this(null, name, value);
+ }
+
+ public XAttr(String uri, String name, QName value) {
+ this.uri = uri;
+ this.name = name;
+ this.value = value;
+ }
+
+ public XAttr(String name, QName value) {
+ this(null, name, value);
+ }
+
+ /**
+ * Writes a string from a QName and registers a prefix for its namespace.
+ * @param reader
+ * @param value
+ * @return
+ */
+ private String writeQNameValue(XMLStreamWriter writer, QName qname) throws XMLStreamException {
+ if (qname != null) {
+ String prefix = qname.getPrefix();
+ String uri = qname.getNamespaceURI();
+ prefix = writer.getPrefix(uri);
+ if (prefix != null && prefix.length() > 0) {
+
+ // Use the prefix already bound to the given URI
+ return prefix + ":" + qname.getLocalPart();
+ } else {
+
+ // Find an available prefix and bind it to the given URI
+ NamespaceContext nsc = writer.getNamespaceContext();
+ for (int i=1; ; i++) {
+ prefix = "ns" + i;
+ if (nsc.getNamespaceURI(prefix) == null) {
+ break;
+ }
+ }
+ writer.setPrefix(prefix, uri);
+ writer.writeNamespace(prefix, uri);
+ return prefix + ":" + qname.getLocalPart();
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Registers a prefix for the namespace of a QName.
+ * @param reader
+ * @param value
+ * @return
+ */
+ private void writeQNamePrefix(XMLStreamWriter writer, QName qname) throws XMLStreamException {
+ if (qname != null) {
+ String prefix = qname.getPrefix();
+ String uri = qname.getNamespaceURI();
+ prefix = writer.getPrefix(uri);
+ if (prefix != null) {
+ return;
+ } else {
+
+ // Find an available prefix and bind it to the given URI
+ NamespaceContext nsc = writer.getNamespaceContext();
+ for (int i=1; ; i++) {
+ prefix = "ns" + i;
+ if (nsc.getNamespaceURI(prefix) == null) {
+ break;
+ }
+ }
+ writer.setPrefix(prefix, uri);
+ }
+ }
+ }
+
+ /**
+ * Write to document
+ * @param writer
+ * @throws XMLStreamException
+ */
+ public void write(XMLStreamWriter writer) throws XMLStreamException {
+ String str;
+ if (value instanceof QName) {
+
+ // Write a QName
+ str = writeQNameValue(writer, (QName)value);
+
+ } else if (value instanceof List) {
+
+ // Write a list of values
+ List<?> values = (List<?>)value;
+ if (values.isEmpty()) {
+ return;
+ }
+ StringBuffer buffer = new StringBuffer();
+ for (Object v: values) {
+ if (v == null) {
+ // Skip null values
+ continue;
+ }
+
+ if (v instanceof XAttr) {
+ // Write an XAttr value
+ ((XAttr)v).write(writer);
+ continue;
+ }
+
+ if (buffer.length() != 0) {
+ buffer.append(' ');
+ }
+ if (v instanceof QName) {
+ // Write a QName value
+ buffer.append(writeQNameValue(writer, (QName)v));
+ } else {
+ // Write value as a string
+ buffer.append(String.valueOf(v));
+ }
+ }
+ str = buffer.toString();
+
+ } else {
+
+ // Write a string
+ if (value == null) {
+ return;
+ }
+ str = String.valueOf(value);
+ }
+ if (str.length() == 0) {
+ return;
+ }
+
+ // Write the attribute
+ if (uri != null && !uri.equals(SCA10_NS)) {
+ writer.writeAttribute(uri, name, str);
+ } else {
+ writer.writeAttribute(name,str);
+ }
+ }
+
+ /**
+ * Registers a prefix for the namespace of a QName or list of QNames
+ * @param writer
+ * @throws XMLStreamException
+ */
+ public void writePrefix(XMLStreamWriter writer) throws XMLStreamException {
+ if (value instanceof QName) {
+
+ // Write prefix for a single QName value
+ writeQNamePrefix(writer, (QName)value);
+
+ } else if (value instanceof List) {
+
+ // Write prefixes for a list of values
+ for (Object v: (List<?>)value) {
+ if (v instanceof QName) {
+ // Write prefix for a QName value
+ writeQNamePrefix(writer, (QName)v);
+
+ } else if (v instanceof XAttr) {
+ // Write prefix for an XAttr value
+ ((XAttr)v).writePrefix(writer);
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..68dcf8dbad
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The default implementation of an artifact processor extension point.
+ *
+ * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $
+ */
+abstract class DefaultArtifactProcessorExtensionPoint<P> {
+ protected final Map<Object, P> processorsByArtifactType = new HashMap<Object, P>();
+ protected final Map<Class<?>, P> processorsByModelType = new HashMap<Class<?>, P>();
+
+ /**
+ * Constructs a new loader registry.
+ */
+ DefaultArtifactProcessorExtensionPoint() {
+ }
+
+ /**
+ * Returns the processor associated with the given artifact type.
+ *
+ * @param artifactType An artifact type
+ * @return The processor associated with the given artifact type
+ */
+ public P getProcessor(Object artifactType) {
+ return processorsByArtifactType.get(artifactType);
+ }
+
+ /**
+ * Returns the processor associated with the given model type.
+ *
+ * @param modelType A model type
+ * @return The processor associated with the given model type
+ */
+ public P getProcessor(Class<?> modelType) {
+ Class<?>[] classes = modelType.getInterfaces();
+ for (Class<?> c : classes) {
+ P processor = processorsByModelType.get(c);
+ if (processor != null) {
+ return processor;
+ }
+ }
+ return processorsByModelType.get(modelType);
+ }
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultPackageProcessorExtensionPoint.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultPackageProcessorExtensionPoint.java
new file mode 100644
index 0000000000..2a98478109
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultPackageProcessorExtensionPoint.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tuscany.sca.contribution.service.ContributionException;
+import org.apache.tuscany.sca.extensibility.ServiceDeclaration;
+import org.apache.tuscany.sca.extensibility.ServiceDiscovery;
+
+/**
+ * Default implementation of a package processor extension point.
+ *
+ * @version $Rev: 632642 $ $Date: 2008-03-01 10:16:44 -0800 (Sat, 01 Mar 2008) $
+ */
+public class DefaultPackageProcessorExtensionPoint implements PackageProcessorExtensionPoint {
+
+ private Map<String, PackageProcessor> processors = new HashMap<String, PackageProcessor>();
+ private boolean loaded;
+
+ public DefaultPackageProcessorExtensionPoint() {
+ }
+
+ public void addPackageProcessor(PackageProcessor processor) {
+ processors.put(processor.getPackageType(), processor);
+ }
+
+ public void removePackageProcessor(PackageProcessor processor) {
+ processors.remove(processor.getPackageType());
+ }
+
+ public PackageProcessor getPackageProcessor(String contentType) {
+ loadProcessors();
+ return processors.get(contentType);
+ }
+
+ private void loadProcessors() {
+ if (loaded)
+ return;
+
+ // Get the processor service declarations
+ Set<ServiceDeclaration> processorDeclarations;
+ try {
+ processorDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(PackageProcessor.class);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+
+ for (ServiceDeclaration processorDeclaration: processorDeclarations) {
+ Map<String, String> attributes = processorDeclaration.getAttributes();
+
+ // Load a URL artifact processor
+ String packageType = attributes.get("type");
+
+ // Create a processor wrapper and register it
+ PackageProcessor processor = new LazyPackageProcessor(packageType, processorDeclaration);
+ addPackageProcessor(processor);
+ }
+
+ loaded = true;
+ }
+
+ /**
+ * A facade for package processors.
+ */
+ private static class LazyPackageProcessor implements PackageProcessor {
+
+ private ServiceDeclaration processorDeclaration;
+ private String packageType;
+ private PackageProcessor processor;
+
+ private LazyPackageProcessor(String packageType, ServiceDeclaration processorDeclaration) {
+ this.processorDeclaration = processorDeclaration;
+ this.packageType = packageType;
+ }
+
+ public URL getArtifactURL(URL packageSourceURL, URI artifact) throws MalformedURLException {
+ return getProcessor().getArtifactURL(packageSourceURL, artifact);
+ }
+
+ public List<URI> getArtifacts(URL packageSourceURL, InputStream inputStream) throws ContributionException, IOException {
+ return getProcessor().getArtifacts(packageSourceURL, inputStream);
+ }
+
+ public String getPackageType() {
+ return packageType;
+ }
+
+ @SuppressWarnings("unchecked")
+ private PackageProcessor getProcessor() {
+ if (processor == null) {
+ try {
+ Class<PackageProcessor> processorClass = (Class<PackageProcessor>)processorDeclaration.loadClass();
+ Constructor<PackageProcessor> constructor = processorClass.getConstructor();
+ processor = constructor.newInstance();
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ return processor;
+ }
+ }
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..f9c21947f7
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.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.sca.contribution.processor;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.service.ContributionReadException;
+import org.apache.tuscany.sca.contribution.service.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.service.ContributionWriteException;
+import org.apache.tuscany.sca.extensibility.ServiceDeclaration;
+import org.apache.tuscany.sca.extensibility.ServiceDiscovery;
+import org.apache.tuscany.sca.policy.PolicyFactory;
+
+/**
+ * The default implementation of an extension point for StAX artifact processors.
+ *
+ * @version $Rev: 639257 $ $Date: 2008-03-20 05:12:00 -0700 (Thu, 20 Mar 2008) $
+ */
+public class DefaultStAXArtifactProcessorExtensionPoint extends
+ DefaultArtifactProcessorExtensionPoint<StAXArtifactProcessor> implements StAXArtifactProcessorExtensionPoint {
+
+ private ModelFactoryExtensionPoint modelFactories;
+ private boolean loaded;
+
+ /**
+ * Constructs a new extension point.
+ */
+ public DefaultStAXArtifactProcessorExtensionPoint(ModelFactoryExtensionPoint modelFactories) {
+ this.modelFactories = modelFactories;
+ }
+
+ public void addArtifactProcessor(StAXArtifactProcessor artifactProcessor) {
+ processorsByArtifactType.put((Object)artifactProcessor.getArtifactType(), artifactProcessor);
+ processorsByModelType.put(artifactProcessor.getModelType(), artifactProcessor);
+ }
+
+ public void removeArtifactProcessor(StAXArtifactProcessor artifactProcessor) {
+ processorsByArtifactType.remove((Object)artifactProcessor.getArtifactType());
+ processorsByModelType.remove(artifactProcessor.getModelType());
+ }
+
+ @Override
+ public StAXArtifactProcessor getProcessor(Class<?> modelType) {
+ loadArtifactProcessors();
+ return super.getProcessor(modelType);
+ }
+
+ @Override
+ public StAXArtifactProcessor getProcessor(Object artifactType) {
+ loadArtifactProcessors();
+ return super.getProcessor(artifactType);
+ }
+
+ /**
+ * Returns a QName object from a QName expressed as {ns}name
+ * or ns#name.
+ *
+ * @param qname
+ * @return
+ */
+ private static QName getQName(String qname) {
+ if (qname == null) {
+ return null;
+ }
+ qname = qname.trim();
+ if (qname.startsWith("{")) {
+ int h = qname.indexOf('}');
+ if (h != -1) {
+ return new QName(qname.substring(1, h), qname.substring(h + 1));
+ }
+ } else {
+ int h = qname.indexOf('#');
+ if (h != -1) {
+ return new QName(qname.substring(0, h), qname.substring(h + 1));
+ }
+ }
+ throw new IllegalArgumentException("Invalid qname: "+qname);
+ }
+
+ /**
+ * Lazily load artifact processors registered in the extension point.
+ */
+ private void loadArtifactProcessors() {
+ if (loaded)
+ return;
+
+ // Get the processor service declarations
+ Set<ServiceDeclaration> processorDeclarations;
+ try {
+ processorDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(StAXArtifactProcessor.class);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+
+ for (ServiceDeclaration processorDeclaration : processorDeclarations) {
+ Map<String, String> attributes = processorDeclaration.getAttributes();
+
+ // Load a StAX artifact processor
+
+ // Get the model QName
+ QName artifactType = getQName(attributes.get("qname"));
+
+ // Get the model class name
+ String modelTypeName = attributes.get("model");
+
+ // Get the model factory class name
+ String factoryName = attributes.get("factory");
+
+ // Create a processor wrapper and register it
+ StAXArtifactProcessor processor =
+ new LazyStAXArtifactProcessor(modelFactories, artifactType, modelTypeName, factoryName,
+ processorDeclaration);
+ addArtifactProcessor(processor);
+ }
+
+ loaded = true;
+ }
+
+ /**
+ * A wrapper around an Artifact processor class allowing lazy loading and
+ * initialization of artifact processors.
+ */
+ private static class LazyStAXArtifactProcessor implements StAXArtifactProcessor {
+
+ private ModelFactoryExtensionPoint modelFactories;
+ private QName artifactType;
+ private String modelTypeName;
+ private String factoryName;
+ private ServiceDeclaration processorDeclaration;
+ private StAXArtifactProcessor processor;
+ private Class<?> modelType;
+
+ LazyStAXArtifactProcessor(ModelFactoryExtensionPoint modelFactories,
+ QName artifactType,
+ String modelTypeName,
+ String factoryName,
+ ServiceDeclaration processorDeclaration) {
+
+ this.modelFactories = modelFactories;
+ this.artifactType = artifactType;
+ this.modelTypeName = modelTypeName;
+ this.factoryName = factoryName;
+ this.processorDeclaration = processorDeclaration;
+ }
+
+ public QName getArtifactType() {
+ return artifactType;
+ }
+
+ @SuppressWarnings("unchecked")
+ private StAXArtifactProcessor getProcessor() {
+ if (processor == null) {
+
+ if (processorDeclaration.getClassName()
+ .equals("org.apache.tuscany.sca.assembly.xml.DefaultBeanModelProcessor")) {
+
+ // Specific initialization for the DefaultBeanModelProcessor
+ AssemblyFactory assemblyFactory = modelFactories.getFactory(AssemblyFactory.class);
+ PolicyFactory policyFactory = modelFactories.getFactory(PolicyFactory.class);
+ try {
+ Class<StAXArtifactProcessor> processorClass =
+ (Class<StAXArtifactProcessor>)processorDeclaration.loadClass();
+ Object modelFactory;
+ if (factoryName != null) {
+ Class<?> factoryClass = (Class<?>)processorDeclaration.loadClass(factoryName);
+ modelFactory = modelFactories.getFactory(factoryClass);
+ } else {
+ modelFactory = null;
+ }
+ Constructor<StAXArtifactProcessor> constructor =
+ processorClass.getConstructor(AssemblyFactory.class,
+ PolicyFactory.class,
+ QName.class,
+ Class.class,
+ Object.class);
+ processor =
+ constructor.newInstance(assemblyFactory,
+ policyFactory,
+ artifactType,
+ getModelType(),
+ modelFactory);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ } else {
+
+ // Load and instantiate the processor class
+ try {
+ Class<StAXArtifactProcessor> processorClass =
+ (Class<StAXArtifactProcessor>)processorDeclaration.loadClass();
+ Constructor<StAXArtifactProcessor> constructor =
+ processorClass.getConstructor(ModelFactoryExtensionPoint.class);
+ processor = constructor.newInstance(modelFactories);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+ return processor;
+ }
+
+ public Object read(XMLStreamReader inputSource) throws ContributionReadException, XMLStreamException {
+ return getProcessor().read(inputSource);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void write(Object model, XMLStreamWriter outputSource) throws ContributionWriteException,
+ XMLStreamException {
+ getProcessor().write(model, outputSource);
+ }
+
+ public Class<?> getModelType() {
+ if (modelType == null) {
+ try {
+ modelType = processorDeclaration.loadClass(modelTypeName);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ return modelType;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void resolve(Object model, ModelResolver resolver) throws ContributionResolveException {
+ getProcessor().resolve(model, resolver);
+ }
+
+ }
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..574ffc5f04
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.net.URI;
+import java.net.URL;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.service.ContributionReadException;
+import org.apache.tuscany.sca.contribution.service.ContributionResolveException;
+import org.apache.tuscany.sca.extensibility.ServiceDeclaration;
+import org.apache.tuscany.sca.extensibility.ServiceDiscovery;
+
+/**
+ * The default implementation of a URL artifact processor extension point.
+ *
+ * @version $Rev: 632642 $ $Date: 2008-03-01 10:16:44 -0800 (Sat, 01 Mar 2008) $
+ */
+public class DefaultURLArtifactProcessorExtensionPoint
+ extends DefaultArtifactProcessorExtensionPoint<URLArtifactProcessor>
+ implements URLArtifactProcessorExtensionPoint {
+
+ private ModelFactoryExtensionPoint modelFactories;
+ private boolean loaded;
+
+ /**
+ * Constructs a new extension point.
+ */
+ public DefaultURLArtifactProcessorExtensionPoint(ModelFactoryExtensionPoint modelFactories) {
+ this.modelFactories = modelFactories;
+ }
+
+ public void addArtifactProcessor(URLArtifactProcessor artifactProcessor) {
+ processorsByArtifactType.put((Object)artifactProcessor.getArtifactType(), artifactProcessor);
+ processorsByModelType.put(artifactProcessor.getModelType(), artifactProcessor);
+ }
+
+ public void removeArtifactProcessor(URLArtifactProcessor artifactProcessor) {
+ processorsByArtifactType.remove((Object)artifactProcessor.getArtifactType());
+ processorsByModelType.remove(artifactProcessor.getModelType());
+ }
+
+ @Override
+ public URLArtifactProcessor getProcessor(Class<?> modelType) {
+ loadProcessors();
+ return super.getProcessor(modelType);
+ }
+
+ @Override
+ public URLArtifactProcessor getProcessor(Object artifactType) {
+ loadProcessors();
+ return super.getProcessor(artifactType);
+ }
+
+ /**
+ * Lazily load artifact processors registered in the extension point.
+ */
+ private void loadProcessors() {
+ if (loaded)
+ return;
+
+ // Get the processor service declarations
+ Set<ServiceDeclaration> processorDeclarations;
+ try {
+ processorDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(URLArtifactProcessor.class);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+
+ for (ServiceDeclaration processorDeclaration: processorDeclarations) {
+ Map<String, String> attributes = processorDeclaration.getAttributes();
+ // Load a URL artifact processor
+ String artifactType = attributes.get("type");
+ String modelTypeName = attributes.get("model");
+
+ // Create a processor wrapper and register it
+ URLArtifactProcessor processor = new LazyURLArtifactProcessor(modelFactories, artifactType, modelTypeName, processorDeclaration);
+ addArtifactProcessor(processor);
+ }
+
+ loaded = true;
+ }
+
+ /**
+ * A wrapper around an Artifact processor class allowing lazy loading and
+ * initialization of artifact processors.
+ */
+ private static class LazyURLArtifactProcessor implements URLArtifactProcessor {
+
+ private ModelFactoryExtensionPoint modelFactories;
+ private String artifactType;
+ private String modelTypeName;
+ private ServiceDeclaration processorDeclaration;
+ private URLArtifactProcessor processor;
+ private Class<?> modelType;
+
+ LazyURLArtifactProcessor(ModelFactoryExtensionPoint modelFactories,
+ String artifactType,
+ String modelTypeName,
+ ServiceDeclaration processorDeclaration) {
+ this.modelFactories = modelFactories;
+ this.artifactType = artifactType;
+ this.modelTypeName = modelTypeName;
+ this.processorDeclaration = processorDeclaration;
+ }
+
+ public String getArtifactType() {
+ return artifactType;
+ }
+
+ @SuppressWarnings("unchecked")
+ private URLArtifactProcessor getProcessor() {
+ if (processor == null) {
+ try {
+ Class<URLArtifactProcessor> processorClass = (Class<URLArtifactProcessor>)processorDeclaration.loadClass();
+ Constructor<URLArtifactProcessor> constructor = processorClass.getConstructor(ModelFactoryExtensionPoint.class);
+ processor = constructor.newInstance(modelFactories);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ return processor;
+ }
+
+ public Object read(URL contributionURL, URI artifactURI, URL artifactURL) throws ContributionReadException {
+ return getProcessor().read(contributionURL, artifactURI, artifactURL);
+ }
+
+ public Class<?> getModelType() {
+ if (modelType == null) {
+ try {
+ modelType = processorDeclaration.loadClass(modelTypeName);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ return modelType;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void resolve(Object model, ModelResolver resolver) throws ContributionResolveException {
+ getProcessor().resolve(model, resolver);
+ }
+
+ }
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java
new file mode 100644
index 0000000000..dcb2c05186
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java
@@ -0,0 +1,236 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.net.URLConnection;
+import java.util.List;
+
+import javax.xml.XMLConstants;
+import javax.xml.stream.EventFilter;
+import javax.xml.stream.StreamFilter;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLReporter;
+import javax.xml.stream.XMLResolver;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.util.XMLEventAllocator;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * Default implementation of an XMLInputFactory that creates validating
+ * XMLStreamReaders.
+ *
+ * @version $Rev: 641645 $ $Date: 2008-03-26 15:37:28 -0800 (Wed, 26 Mar 2008) $
+ */
+public class DefaultValidatingXMLInputFactory extends XMLInputFactory {
+
+ private XMLInputFactory inputFactory;
+ private ValidationSchemaExtensionPoint schemas;
+ private boolean initialized;
+ private Schema aggregatedSchema;
+
+ /**
+ * Constructs a new XMLInputFactory.
+ *
+ * @param inputFactory
+ * @param schemas
+ */
+ public DefaultValidatingXMLInputFactory(XMLInputFactory inputFactory, ValidationSchemaExtensionPoint schemas) {
+ this.inputFactory = inputFactory;
+ this.schemas = schemas;
+ }
+
+ /**
+ * Initialize the registered schemas and create an aggregated schema for
+ * validation.
+ */
+ private void initializeSchemas() {
+ if (initialized) {
+ return;
+ }
+ initialized = true;
+
+ // Load the XSDs registered in the validation schema extension point
+ try {
+ List<String> uris = schemas.getSchemas();
+ int n = uris.size();
+ final Source[] sources = new Source[n];
+ for (int i =0; i < n; i++) {
+ final String uri = uris.get(i);
+ // Allow privileged access to open URL stream. Requires FilePermission in security policy.
+ final URL url = new URL( uri );
+ InputStream urlStream;
+ try {
+ urlStream = AccessController.doPrivileged(new PrivilegedExceptionAction<InputStream>() {
+ public InputStream run() throws IOException {
+ URLConnection connection = url.openConnection();
+ connection.setUseCaches(false);
+ return connection.getInputStream();
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw (IOException)e.getException();
+ }
+ sources[i] = new StreamSource(urlStream, uri);
+ }
+
+ // Create an aggregated validation schemas from all the XSDs
+ final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ // Allow privileged access to check files. Requires FilePermission
+ // in security policy.
+ try {
+ aggregatedSchema = AccessController.doPrivileged(new PrivilegedExceptionAction<Schema>() {
+ public Schema run() throws SAXException {
+ return schemaFactory.newSchema(sources);
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw (SAXException)e.getException();
+ }
+
+ } catch (Error e) {
+ // FIXME Log this, some old JDKs don't support XMLSchema validation
+ //e.printStackTrace();
+ } catch (SAXParseException e) {
+ throw new IllegalStateException(e);
+ } catch (Exception e) {
+ //FIXME Log this, some old JDKs don't support XMLSchema validation
+ e.printStackTrace();
+ }
+ }
+
+ public XMLEventReader createFilteredReader(XMLEventReader arg0, EventFilter arg1) throws XMLStreamException {
+ return inputFactory.createFilteredReader(arg0, arg1);
+ }
+
+ public XMLStreamReader createFilteredReader(XMLStreamReader arg0, StreamFilter arg1) throws XMLStreamException {
+ return inputFactory.createFilteredReader(arg0, arg1);
+ }
+
+ public XMLEventReader createXMLEventReader(InputStream arg0, String arg1) throws XMLStreamException {
+ return inputFactory.createXMLEventReader(arg0, arg1);
+ }
+
+ public XMLEventReader createXMLEventReader(InputStream arg0) throws XMLStreamException {
+ return inputFactory.createXMLEventReader(arg0);
+ }
+
+ public XMLEventReader createXMLEventReader(Reader arg0) throws XMLStreamException {
+ return inputFactory.createXMLEventReader(arg0);
+ }
+
+ public XMLEventReader createXMLEventReader(Source arg0) throws XMLStreamException {
+ return inputFactory.createXMLEventReader(arg0);
+ }
+
+ public XMLEventReader createXMLEventReader(String arg0, InputStream arg1) throws XMLStreamException {
+ return inputFactory.createXMLEventReader(arg0, arg1);
+ }
+
+ public XMLEventReader createXMLEventReader(String arg0, Reader arg1) throws XMLStreamException {
+ return inputFactory.createXMLEventReader(arg0, arg1);
+ }
+
+ public XMLEventReader createXMLEventReader(XMLStreamReader arg0) throws XMLStreamException {
+ return inputFactory.createXMLEventReader(arg0);
+ }
+
+ public XMLStreamReader createXMLStreamReader(InputStream arg0, String arg1) throws XMLStreamException {
+ initializeSchemas();
+ return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0, arg1), aggregatedSchema);
+ }
+
+ public XMLStreamReader createXMLStreamReader(InputStream arg0) throws XMLStreamException {
+ initializeSchemas();
+ return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0), aggregatedSchema);
+ }
+
+ public XMLStreamReader createXMLStreamReader(Reader arg0) throws XMLStreamException {
+ initializeSchemas();
+ return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0), aggregatedSchema);
+ }
+
+ public XMLStreamReader createXMLStreamReader(Source arg0) throws XMLStreamException {
+ initializeSchemas();
+ return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0), aggregatedSchema);
+ }
+
+ public XMLStreamReader createXMLStreamReader(String arg0, InputStream arg1) throws XMLStreamException {
+ initializeSchemas();
+ return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0, arg1), aggregatedSchema);
+ }
+
+ public XMLStreamReader createXMLStreamReader(String arg0, Reader arg1) throws XMLStreamException {
+ initializeSchemas();
+ return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0, arg1), aggregatedSchema);
+ }
+
+ public XMLEventAllocator getEventAllocator() {
+ return inputFactory.getEventAllocator();
+ }
+
+ public Object getProperty(String arg0) throws IllegalArgumentException {
+ return inputFactory.getProperty(arg0);
+ }
+
+ public XMLReporter getXMLReporter() {
+ return inputFactory.getXMLReporter();
+ }
+
+ public XMLResolver getXMLResolver() {
+ return inputFactory.getXMLResolver();
+ }
+
+ public boolean isPropertySupported(String arg0) {
+ return inputFactory.isPropertySupported(arg0);
+ }
+
+ public void setEventAllocator(XMLEventAllocator arg0) {
+ inputFactory.setEventAllocator(arg0);
+ }
+
+ public void setProperty(String arg0, Object arg1) throws IllegalArgumentException {
+ inputFactory.setProperty(arg0, arg1);
+ }
+
+ public void setXMLReporter(XMLReporter arg0) {
+ inputFactory.setXMLReporter(arg0);
+ }
+
+ public void setXMLResolver(XMLResolver arg0) {
+ inputFactory.setXMLResolver(arg0);
+ }
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidationSchemaExtensionPoint.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidationSchemaExtensionPoint.java
new file mode 100644
index 0000000000..e27add9b81
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidationSchemaExtensionPoint.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.tuscany.sca.extensibility.ServiceDeclaration;
+import org.apache.tuscany.sca.extensibility.ServiceDiscovery;
+
+/**
+ * Default implementation of an extension point for XML schemas.
+ *
+ * @version $Rev: 632642 $ $Date: 2008-03-01 10:16:44 -0800 (Sat, 01 Mar 2008) $
+ */
+public class DefaultValidationSchemaExtensionPoint implements ValidationSchemaExtensionPoint {
+
+ private List<String> schemas = new ArrayList<String>();
+ private boolean loaded;
+
+ public void addSchema(String uri) {
+ schemas.add(uri);
+ }
+
+ public void removeSchema(String uri) {
+ schemas.remove(uri);
+ }
+
+ /**
+ * Load schema declarations from META-INF/services/
+ * org.apache.tuscany.sca.contribution.processor.ValidationSchema files
+ */
+ private void loadSchemas() {
+ if (loaded)
+ return;
+
+ // Get the schema declarations
+ Set<ServiceDeclaration> schemaDeclarations;
+ try {
+ schemaDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations("org.apache.tuscany.sca.contribution.processor.ValidationSchema");
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+
+ // Find each schema
+ for (ServiceDeclaration schemaDeclaration: schemaDeclarations) {
+ URL url = schemaDeclaration.getResource();
+ if (url == null) {
+ throw new IllegalArgumentException(new FileNotFoundException(schemaDeclaration.getClassName()));
+ }
+ schemas.add(url.toString());
+ }
+
+ loaded = true;
+ }
+
+ public List<String> getSchemas() {
+ loadSchemas();
+ return schemas;
+ }
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensiblePackageProcessor.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensiblePackageProcessor.java
new file mode 100644
index 0000000000..0b1587d10a
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensiblePackageProcessor.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.util.List;
+
+import org.apache.tuscany.sca.contribution.service.ContributionException;
+import org.apache.tuscany.sca.contribution.service.TypeDescriber;
+import org.apache.tuscany.sca.contribution.service.UnsupportedPackageTypeException;
+
+/**
+ * Implementation of an extensible package processor.
+ *
+ * Takes a package processor extension point and delegates to the proper package
+ * processor from the extension point based on the package's content type.
+ *
+ * @version $Rev: 616149 $ $Date: 2008-01-28 19:10:32 -0800 (Mon, 28 Jan 2008) $
+ */
+public class ExtensiblePackageProcessor implements PackageProcessor {
+
+ private PackageProcessorExtensionPoint processors;
+ private TypeDescriber packageTypeDescriber;
+
+ public ExtensiblePackageProcessor(PackageProcessorExtensionPoint processors, TypeDescriber packageTypeDescriber) {
+ this.processors = processors;
+ this.packageTypeDescriber = packageTypeDescriber;
+ }
+
+ public List<URI> getArtifacts(URL packageSourceURL, InputStream inputStream)
+ throws ContributionException, IOException {
+ String packageType = this.packageTypeDescriber.getType(packageSourceURL, null);
+ if (packageType == null) {
+ throw new UnsupportedPackageTypeException("Unsupported contribution package type: " + packageSourceURL.toString());
+ }
+
+ PackageProcessor packageProcessor = this.processors.getPackageProcessor(packageType);
+ if (packageProcessor == null) {
+ throw new UnsupportedPackageTypeException("Unsupported contribution package type: " + packageType);
+ }
+
+ return packageProcessor.getArtifacts(packageSourceURL, inputStream);
+ }
+
+ public URL getArtifactURL(URL packageSourceURL, URI artifact) throws MalformedURLException {
+ String contentType = this.packageTypeDescriber.getType(packageSourceURL, null);
+ PackageProcessor packageProcessor = this.processors.getPackageProcessor(contentType);
+ return packageProcessor.getArtifactURL(packageSourceURL, artifact);
+ }
+
+ public String getPackageType() {
+ return null;
+ }
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java
new file mode 100644
index 0000000000..ea2bfdd3ac
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.service.ContributionReadException;
+import org.apache.tuscany.sca.contribution.service.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.service.ContributionWriteException;
+import org.apache.tuscany.sca.contribution.service.UnrecognizedElementException;
+
+/**
+ * Implementation of an extensible StAX artifact processor.
+ *
+ * Takes a StAXArtifactProcessorExtensionPoint and delegates to the proper
+ * StAXArtifactProcessor by element QName
+ *
+ * @version $Rev: 639257 $ $Date: 2008-03-20 05:12:00 -0700 (Thu, 20 Mar 2008) $
+ */
+public class ExtensibleStAXArtifactProcessor
+ implements StAXArtifactProcessor<Object> {
+
+ private static final Logger logger = Logger.getLogger(ExtensibleStAXArtifactProcessor.class.getName());
+ private XMLInputFactory inputFactory;
+ private XMLOutputFactory outputFactory;
+ private StAXArtifactProcessorExtensionPoint processors;
+
+ /**
+ * Constructs a new ExtensibleStAXArtifactProcessor.
+ * @param processors
+ * @param inputFactory
+ * @param outputFactory
+ */
+ public ExtensibleStAXArtifactProcessor(StAXArtifactProcessorExtensionPoint processors, XMLInputFactory inputFactory, XMLOutputFactory outputFactory) {
+ super();
+ this.processors = processors;
+ this.inputFactory = inputFactory;
+ this.outputFactory = outputFactory;
+ //this.outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", Boolean.TRUE);
+ }
+
+ public Object read(XMLStreamReader source) throws ContributionReadException, XMLStreamException {
+
+ // Delegate to the processor associated with the element QName
+ QName name = source.getName();
+ StAXArtifactProcessor<?> processor = (StAXArtifactProcessor<?>)processors.getProcessor(name);
+ if (processor == null) {
+ if (logger.isLoggable(Level.WARNING)) {
+ Location location = source.getLocation();
+ logger.warning("Element " + name + " cannot be processed. (" + location + ")");
+ }
+ return null;
+ }
+ return processor.read(source);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void write(Object model, XMLStreamWriter outputSource) throws ContributionWriteException, XMLStreamException {
+
+ // Delegate to the processor associated with the model type
+ if (model != null) {
+ StAXArtifactProcessor processor = processors.getProcessor(model.getClass());
+ if (processor != null) {
+ processor.write(model, outputSource);
+ } else {
+ if (logger.isLoggable(Level.WARNING)) {
+ logger.warning("No StAX processor is configured to handle " + model.getClass());
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public void resolve(Object model, ModelResolver resolver) throws ContributionResolveException {
+
+ // Delegate to the processor associated with the model type
+ if (model != null) {
+ StAXArtifactProcessor processor = processors.getProcessor(model.getClass());
+ if (processor != null) {
+ processor.resolve(model, resolver);
+ }
+ }
+ }
+
+ /**
+ * Read a model from an InputStream.
+ * @param is The artifact InputStream
+ * @param type Model type
+ * @return The model
+ * @throws ContributionReadException
+ */
+ public <M> M read(InputStream is, Class<M> type) throws ContributionReadException {
+ try {
+ XMLStreamReader reader;
+ try {
+ reader = inputFactory.createXMLStreamReader(is);
+ try {
+ reader.nextTag();
+ QName name = reader.getName();
+ Object mo = read(reader);
+ if (type.isInstance(mo)) {
+ return type.cast(mo);
+ } else {
+ UnrecognizedElementException e = new UnrecognizedElementException(name);
+ throw e;
+ }
+ } catch (ContributionReadException e) {
+ Location location = reader.getLocation();
+ e.setLine(location.getLineNumber());
+ e.setColumn(location.getColumnNumber());
+ throw e;
+ } finally {
+ try {
+ reader.close();
+ } catch (XMLStreamException e) {
+ // ignore
+ }
+ }
+ } finally {
+ try {
+ is.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ } catch (XMLStreamException e) {
+ ContributionReadException ce = new ContributionReadException(e);
+ throw ce;
+ }
+ }
+
+ /**
+ * Write a model to an OutputStream.
+ * @param model
+ * @param os
+ * @throws ContributionWriteException
+ */
+ public void write(Object model, OutputStream os) throws ContributionWriteException {
+ try {
+ XMLStreamWriter writer = outputFactory.createXMLStreamWriter(os);
+ write(model, writer);
+ writer.flush();
+ writer.close();
+ } catch (XMLStreamException e) {
+ throw new ContributionWriteException(e);
+ }
+ }
+
+ public QName getArtifactType() {
+ return null;
+ }
+
+ public Class<Object> getModelType() {
+ return null;
+ }
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java
new file mode 100644
index 0000000000..c399800459
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.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.sca.contribution.processor;
+
+import java.net.URI;
+import java.net.URL;
+
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.service.ContributionReadException;
+import org.apache.tuscany.sca.contribution.service.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.service.UnrecognizedElementException;
+
+/**
+ * Implementation of an extensible URL artifact processor.
+ *
+ * Takes a URLArtifactProcessorExtensionPoint and delegates to the proper URLArtifactProcessor
+ * by either fileName or fileExtention
+ *
+ * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $
+ */
+public class ExtensibleURLArtifactProcessor
+ implements URLArtifactProcessor<Object> {
+
+ private URLArtifactProcessorExtensionPoint processors;
+
+ /**
+ * Constructs a new ExtensibleURLArtifactProcessor.
+ *
+ * @param processors
+ */
+ public ExtensibleURLArtifactProcessor(URLArtifactProcessorExtensionPoint processors) {
+ this.processors = processors;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object read(URL contributionURL, URI sourceURI, URL sourceURL) throws ContributionReadException {
+ URLArtifactProcessor<Object> processor = null;
+
+ // Delegate to the processor associated with file extension
+ String fileName = getFileName(sourceURL);
+
+ //try to retrieve a processor for the specific filename
+ processor = (URLArtifactProcessor<Object>)processors.getProcessor(fileName);
+
+ if (processor == null) {
+ //try to find my file type (extension)
+ String extension = sourceURL.getPath();
+
+ int extensionStart = extension.lastIndexOf('.');
+ //handle files without extension (e.g NOTICE)
+ if (extensionStart > 0) {
+ extension = extension.substring(extensionStart);
+ processor = (URLArtifactProcessor<Object>)processors.getProcessor(extension);
+ }
+ }
+
+ if (processor == null) {
+ return null;
+ }
+ return processor.read(contributionURL, sourceURI, sourceURL);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void resolve(Object model, ModelResolver resolver) throws ContributionResolveException {
+
+ // Delegate to the processor associated with the model type
+ if (model != null) {
+ URLArtifactProcessor processor = processors.getProcessor(model.getClass());
+ if (processor != null) {
+ processor.resolve(model, resolver);
+ }
+ }
+ }
+
+ public <M> M read(URL contributionURL, URI artifactURI, URL artifactUrl, Class<M> type)
+ throws ContributionReadException {
+ Object mo = read(contributionURL, artifactURI, artifactUrl);
+ if (type.isInstance(mo)) {
+ return type.cast(mo);
+ } else {
+ UnrecognizedElementException e = new UnrecognizedElementException(null);
+ e.setResourceURI(artifactURI.toString());
+ throw e;
+ }
+ }
+
+ public String getArtifactType() {
+ return null;
+ }
+
+ public Class<Object> getModelType() {
+ return null;
+ }
+
+ /**
+ * Returns the file name from a URL.
+ * @param url
+ * @return
+ */
+ private static String getFileName(URL url){
+ String fileName = url.getPath();
+ int pos = fileName.lastIndexOf("/");
+
+ return fileName.substring(pos +1);
+ }
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessor.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessor.java
new file mode 100644
index 0000000000..e4034c358e
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessor.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.util.List;
+
+import org.apache.tuscany.sca.contribution.service.ContributionException;
+
+/**
+ * Interface for contribution package processors
+ *
+ * Package processors understand the format of the contribution and how to get the
+ * artifacts in the contribution.
+ *
+ * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $
+ */
+public interface PackageProcessor {
+
+ /**
+ * Returns the type of package supported by this package processor.
+ *
+ * @return the package type
+ */
+ String getPackageType();
+
+ /**
+ * Returns a list of artifacts in the contribution.
+ *
+ * @param packageSourceURL Contribution package location URL
+ * @param inputStream Optional content of the package
+ * @return List of artifact URIs
+ * @throws ContributionException
+ * @throws IOException
+ */
+ List<URI> getArtifacts(URL packageSourceURL, InputStream inputStream) throws ContributionException, IOException;
+
+ /**
+ * Return the URL for an artifact in the package.
+ *
+ * This is needed for archives such as jar files that have specific URL schemes
+ * for the artifacts they contain.
+ *
+ * @param packageSourceURL Contribution package location URL
+ * @param artifact The relative URI for the artifact
+ * @return The artifact URL
+ */
+ URL getArtifactURL(URL packageSourceURL, URI artifact) throws MalformedURLException;
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessorExtensionPoint.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessorExtensionPoint.java
new file mode 100644
index 0000000000..97fd5fee76
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessorExtensionPoint.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+/**
+ * An extension point for package processors
+ *
+ * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $
+ */
+public interface PackageProcessorExtensionPoint {
+
+ /**
+ * Register a PackageProcessor using the package type as the key.
+ *
+ * @param processor The package processor
+ */
+ void addPackageProcessor(PackageProcessor processor);
+
+ /**
+ * Unregister a PackageProcessor.
+ *
+ * @param processor The package processor
+ */
+ void removePackageProcessor(PackageProcessor processor);
+
+ /**
+ * Returns the PackageProcessor for the given package type.
+ *
+ * @param packageType The package type
+ * @return The package processor
+ */
+ PackageProcessor getPackageProcessor(String packageType);
+
+} \ No newline at end of file
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java
new file mode 100644
index 0000000000..62e6bd0f86
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.sca.contribution.service.ContributionReadException;
+import org.apache.tuscany.sca.contribution.service.ContributionWriteException;
+
+/**
+ * An artifact processor that can read models from a StAX XMLStreamReader.
+ *
+ * @version $Rev: 572267 $ $Date: 2007-09-03 02:46:41 -0700 (Mon, 03 Sep 2007) $
+ */
+public interface StAXArtifactProcessor<M> extends ArtifactProcessor<M> {
+
+ /**
+ * Reads a model from an XMLStreamReader.
+ *
+ * @param reader The XMLStreamReader
+ * @return A model representation of the input.
+ */
+ M read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException;
+
+ /**
+ * Writes a model to an XMLStreamWriter.
+ *
+ * @param model A model representing the source
+ * @param writer The XML stream writer
+ * @throws ContributionWriteException
+ * @throws XMLStreamException
+ */
+ void write(M model, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException;
+
+ /**
+ * Returns the type of artifact handled by this artifact processor.
+ *
+ * @return The type of artifact handled by this artifact processor
+ */
+ QName getArtifactType();
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..0bf0f81b5e
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+/**
+ * An extension point for StAX artifact processors.
+ *
+ * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $
+ */
+public interface StAXArtifactProcessorExtensionPoint extends
+ ArtifactProcessorExtensionPoint<StAXArtifactProcessor> {
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java
new file mode 100644
index 0000000000..07e71aba5a
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.net.URI;
+import java.net.URL;
+
+import org.apache.tuscany.sca.contribution.service.ContributionReadException;
+
+/**
+ * An artifact processor that can read models from a URL.
+ *
+ * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $
+ */
+public interface URLArtifactProcessor<M> extends ArtifactProcessor<M> {
+
+ /**
+ * Reads a model from a URL.
+ *
+ * @param contributionURL Contribution location URL
+ * @param artifactURI Artifact URI
+ * @param artifactURL Artifact location URL
+ * @return A model representation of the input.
+ */
+ M read(URL contributionURL, URI artifactURI, URL artifactURL) throws ContributionReadException;
+
+ /**
+ * Returns the type of artifact handled by this artifact processor.
+ *
+ * @return The type of artifact handled by this artifact processor
+ */
+ String getArtifactType();
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..653b0ed637
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+/**
+ * An extension point for URL artifact processors.
+ *
+ * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $
+ */
+public interface URLArtifactProcessorExtensionPoint extends
+ ArtifactProcessorExtensionPoint<URLArtifactProcessor> {
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java
new file mode 100644
index 0000000000..8d5e2f33db
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java
@@ -0,0 +1,336 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.util.logging.Logger;
+
+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 javax.xml.stream.util.StreamReaderDelegate;
+import javax.xml.validation.Schema;
+import javax.xml.validation.ValidatorHandler;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ *
+ * A validating XMLStreamReader that reports XMLSchema validation errors.
+ *
+ * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $
+ */
+class ValidatingXMLStreamReader extends StreamReaderDelegate implements XMLStreamReader {
+ private static final Logger logger = Logger.getLogger(ValidatingXMLStreamReader.class.getName());
+
+ private int level;
+ private ValidatorHandler handler;
+
+ /**
+ * Constructs a new ValidatingXMLStreamReader.
+ *
+ * @param reader
+ * @param schema
+ * @throws XMLStreamException
+ */
+ ValidatingXMLStreamReader(XMLStreamReader reader, Schema schema) throws XMLStreamException {
+ super(reader);
+ if (schema == null) {
+ return;
+ }
+
+ handler = schema.newValidatorHandler();
+ handler.setDocumentLocator(new LocatorAdapter());
+ try {
+ handler.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
+ } catch (SAXException e) {
+ throw new XMLStreamException(e);
+ }
+
+ // These validation errors are just warnings for us as we want to support
+ // running from an XML document with XSD validation errors, as long as we can
+ // get the metadata we need from the document
+ handler.setErrorHandler(new ErrorHandler() {
+ private String getMessage(SAXParseException e) {
+ return "XMLSchema validation problem in: " + e.getSystemId() + ", line: " + e.getLineNumber() + ", column: " + e.getColumnNumber() + "\n" + e.getMessage();
+ }
+
+ public void error(SAXParseException exception) throws SAXException {
+ logger.warning(getMessage(exception));
+ }
+
+ public void fatalError(SAXParseException exception) throws SAXException {
+ logger.warning(getMessage(exception));
+ }
+
+ public void warning(SAXParseException exception) throws SAXException {
+ logger.warning(getMessage(exception));
+ }
+ });
+ }
+
+ @Override
+ public int next() throws XMLStreamException {
+ if (handler == null) {
+ return super.next();
+ }
+
+ int event = super.next();
+ try {
+ switch (event) {
+ case XMLStreamConstants.START_DOCUMENT:
+ level++;
+ handler.startDocument();
+ break;
+ case XMLStreamConstants.START_ELEMENT:
+ level++;
+ handleStartElement();
+ break;
+ case XMLStreamConstants.PROCESSING_INSTRUCTION:
+ handler.processingInstruction(super.getPITarget(), super.getPIData());
+ break;
+ case XMLStreamConstants.CHARACTERS:
+ case XMLStreamConstants.CDATA:
+ case XMLStreamConstants.SPACE:
+ case XMLStreamConstants.ENTITY_REFERENCE:
+ handler.characters(super.getTextCharacters(), super.getTextStart(), super.getTextLength());
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ handleEndElement();
+ level--;
+ break;
+ case XMLStreamConstants.END_DOCUMENT:
+ handler.endDocument();
+ break;
+ }
+ } catch (SAXException e) {
+ throw new XMLStreamException(e.getMessage(), e);
+ }
+ return event;
+ }
+
+ @Override
+ public int nextTag() throws XMLStreamException {
+ if (handler == null) {
+ return super.nextTag();
+ }
+
+ for (;;) {
+ int event = super.getEventType();
+ try {
+ switch (event) {
+ case XMLStreamConstants.START_DOCUMENT:
+ level++;
+ handler.startDocument();
+ break;
+ case XMLStreamConstants.START_ELEMENT:
+ level++;
+ handleStartElement();
+ return event;
+ case XMLStreamConstants.PROCESSING_INSTRUCTION:
+ handler.processingInstruction(super.getPITarget(), super.getPIData());
+ break;
+ case XMLStreamConstants.CHARACTERS:
+ case XMLStreamConstants.CDATA:
+ case XMLStreamConstants.SPACE:
+ case XMLStreamConstants.ENTITY_REFERENCE:
+ handler.characters(super.getTextCharacters(), super.getTextStart(), super.getTextLength());
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ handleEndElement();
+ level--;
+ return event;
+ case XMLStreamConstants.END_DOCUMENT:
+ handler.endDocument();
+ return event;
+ }
+ } catch (SAXException e) {
+ throw new XMLStreamException(e);
+ }
+ super.next();
+ }
+ }
+
+ @Override
+ public String getElementText() throws XMLStreamException {
+ if (handler == null) {
+ return super.getElementText();
+ }
+
+ if (getEventType() != XMLStreamConstants.START_ELEMENT) {
+ return super.getElementText();
+ }
+ StringBuffer text = new StringBuffer();
+
+ for (;;) {
+ int event = next();
+ switch (event) {
+ case XMLStreamConstants.END_ELEMENT:
+ return text.toString();
+
+ case XMLStreamConstants.COMMENT:
+ case XMLStreamConstants.PROCESSING_INSTRUCTION:
+ continue;
+
+ case CHARACTERS:
+ case CDATA:
+ case SPACE:
+ case ENTITY_REFERENCE:
+ text.append(getText());
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ /**
+ * Handle a start element event.
+ *
+ * @throws SAXException
+ */
+ private void handleStartElement() throws SAXException {
+
+ // send startPrefixMapping events immediately before startElement event
+ int nsCount = super.getNamespaceCount();
+ for (int i = 0; i < nsCount; i++) {
+ String prefix = super.getNamespacePrefix(i);
+ if (prefix == null) { // true for default namespace
+ prefix = "";
+ }
+ handler.startPrefixMapping(prefix, super.getNamespaceURI(i));
+ }
+
+ // fire startElement
+ QName qname = super.getName();
+ String prefix = qname.getPrefix();
+ String rawname;
+ if (prefix == null || prefix.length() == 0) {
+ rawname = qname.getLocalPart();
+ } else {
+ rawname = prefix + ':' + qname.getLocalPart();
+ }
+ Attributes attrs = getAttributes();
+ handler.startElement(qname.getNamespaceURI(), qname.getLocalPart(), rawname, attrs);
+ }
+
+ /**
+ * Handle an endElement event.
+ *
+ * @throws SAXException
+ */
+ private void handleEndElement() throws SAXException {
+
+ // fire endElement
+ QName qname = super.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 = super.getNamespaceCount();
+ for (int i = nsCount - 1; i >= 0; i--) {
+ String prefix = super.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() {
+ AttributesImpl attrs = new AttributesImpl();
+
+ // add namespace declarations
+ for (int i = 0; i < super.getNamespaceCount(); i++) {
+ String prefix = super.getNamespacePrefix(i);
+ String uri = super.getNamespaceURI(i);
+ if (prefix == null) {
+ attrs.addAttribute("", "", "xmlns", "CDATA", uri);
+ } else {
+ attrs.addAttribute("", "", "xmlns:" + prefix, "CDATA", uri);
+ }
+ }
+
+ // Regular attributes
+ for (int i = 0; i < super.getAttributeCount(); i++) {
+ String uri = super.getAttributeNamespace(i);
+ if (uri == null) {
+ uri = "";
+ }
+ String localName = super.getAttributeLocalName(i);
+ String prefix = super.getAttributePrefix(i);
+ String qname;
+ if (prefix == null || prefix.length() == 0) {
+ qname = localName;
+ } else {
+ qname = prefix + ':' + localName;
+ }
+ String type = super.getAttributeType(i);
+ String value = super.getAttributeValue(i);
+
+ attrs.addAttribute(uri, localName, qname, type, value);
+ }
+
+ return attrs;
+ }
+
+ /**
+ * Adapter for mapping Locator information.
+ */
+ private final class LocatorAdapter implements Locator {
+
+ private LocatorAdapter() {
+ }
+
+ public int getColumnNumber() {
+ Location location = getLocation();
+ return location == null ? 0 : location.getColumnNumber();
+ }
+
+ public int getLineNumber() {
+ Location location = getLocation();
+ return location == null ? 0 : location.getLineNumber();
+ }
+
+ public String getPublicId() {
+ Location location = getLocation();
+ return location == null ? "" : location.getPublicId();
+ }
+
+ public String getSystemId() {
+ Location location = getLocation();
+ return location == null ? "" : location.getSystemId();
+ }
+ }
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidationSchemaExtensionPoint.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidationSchemaExtensionPoint.java
new file mode 100644
index 0000000000..8316786ce0
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidationSchemaExtensionPoint.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.util.List;
+
+
+/**
+ * An extension point for XML schemas used for validation.
+ *
+ * @version $Rev: 581132 $ $Date: 2007-10-01 21:05:32 -0700 (Mon, 01 Oct 2007) $
+ */
+public interface ValidationSchemaExtensionPoint {
+
+ /**
+ * Add a schema.
+ *
+ * @param uri the URI of the schema
+ */
+ void addSchema(String uri);
+
+ /**
+ * Remove a schema.
+ *
+ * @param uri the URI of the schema
+ */
+ void removeSchema(String uri);
+
+ /**
+ * Returns the list of schemas registered in the extension point.
+ * @return the list of schemas
+ */
+ List<String> getSchemas();
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java
new file mode 100644
index 0000000000..235e542e52
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.resolver;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * A weak reference to a class, which should be used to register classes
+ * with an ArtifactResolver and resolve these classes later.
+ *
+ * FIXME The core contribution model should not have dependencies on classes
+ * and ClassLoaders. This should move to the Java import support module.
+ *
+ * @version $Rev: 639257 $ $Date: 2008-03-20 05:12:00 -0700 (Thu, 20 Mar 2008) $
+ */
+public class ClassReference {
+
+ private WeakReference<Class> clazz;
+ private String className;
+
+ /**
+ * Constructs a new ClassReference.
+ *
+ * @param clazz The class reference
+ */
+ public ClassReference(Class clazz) {
+ this.clazz = new WeakReference<Class>(clazz);
+ this.className = clazz.getName();
+ }
+
+ /**
+ * Constructs a new ClassReference.
+ *
+ * @param className The class name
+ */
+ public ClassReference(String className) {
+ this.className = className;
+ }
+
+ /**
+ * Get the referenced class.
+ *
+ * @return The referenced class
+ */
+ public Class getJavaClass() {
+ if (clazz != null) {
+ return clazz.get();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Get the referenced class name.
+ *
+ * @return The class name
+ */
+ public String getClassName() {
+ return className;
+ }
+
+ /**
+ * Returns true if the class reference is unresolved.
+ *
+ * @return Whether or not the class has been resolved
+ */
+ public boolean isUnresolved() {
+ return clazz == null;
+ }
+
+ @Override
+ public int hashCode() {
+ return className.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ } else {
+ if (obj instanceof ClassReference) {
+ return className.equals(((ClassReference)obj).className);
+ } else {
+ return false;
+ }
+ }
+ }
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java
new file mode 100644
index 0000000000..e8a9edb275
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.resolver;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Base;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.Export;
+import org.apache.tuscany.sca.contribution.Import;
+
+/**
+ * A model resolver implementation that considers Exports in any available contribution
+ *
+ * @version $Rev: 560435 $ $Date: 2007-07-27 18:26:55 -0700 (Fri, 27 Jul 2007) $
+ */
+public class DefaultImportAllModelResolver implements ModelResolver {
+
+ private Import import_;
+ private List<Contribution> contributions;
+
+ public DefaultImportAllModelResolver(Import import_, List<Contribution> contributions) {
+ this.import_ = import_;
+ this.contributions = contributions;
+ }
+
+ public void addModel(Object resolved) {
+ throw new IllegalStateException();
+ }
+
+ public Object removeModel(Object resolved) {
+ throw new IllegalStateException();
+ }
+
+ public <T> T resolveModel(Class<T> modelClass, T unresolved) {
+
+ //TODO optimize and cache results of the resolution later
+
+ // Go over all available contributions
+ for (Contribution contribution : contributions) {
+
+ // Go over all exports in the contribution
+ for (Export export : contribution.getExports()) {
+
+ // If the export matches the export, try to resolve the model object
+ if (import_.match(export)) {
+ Object resolved = export.getModelResolver().resolveModel(modelClass, unresolved);
+
+ // Return the resolved model object
+ if (resolved instanceof Base) {
+ if (!((Base)resolved).isUnresolved()) {
+ return modelClass.cast(resolved);
+ }
+ }
+ }
+ }
+ }
+
+ // Model object was not resolved
+ return unresolved;
+ }
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolver.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolver.java
new file mode 100644
index 0000000000..e8e635ad07
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolver.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.resolver;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * A default implementation of a model resolver based on a map.
+ *
+ * @version $Rev: 631277 $ $Date: 2008-02-26 08:23:26 -0800 (Tue, 26 Feb 2008) $
+ */
+public class DefaultModelResolver implements ModelResolver {
+
+ private Map<Object, Object> map = new HashMap<Object, Object>();
+
+ public DefaultModelResolver() {
+ }
+
+ public <T> T resolveModel(Class<T> modelClass, T unresolved) {
+ Object resolved = map.get(unresolved);
+ if (resolved != null) {
+
+ // Return the resolved object
+ return modelClass.cast(resolved);
+
+ } else {
+
+ // Return the unresolved object
+ return unresolved;
+ }
+ }
+
+ public void addModel(Object resolved) {
+ map.put(resolved, resolved);
+ }
+
+ public Object removeModel(Object resolved) {
+ return map.remove(resolved);
+ }
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.java
new file mode 100644
index 0000000000..471cfde136
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.resolver;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tuscany.sca.extensibility.ServiceDeclaration;
+import org.apache.tuscany.sca.extensibility.ServiceDiscovery;
+
+
+/**
+ * The default implementation of a model resolver extension point.
+ *
+ * @version $Rev: 632642 $ $Date: 2008-03-01 10:16:44 -0800 (Sat, 01 Mar 2008) $
+ */
+public class DefaultModelResolverExtensionPoint implements ModelResolverExtensionPoint {
+
+ private final Map<Class<?>, Class<? extends ModelResolver>> resolvers = new HashMap<Class<?>, Class<? extends ModelResolver>>();
+ private Map<String, ServiceDeclaration> loadedResolvers;
+
+ /**
+ * Constructs a new DefaultModelResolverExtensionPoint.
+ */
+ public DefaultModelResolverExtensionPoint() {
+ }
+
+ public void addResolver(Class<?> modelType, Class<? extends ModelResolver> resolver) {
+ resolvers.put(modelType, resolver);
+ }
+
+ public void removeResolver(Class<?> modelType) {
+ resolvers.remove(modelType);
+ }
+
+ @SuppressWarnings("unchecked")
+ public Class<? extends ModelResolver> getResolver(Class<?> modelType) {
+ loadModelResolvers();
+
+ Class<?>[] classes = modelType.getInterfaces();
+ for (Class<?> c : classes) {
+ Class<? extends ModelResolver> resolver = resolvers.get(c);
+ if (resolver == null) {
+ ServiceDeclaration resolverClass = loadedResolvers.get(c.getName());
+ if (resolverClass != null) {
+ try {
+ return (Class<? extends ModelResolver>)resolverClass.loadClass();
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ } else {
+ return resolver;
+ }
+ }
+
+ Class<? extends ModelResolver > resolver = resolvers.get(modelType);
+ if (resolver == null) {
+ ServiceDeclaration resolverClass = loadedResolvers.get(modelType.getName());
+ if (resolverClass != null) {
+ try {
+ return (Class<? extends ModelResolver>)resolverClass.loadClass();
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ }
+ return resolver;
+ }
+
+ /**
+ * Dynamically load model resolvers declared under META-INF/services
+ */
+ private void loadModelResolvers() {
+ if (loadedResolvers != null)
+ return;
+ loadedResolvers = new HashMap<String, ServiceDeclaration>();
+
+ // Get the model resolver service declarations
+ Set<ServiceDeclaration> modelResolverDeclarations;
+ try {
+ modelResolverDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(ModelResolver.class);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+
+ // Load model resolvers
+ for (ServiceDeclaration dataBindingDeclaration: modelResolverDeclarations) {
+ Map<String, String> attributes = dataBindingDeclaration.getAttributes();
+ String model = attributes.get("model");
+
+ loadedResolvers.put(model, dataBindingDeclaration);
+ }
+ }
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java
new file mode 100644
index 0000000000..92cae94997
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.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.sca.contribution.resolver;
+
+import java.lang.reflect.Constructor;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint;
+
+/**
+ * An implementation of an extensible model resolver which delegates to the
+ * proper resolver extension based on the class of the model to resolve.
+ *
+ * @version $Rev: 632499 $ $Date: 2008-02-29 15:59:39 -0800 (Fri, 29 Feb 2008) $
+ */
+public class ExtensibleModelResolver implements ModelResolver {
+ private final ModelResolverExtensionPoint resolvers;
+ private final ModelFactoryExtensionPoint factories;
+ private final Contribution contribution;
+ private final ModelResolver defaultResolver;
+ private final Map<Class<?>, ModelResolver> resolverInstances = new HashMap<Class<?>, ModelResolver>();
+ private Map<Object, Object> map = new HashMap<Object, Object>();
+
+ /**
+ * Constructs an extensible model resolver
+ *
+ * @param resolvers
+ * @param contribution
+ * @param factories
+ */
+ @Deprecated
+ public ExtensibleModelResolver(Contribution contribution,
+ ModelResolverExtensionPoint resolvers,
+ ModelFactoryExtensionPoint factories,
+ ModelResolver defaultResolver) {
+ this.contribution = contribution;
+ this.resolvers = resolvers;
+ this.factories = factories;
+ //FIXME Remove this default resolver, this is currently used to resolve policy declarations
+ // but they should be handled by the contribution import/export mechanism instead of this
+ // defaultResolver hack.
+ this.defaultResolver = defaultResolver;
+ }
+
+ /**
+ * Constructs an extensible model resolver
+ *
+ * @param resolvers
+ * @param contribution
+ * @param factories
+ */
+ public ExtensibleModelResolver(Contribution contribution,
+ ModelResolverExtensionPoint resolvers,
+ ModelFactoryExtensionPoint factories) {
+ this.contribution = contribution;
+ this.resolvers = resolvers;
+ this.factories = factories;
+ this.defaultResolver = null;
+ }
+
+ /**
+ * Returns the proper resolver instance based on the interfaces of the model
+ * If one is not available on the registry, instantiate on demand
+ *
+ * @param modelType
+ * @return
+ */
+ private ModelResolver getModelResolverInstance(Class<?> modelType) {
+
+ // Look up a model resolver instance for the model class or
+ // each implemented interface
+ Class<?>[] interfaces = modelType.getInterfaces();
+ Class<?>[] classes = new Class<?>[interfaces.length + 1];
+ classes[0] = modelType;
+ if (interfaces.length != 0) {
+ System.arraycopy(interfaces, 0, classes, 1, interfaces.length);
+ }
+ for (Class<?> c : classes) {
+
+ // Look up an existing model resolver instance
+ ModelResolver resolverInstance = resolverInstances.get(c);
+ if (resolverInstance != null) {
+ return resolverInstance;
+ }
+
+ // We don't have an instance, lookup a model resolver class
+ // and instantiate it
+ Class<? extends ModelResolver> resolverClass = resolvers.getResolver(c);
+ if (resolverClass != null) {
+ try {
+ Constructor<? extends ModelResolver> constructor =
+ resolverClass
+ .getConstructor(new Class[] {Contribution.class, ModelFactoryExtensionPoint.class});
+ if (constructor != null) {
+
+ // Construct the model resolver instance and cache it
+ resolverInstance = constructor.newInstance(contribution, factories);
+ resolverInstances.put(c, resolverInstance);
+ return resolverInstance;
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public void addModel(Object resolved) {
+ ModelResolver resolver = getModelResolverInstance(resolved.getClass());
+ if (resolver != null) {
+ resolver.addModel(resolved);
+ } else {
+ map.put(resolved, resolved);
+ }
+ }
+
+ public Object removeModel(Object resolved) {
+ ModelResolver resolver = getModelResolverInstance(resolved.getClass());
+ if (resolver != null) {
+ return resolver.removeModel(resolved);
+ } else {
+ return map.remove(resolved);
+ }
+ }
+
+ public <T> T resolveModel(Class<T> modelClass, T unresolved) {
+ ModelResolver resolver = getModelResolverInstance(unresolved.getClass());
+ if (resolver != null) {
+ return resolver.resolveModel(modelClass, unresolved);
+ } else {
+ //FIXME Remove this default resolver, this is currently used to resolve policy declarations
+ // but they should be handled by the contribution import/export mechanism instead of this
+ // defaultResolver hack.
+ if (defaultResolver != null) {
+ Object resolved = defaultResolver.resolveModel(modelClass, unresolved);
+ if (resolved != null && resolved != unresolved) {
+ return modelClass.cast(resolved);
+ }
+ }
+
+ Object resolved = map.get(unresolved);
+ if (resolved != null) {
+ // Return the resolved object
+ return modelClass.cast(resolved);
+ }
+ }
+
+ return unresolved;
+ }
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.java
new file mode 100644
index 0000000000..9eaaef6e9b
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.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.sca.contribution.resolver;
+
+/**
+ * A model resolver, responsible for resolving models in the scope of an
+ * SCA contribution.
+ *
+ * SCA Assemblies reference artifacts of a wide variety of types. These
+ * include:
+ * <ul>
+ * <li> Reference from one SCA composite to another SCA composite
+ * <li> Reference to PolicySet files
+ * <li> Reference to interface definition files, either WSDL or Java interfaces
+ * <li> Reference to XSD files
+ * <li> Reference to any of a wide variety of implementation artifact files,
+ * including Java classes, BPEL scripts, C++ DLLs and classes, PHP scripts
+ * </ul>
+ *
+ * In the SCA assemblies, these various artifacts are referenced using either
+ * QNames or logical URIs. Model resolvers are used to resolve these references
+ * and get the in-memory models representing the referenced artifacts.
+ *
+ * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $
+ */
+public interface ModelResolver {
+
+ /**
+ * Resolve the model representing an artifact.
+ *
+ * @param modelClass the type of artifact
+ * @param unresolved the unresolved model
+ * @return the resolved model
+ */
+ <T> T resolveModel(Class<T> modelClass, T unresolved);
+
+ /**
+ * Add a resolved model.
+ *
+ * @param resolved The model
+ */
+ void addModel(Object resolved);
+
+ /**
+ * Remove a resolved model.
+ *
+ * @param resolved
+ * @return The removed model, or null if the model was not removed
+ */
+ Object removeModel(Object resolved);
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java
new file mode 100644
index 0000000000..e17e815064
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.resolver;
+
+
+/**
+ * An extension point for model resolvers
+ *
+ * @version $Rev: 616114 $ $Date: 2008-01-28 16:05:37 -0800 (Mon, 28 Jan 2008) $
+ */
+public interface ModelResolverExtensionPoint {
+
+ /**
+ * Register a model resolver class using the model type as the key
+ *
+ * @param modelType The model type
+ * @param resolver The model resolver Class
+ */
+ void addResolver(Class<?> modelType, Class <? extends ModelResolver> resolver);
+
+ /**
+ * Remove the model resolver class for a specific model type
+ *
+ * @param modelType The model type
+ */
+ void removeResolver(Class<?> modelType);
+
+ /**
+ * Retrieve a model resolver class for a specific model type
+ *
+ * @param modelType The model artifact type
+ * @return The model resolver Class
+ */
+ Class <? extends ModelResolver> getResolver(Class<?> modelType);
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResourceReference.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResourceReference.java
new file mode 100644
index 0000000000..941837d862
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResourceReference.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.sca.contribution.resolver;
+
+import java.net.URL;
+
+/**
+ * A resource URL, which should be used to register resources
+ * with an ArtifactResolver and resolve these resources later.
+ *
+ * FIXME Don't use as its deprecated, use Artifact instead.
+ */
+@Deprecated
+public class ResourceReference {
+
+ private URL resourceURL;
+ private String resourceName;
+
+ /**
+ * Constructs a new ResourceReference.
+ *
+ * @param resourceName Name of resource
+ * @param resourceURL The resource URL
+ */
+ public ResourceReference(String resourceName, URL resourceURL) {
+ this.resourceURL = resourceURL;
+ this.resourceName = resourceName;
+ }
+
+ /**
+ * Constructs a new ResourceReference.
+ *
+ * @param resourceName Name of resource
+ */
+ public ResourceReference(String resourceName) {
+ this.resourceName = resourceName;
+ }
+
+ /**
+ * Get the resource URL.
+ *
+ * @return The resource URL
+ */
+ public URL getResource() {
+ return resourceURL;
+ }
+
+ /**
+ * Get the resource name.
+ *
+ * @return The resource name
+ */
+ public String getResourceName() {
+ return resourceName;
+ }
+
+ /**
+ * Returns true if the resource reference is unresolved.
+ *
+ * @return Whether or not the resource has been resolved
+ */
+ public boolean isUnresolved() {
+ return resourceURL == null;
+ }
+
+ @Override
+ public int hashCode() {
+ return resourceName.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ } else {
+ if (obj instanceof ResourceReference) {
+ return resourceName.equals(((ResourceReference)obj).resourceName);
+ } else {
+ return false;
+ }
+ }
+ }
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java
new file mode 100644
index 0000000000..b754de11fd
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.scanner;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+
+import org.apache.tuscany.sca.contribution.service.ContributionReadException;
+
+/**
+ * Interface for contribution package scanners
+ *
+ * Contribution scanners understand the format of the contribution and how to get the
+ * artifacts in the contribution.
+ *
+ * @version $Rev: 631891 $ $Date: 2008-02-28 00:34:05 -0800 (Thu, 28 Feb 2008) $
+ */
+public interface ContributionScanner {
+
+ /**
+ * Returns the type of package supported by this package scanner.
+ *
+ * @return the package type
+ */
+ String getContributionType();
+
+ /**
+ * Returns a list of artifacts in the contribution.
+ *
+ * @param contributionURL Contribution URL
+ * @return List of artifact URIs
+ * @throws ContributionException
+ * @throws IOException
+ */
+ List<String> getArtifacts(URL contributionURL) throws ContributionReadException;
+
+ /**
+ * Return the URL for an artifact in the contribution.
+ *
+ * This is needed for archives such as jar files that have specific URL schemes
+ * for the artifacts they contain.
+ *
+ * @param contributionURL Contribution URL
+ * @param artifact The relative URI for the artifact
+ * @return The artifact URL
+ */
+ URL getArtifactURL(URL contributionURL, String artifact) throws ContributionReadException;
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java
new file mode 100644
index 0000000000..c78872e5af
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.scanner;
+
+/**
+ * An extension point for contribution scanners
+ *
+ * @version $Rev: 631271 $ $Date: 2008-02-26 08:11:36 -0800 (Tue, 26 Feb 2008) $
+ */
+public interface ContributionScannerExtensionPoint {
+
+ /**
+ * Add a ContributionScanner using the contribution type as the key.
+ *
+ * @param scanner The contribution scanner
+ */
+ void addContributionScanner(ContributionScanner scanner);
+
+ /**
+ * Remove a ContributionScanner.
+ *
+ * @param scanner The contribution scanner
+ */
+ void removeContributionScanner(ContributionScanner scanner);
+
+ /**
+ * Returns the ContributionScanner for the given contribution type.
+ *
+ * @param contributionType The contribution type
+ * @return The contribution scanner
+ */
+ ContributionScanner getContributionScanner(String contributionType);
+
+} \ No newline at end of file
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java
new file mode 100644
index 0000000000..97ddabda19
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.scanner;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tuscany.sca.contribution.service.ContributionReadException;
+import org.apache.tuscany.sca.extensibility.ServiceDeclaration;
+import org.apache.tuscany.sca.extensibility.ServiceDiscovery;
+
+/**
+ * Default implementation of a contribution scanner extension point.
+ *
+ * @version $Rev: 632642 $ $Date: 2008-03-01 10:16:44 -0800 (Sat, 01 Mar 2008) $
+ */
+public class DefaultContributionScannerExtensionPoint implements ContributionScannerExtensionPoint {
+
+ private Map<String, ContributionScanner> scanners = new HashMap<String, ContributionScanner>();
+ private boolean loaded;
+
+ public DefaultContributionScannerExtensionPoint() {
+ }
+
+ public void addContributionScanner(ContributionScanner scanner) {
+ scanners.put(scanner.getContributionType(), scanner);
+ }
+
+ public void removeContributionScanner(ContributionScanner scanner) {
+ scanners.remove(scanner.getContributionType());
+ }
+
+ public ContributionScanner getContributionScanner(String contentType) {
+ loadScanners();
+ return scanners.get(contentType);
+ }
+
+ private void loadScanners() {
+ if (loaded)
+ return;
+
+ // Get the scanner service declarations
+ Set<ServiceDeclaration> scannerDeclarations;
+ try {
+ scannerDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(ContributionScanner.class);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+
+ for (ServiceDeclaration scannerDeclaration: scannerDeclarations) {
+ Map<String, String> attributes = scannerDeclaration.getAttributes();
+
+ // Load a URL artifact scanner
+ String contributionType = attributes.get("type");
+
+ // Create a scanner wrapper and register it
+ ContributionScanner scanner = new LazyContributionScanner(contributionType, scannerDeclaration);
+ addContributionScanner(scanner);
+ }
+
+ loaded = true;
+ }
+
+ /**
+ * A facade for contribution scanners.
+ */
+ private static class LazyContributionScanner implements ContributionScanner {
+
+ private ServiceDeclaration scannerDeclaration;
+ private String contributionType;
+ private ContributionScanner scanner;
+
+ private LazyContributionScanner(String contributionType, ServiceDeclaration scannerDeclaration) {
+ this.scannerDeclaration = scannerDeclaration;
+ this.contributionType = contributionType;
+ }
+
+ public URL getArtifactURL(URL contributionSourceURL, String artifact) throws ContributionReadException {
+ return getScanner().getArtifactURL(contributionSourceURL, artifact);
+ }
+
+ public List<String> getArtifacts(URL contributionSourceURL) throws ContributionReadException {
+ return getScanner().getArtifacts(contributionSourceURL);
+ }
+
+ public String getContributionType() {
+ return contributionType;
+ }
+
+ private ContributionScanner getScanner() {
+ if (scanner == null) {
+ try {
+ Class<ContributionScanner> scannerClass = (Class<ContributionScanner>)scannerDeclaration.loadClass();
+ Constructor<ContributionScanner> constructor = scannerClass.getConstructor();
+ scanner = constructor.newInstance();
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ return scanner;
+ }
+ }
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionException.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionException.java
new file mode 100644
index 0000000000..6ce3e307ca
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionException.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.service;
+
+/**
+ * Base class for exceptions raised by contribution services.
+ *
+ * @version $Rev: 616149 $ $Date: 2008-01-28 19:10:32 -0800 (Mon, 28 Jan 2008) $
+ */
+public class ContributionException extends Exception {
+
+ private static final long serialVersionUID = 4432880414927652578L;
+
+ protected ContributionException() {
+ super();
+ }
+
+ protected ContributionException(String message) {
+ super(message);
+ }
+
+ protected ContributionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ContributionException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListener.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListener.java
new file mode 100644
index 0000000000..e46a6b8b40
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListener.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.service;
+
+import java.util.EventListener;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+
+/**
+ * A listener interface used to listen to contribution repository events.
+ *
+ * @version $Rev: 561159 $ $Date: 2007-07-30 15:28:12 -0700 (Mon, 30 Jul 2007) $
+ */
+public interface ContributionListener extends EventListener {
+
+ /**
+ * Notifies the listener that a contribution has been added.
+ *
+ * @param repository The contribution repository
+ * @param contribution The new contribution
+ */
+ void contributionAdded(ContributionRepository repository, Contribution contribution);
+
+ /**
+ * Notifies the listener that a contribution has been removed.
+ *
+ * @param repository The contribution repository
+ * @param contribution The removed contribution.
+ */
+ void contributionRemoved(ContributionRepository repository, Contribution contribution);
+
+ /**
+ * Notifies the listener that a contribution has been updated.
+ *
+ * @param repository The contribution repository
+ * @param oldContribution The old contribution
+ * @param contribution The new contribution
+ */
+ void contributionUpdated(ContributionRepository repository, Contribution oldContribution, Contribution contribution);
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListenerExtensionPoint.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListenerExtensionPoint.java
new file mode 100644
index 0000000000..cbe9cf29b0
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListenerExtensionPoint.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.service;
+
+import java.util.List;
+
+public interface ContributionListenerExtensionPoint {
+
+ /**
+ * Adds a contribution repository listener extension.
+ * @param listener The listener to add
+ */
+ void addContributionListener(ContributionListener listener);
+
+ /**
+ * Removes a contribution repository listener extension.
+ * @param listener The listener to remove
+ */
+ void removeContributionListener(ContributionListener listener);
+
+ /**
+ * Returns the contribution repository listeners.
+ * @return
+ */
+ List<ContributionListener> getContributionListeners();
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionReadException.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionReadException.java
new file mode 100644
index 0000000000..eff3f59b40
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionReadException.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.sca.contribution.service;
+
+/**
+ * Denotes an exception while reading artifacts inside an SCA contribution.
+ *
+ * @version $Rev: 560434 $ $Date: 2007-07-27 18:23:02 -0700 (Fri, 27 Jul 2007) $
+ */
+public class ContributionReadException extends ContributionException {
+ public static final int UNDEFINED = -1;
+ private static final long serialVersionUID = -7459051598906813461L;
+ private String resourceURI;
+ private int line = UNDEFINED;
+ private int column = UNDEFINED;
+
+ public ContributionReadException(String message) {
+ super(message);
+ }
+
+ public ContributionReadException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ContributionReadException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Returns the location of the resource that was being read.
+ *
+ * @return the location of the resource that was being read
+ */
+ public String getResourceURI() {
+ return resourceURI;
+ }
+
+ /**
+ * Sets the location of the resource that was being read.
+ *
+ * @param resourceURI the location of the resource that was being read
+ */
+ public void setResourceURI(String resourceURI) {
+ this.resourceURI = resourceURI;
+ }
+
+ /**
+ * Returns the line inside the resource that was being read.
+ * @return the line inside the resource that was being read
+ */
+ public int getLine() {
+ return line;
+ }
+
+ /**
+ * Sets the line inside the resource that was being read.
+ * @param line the line inside the resource that was being read
+ */
+ public void setLine(int line) {
+ this.line = line;
+ }
+
+ /**
+ * Returns the column inside the resource that was being read.
+ * @return the column inside the resource that was being read
+ */
+ public int getColumn() {
+ return column;
+ }
+
+ /**
+ * Sets the column inside the resource that was being read.
+ * @param column the column inside the resource that was being read
+ */
+ public void setColumn(int column) {
+ this.column = column;
+ }
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRepository.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRepository.java
new file mode 100644
index 0000000000..1fbfedfd97
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRepository.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.sca.contribution.service;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+import java.util.List;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+
+/**
+ * Contribution repository
+ *
+ * @version $Rev: 639257 $ $Date: 2008-03-20 05:12:00 -0700 (Thu, 20 Mar 2008) $
+ */
+public interface ContributionRepository {
+
+ /**
+ * Get the URI of the SCA domain
+ *
+ * @return The domain URI
+ */
+ URI getDomain();
+
+ /**
+ * Copies a contribution to the repository.
+ *
+ * @param contribution A URl pointing to the contribution being copied to
+ * the repository
+ * @param sourceURL URL of the source. this would be used to calculate the right
+ * filename to be stored on the repository when a inputStream is being
+ * provided
+ * @param contributionStream InputStream with the content of the
+ * distribution
+ * @return A URL pointing to the content of the contribution in the
+ * repository
+ * @throws IOException
+ */
+ URL store(String contribution, URL sourceURL, InputStream contributionStream) throws IOException;
+ /**
+ * Copy a contribution from the source URL to the repository
+ *
+ * @param contribution A URl pointing to the contribution being copied to
+ * the repository
+ * @param sourceURL URL of the source. this would be used to calculate the right
+ * filename to be stored on the repository when a inputStream is being
+ * provided
+ * @return A URL pointing to the content of the contribution in the
+ * repository
+ * @throws IOException
+ */
+ URL store(String contribution, URL sourceURL) throws IOException;
+
+ /**
+ * Look up the contribution by URI
+ *
+ * @param contribution The URI of the contribution
+ * @return A URL pointing to the content of the contribution in the
+ * repository, it will be null if the contribution cannot be found
+ * in the repository
+ */
+ URL find(String contribution);
+
+ /**
+ * Remove a contribution from the repository
+ *
+ * @param contribution The URI of the contribution to be removed
+ */
+ void remove(String contribution);
+
+ /**
+ * Get list of URIs for all the contributions in the repository
+ *
+ * @return A list of contribution URIs
+ */
+ List<String> list();
+
+ /**
+ * Returns the contributions available in the repository.
+ * @return The list of contributions.
+ */
+ List<Contribution> getContributions();
+
+ /**
+ * Adds a contribution to the repository.
+ * @param contribution The new contribution.
+ */
+ void addContribution(Contribution contribution);
+
+ /**
+ * Removes a contribution from the repository.
+ * @param contribution The contribution to remove
+ */
+ void removeContribution(Contribution contribution);
+
+ /**
+ * Updates a contribution in the repository
+ * @param contribution The contribution to update
+ */
+ void updateContribution(Contribution contribution);
+
+ /**
+ * Returns the contribution with the given URI.
+ * @param uri the URI of the contribution
+ * @return The contribution
+ */
+ Contribution getContribution(String uri);
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionResolveException.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionResolveException.java
new file mode 100644
index 0000000000..cbfaac370f
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionResolveException.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.service;
+
+/**
+ * Denotes a problem while resolving models inside an SCA contribution.
+ *
+ * @version $Rev: 560434 $ $Date: 2007-07-27 18:23:02 -0700 (Fri, 27 Jul 2007) $
+ */
+public class ContributionResolveException extends ContributionException {
+ private static final long serialVersionUID = -7459051598906813461L;
+
+ public ContributionResolveException(String message) {
+ super(message);
+ }
+
+ public ContributionResolveException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ContributionResolveException(Throwable cause) {
+ super(cause);
+ }
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRuntimeException.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRuntimeException.java
new file mode 100644
index 0000000000..5ff34dea8a
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRuntimeException.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.service;
+
+/**
+ * Base class for runtime exceptions raised by contribution services.
+ *
+ * @version $Rev: 560434 $ $Date: 2007-07-27 18:23:02 -0700 (Fri, 27 Jul 2007) $
+ */
+public class ContributionRuntimeException extends RuntimeException {
+ private static final long serialVersionUID = 7711215366287498896L;
+
+ protected ContributionRuntimeException() {
+ super();
+ }
+
+ protected ContributionRuntimeException(String message) {
+ super(message);
+ }
+
+ protected ContributionRuntimeException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ContributionRuntimeException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionService.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionService.java
new file mode 100644
index 0000000000..86f0523264
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionService.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.service;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * Service interface that manages artifacts contributed to a Tuscany runtime.
+ *
+ * @version $Rev: 637129 $ $Date: 2008-03-14 08:11:59 -0700 (Fri, 14 Mar 2008) $
+ */
+public interface ContributionService {
+ /**
+ * Contribute an artifact to the SCA Domain. The type of the contribution is
+ * determined by the Content-Type of the resource or, if that is undefined,
+ * by some implementation-specific means (such as mapping an extension in
+ * the URL's path).
+ *
+ * @param contributionURI The URI that is used as the contribution unique ID.
+ * @param sourceURL The location of the resource containing the artifact
+ * @param modelResolver The model resolver to use to resolve models in the
+ * scope of this contribution
+ * @param storeInRepository Flag that identifies if you want to copy the
+ * contribution to the repository
+ * @return The contribution model representing the contribution
+ * @throws DeploymentException if there was a problem with the contribution
+ * @throws IOException if there was a problem reading the resource
+ */
+ Contribution contribute(String contributionURI, URL sourceURL, boolean storeInRepository) throws ContributionException,
+ IOException;
+
+ /**
+ * Contribute an artifact to the SCA Domain. The type of the contribution is
+ * determined by the Content-Type of the resource or, if that is undefined,
+ * by some implementation-specific means (such as mapping an extension in
+ * the URL's path).
+ *
+ * @param contributionURI The URI that is used as the contribution unique ID.
+ * @param sourceURL The location of the resource containing the artifact
+ * @param modelResolver The model resolver to use to resolve models in the
+ * scope of this contribution
+ * @param storeInRepository Flag that identifies if you want to copy the
+ * contribution to the repository
+ * @return The contribution model representing the contribution
+ * @throws DeploymentException if there was a problem with the contribution
+ * @throws IOException if there was a problem reading the resource
+ */
+ Contribution contribute(String contributionURI, URL sourceURL, ModelResolver modelResolver, boolean storeInRepository) throws ContributionException,
+ IOException;
+
+ /**
+ * Contribute an artifact to the SCA Domain.
+ *
+ * @param contributionURI The URI that is used as the contribution unique ID.
+ * @param sourceURL The location of the resource containing the artifact.
+ * This is used to identify what name should be used when storing
+ * the contribution on the repository
+ * @param modelResolver The model resolver to use to resolve models in the
+ * scope of this contribution
+ * @param contributionContent A stream containing the resource being
+ * contributed; the stream will not be closed but the read
+ * position after the call is undefined
+ * @return The contribution model representing the contribution
+ * @throws DeploymentException if there was a problem with the contribution
+ * @throws IOException if there was a problem reading the stream
+ */
+ Contribution contribute(String contributionURI, URL sourceURL, InputStream contributionContent)
+ throws ContributionException, IOException;
+
+ /**
+ * Contribute an artifact to the SCA Domain.
+ *
+ * @param contributionURI The URI that is used as the contribution unique ID.
+ * @param sourceURL The location of the resource containing the artifact.
+ * This is used to identify what name should be used when storing
+ * the contribution on the repository
+ * @param modelResolver The model resolver to use to resolve models in the
+ * scope of this contribution
+ * @param contributionContent A stream containing the resource being
+ * contributed; the stream will not be closed but the read
+ * position after the call is undefined
+ * @return The contribution model representing the contribution
+ * @throws DeploymentException if there was a problem with the contribution
+ * @throws IOException if there was a problem reading the stream
+ */
+ Contribution contribute(String contributionURI, URL sourceURL, InputStream contributionContent, ModelResolver modelResolver)
+ throws ContributionException, IOException;
+
+ /**
+ * Get the model for an installed contribution
+ *
+ * @param contribution The URI of an installed contribution
+ * @return The model for the contribution or null if there is no such
+ * contribution
+ */
+ Contribution getContribution(String contribution);
+
+ /**
+ * Adds or updates a deployment composite using a supplied composite
+ * ("composite by value" - a data structure, not an existing resource in the
+ * domain) to the contribution identified by a supplied contribution URI.
+ * The added or updated deployment composite is given a relative URI that
+ * matches the "name" attribute of the composite, with a ".composite"
+ * suffix.
+ *
+ * @param contribution The contribution to where
+ * @param composite
+ * @throws ContributionException
+ */
+ void addDeploymentComposite(Contribution contribution, Composite composite) throws ContributionException;
+
+ /**
+ * Remove a contribution from the SCA domain
+ *
+ * @param contribution The URI of the contribution
+ * @throws DeploymentException
+ */
+ void remove(String contribution) throws ContributionException;
+} \ No newline at end of file
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionWriteException.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionWriteException.java
new file mode 100644
index 0000000000..30bfe8d1cd
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionWriteException.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.service;
+
+
+/**
+ * Denotes an exception while writing artifacts inside an SCA contribution.
+ *
+ * @version $Rev: 560434 $ $Date: 2007-07-27 18:23:02 -0700 (Fri, 27 Jul 2007) $
+ */
+public class ContributionWriteException extends ContributionException {
+ private static final long serialVersionUID = -7459051598906813461L;
+ private String resourceURI;
+
+ public ContributionWriteException(String message) {
+ super(message);
+ }
+
+ public ContributionWriteException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ContributionWriteException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Returns the location of the resource that was being written.
+ *
+ * @return the location of the resource that was being written
+ */
+ public String getResourceURI() {
+ return resourceURI;
+ }
+
+ /**
+ * Sets the location of the resource that was being written.
+ *
+ * @param resourceURI the location of the resource that was being written
+ */
+ public void setResourceURI(String resourceURI) {
+ this.resourceURI = resourceURI;
+ }
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/DefaultContributionListenerExtensionPoint.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/DefaultContributionListenerExtensionPoint.java
new file mode 100644
index 0000000000..d6390c9250
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/DefaultContributionListenerExtensionPoint.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.sca.contribution.service;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint;
+import org.apache.tuscany.sca.extensibility.ServiceDeclaration;
+import org.apache.tuscany.sca.extensibility.ServiceDiscovery;
+
+/**
+ * Default implementation of a contribution listener extension point.
+ *
+ * @version $Rev: 632642 $ $Date: 2008-03-01 10:16:44 -0800 (Sat, 01 Mar 2008) $
+ */
+public class DefaultContributionListenerExtensionPoint implements ContributionListenerExtensionPoint {
+
+ private List<ContributionListener> listeners = new ArrayList<ContributionListener>();
+ private boolean loadedListeners;
+ private ModelFactoryExtensionPoint modelFactories;
+
+ /**
+ * Constructs a new DefaultContributionListenerExtensionPoint.
+ *
+ */
+ public DefaultContributionListenerExtensionPoint(ModelFactoryExtensionPoint modelFactories) {
+ this.modelFactories = modelFactories;
+ }
+
+ public void addContributionListener(ContributionListener listener) {
+ listeners.add(listener);
+ }
+
+ public List<ContributionListener> getContributionListeners() {
+ loadListeners();
+ return listeners;
+ }
+
+ public void removeContributionListener(ContributionListener listener) {
+ listeners.remove(listener);
+ }
+
+ /**
+ * Dynamically load listeners declared under META-INF/services
+ */
+ @SuppressWarnings("unchecked")
+ private void loadListeners() {
+ if (loadedListeners)
+ return;
+
+ // Get the listener service declarations
+ Set<ServiceDeclaration> listenerDeclarations;
+ try {
+ listenerDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(ContributionListener.class);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+
+ // Load and instantiate the listeners
+ for (ServiceDeclaration listenerDeclaration: listenerDeclarations) {
+ ContributionListener listener;
+ try {
+ Class<ContributionListener> listenerClass = (Class<ContributionListener>)listenerDeclaration.loadClass();
+ try {
+ Constructor<ContributionListener> constructor = listenerClass.getConstructor(ModelFactoryExtensionPoint.class);
+ try {
+ listener = constructor.newInstance(modelFactories);
+ } catch (InvocationTargetException e) {
+ throw new IllegalArgumentException(e);
+ }
+ } catch (NoSuchMethodException e) {
+ listener = listenerClass.newInstance();
+ }
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException(e);
+ } catch (InstantiationException e) {
+ throw new IllegalArgumentException(e);
+ } catch (IllegalAccessException e) {
+ throw new IllegalArgumentException(e);
+ }
+ addContributionListener(listener);
+ }
+
+ loadedListeners = true;
+ }
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ExtensibleContributionListener.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ExtensibleContributionListener.java
new file mode 100644
index 0000000000..cba24e7b37
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ExtensibleContributionListener.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.service;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+
+public class ExtensibleContributionListener implements ContributionListener {
+ private final ContributionListenerExtensionPoint listeners;
+
+ /**
+ * Default constructor receiving the listener extension point
+ *
+ * @param listeners
+ */
+ public ExtensibleContributionListener(ContributionListenerExtensionPoint listeners) {
+ this.listeners = listeners;
+ }
+
+ /**
+ * Process "contributionAdded" event to all registered listeners
+ */
+ public void contributionAdded(ContributionRepository repository, Contribution contribution) {
+ for (ContributionListener listener : listeners.getContributionListeners()) {
+ try {
+ listener.contributionAdded(repository, contribution);
+ } catch (Exception e) {
+ // ignore, continue to the next listener
+ }
+ }
+ }
+
+ /**
+ * Process "contributionRemoved" event to all registered listeners
+ */
+ public void contributionRemoved(ContributionRepository repository, Contribution contribution) {
+ for (ContributionListener listener : listeners.getContributionListeners()) {
+ try {
+ listener.contributionRemoved(repository, contribution);
+ } catch (Exception e) {
+ // ignore, continue to the next listener
+ }
+
+ }
+ }
+
+ /**
+ * Process "contributionUpdated" event to all registered listeners
+ */
+ public void contributionUpdated(ContributionRepository repository, Contribution oldContribution, Contribution contribution) {
+ for (ContributionListener listener : listeners.getContributionListeners()) {
+ try {
+ listener.contributionUpdated(repository, oldContribution, contribution);
+ } catch (Exception e) {
+ // ignore, continue to the next listener
+ }
+
+ }
+ }
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/TypeDescriber.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/TypeDescriber.java
new file mode 100644
index 0000000000..28ea8a92ad
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/TypeDescriber.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.service;
+
+import java.net.URL;
+
+/**
+ * Provide content type for a given resource
+ *
+ * @version $Rev: 639257 $ $Date: 2008-03-20 05:12:00 -0700 (Thu, 20 Mar 2008) $
+ */
+public interface TypeDescriber {
+ /**
+ * Get the content type for the specified resource
+ *
+ * @param resourceURL The resource URL
+ * @param defaultType The default content type
+ * @return The content type
+ */
+ String getType(URL resourceURL, String defaultType);
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnrecognizedElementException.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnrecognizedElementException.java
new file mode 100644
index 0000000000..9c6fbcce2f
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnrecognizedElementException.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.service;
+
+import javax.xml.namespace.QName;
+
+/**
+ * Exception that indicates an element was encountered that could not be handled.
+ *
+ * @version $Rev: 560434 $ $Date: 2007-07-27 18:23:02 -0700 (Fri, 27 Jul 2007) $
+ */
+public class UnrecognizedElementException extends ContributionReadException {
+ private static final long serialVersionUID = 2549543622209829032L;
+ private final QName element;
+
+ /**
+ * Constructor that indicates which element could not be handled.
+ * @param element the element that could not be handled
+ */
+ public UnrecognizedElementException(QName element) {
+ super("Unrecognized element: " + element.toString());
+ this.element = element;
+ }
+
+ /**
+ * Returns the element that could not be handled.
+ * @return the element that could not be handled.
+ */
+ public QName getElement() {
+ return element;
+ }
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedContentTypeException.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedContentTypeException.java
new file mode 100644
index 0000000000..4744fcd811
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedContentTypeException.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.service;
+
+/**
+ * Exception thrown to indicate that a Content-Type is not supported by this SCA Domain.
+ * The Content-Type value supplied will be returned as the message text for this exception.
+ *
+ * FIXME Don't use as it's deprecated and replaced by UnsupportedPackageTypeException.
+ *
+ * @version $Rev: 616149 $ $Date: 2008-01-28 19:10:32 -0800 (Mon, 28 Jan 2008) $
+ */
+@Deprecated
+public class UnsupportedContentTypeException extends ContributionException {
+ private static final long serialVersionUID = -1831797280021355672L;
+
+ /**
+ * Constructs a new UnsupportedContentTypeException.
+ *
+ * @param message
+ */
+ public UnsupportedContentTypeException(String message) {
+ super(message);
+ }
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedPackageTypeException.java b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedPackageTypeException.java
new file mode 100644
index 0000000000..ba549b22a9
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedPackageTypeException.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.service;
+
+/**
+ * Exception thrown to indicate that a Content-Type is not supported by this SCA Domain.
+ * The Content-Type value supplied will be returned as the message text for this exception.
+ *
+ * @version $Rev: 616149 $ $Date: 2008-01-28 19:10:32 -0800 (Mon, 28 Jan 2008) $
+ */
+public class UnsupportedPackageTypeException extends ContributionException {
+ private static final long serialVersionUID = -1831797280021355672L;
+
+ /**
+ * Constructs a new UnsupportedPackageTypeException.
+ *
+ * @param message
+ */
+ public UnsupportedPackageTypeException(String message) {
+ super(message);
+ }
+
+}
diff --git a/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ContributionFactory b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ContributionFactory
new file mode 100644
index 0000000000..bcc346d9f8
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ContributionFactory
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+org.apache.tuscany.sca.contribution.DefaultContributionFactory \ No newline at end of file
diff --git a/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint
new file mode 100644
index 0000000000..6b4d2ebdeb
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+org.apache.tuscany.sca.contribution.DefaultModelFactoryExtensionPoint
diff --git a/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ContributionPostProcessorExtensionPoint b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ContributionPostProcessorExtensionPoint
new file mode 100644
index 0000000000..9e6433ba6c
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ContributionPostProcessorExtensionPoint
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+org.apache.tuscany.sca.contribution.processor.DefaultContributionPostProcessorExtensionPoint
diff --git a/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.PackageProcessorExtensionPoint b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.PackageProcessorExtensionPoint
new file mode 100644
index 0000000000..7609eda0d1
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.PackageProcessorExtensionPoint
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+org.apache.tuscany.sca.contribution.processor.DefaultPackageProcessorExtensionPoint
diff --git a/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint
new file mode 100644
index 0000000000..8ea5fc0a7e
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+org.apache.tuscany.sca.contribution.processor.DefaultStAXArtifactProcessorExtensionPoint
diff --git a/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint
new file mode 100644
index 0000000000..9d78ca93d0
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+org.apache.tuscany.sca.contribution.processor.DefaultURLArtifactProcessorExtensionPoint
diff --git a/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchemaExtensionPoint b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchemaExtensionPoint
new file mode 100644
index 0000000000..ae6e876df6
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchemaExtensionPoint
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+org.apache.tuscany.sca.contribution.processor.DefaultValidationSchemaExtensionPoint
diff --git a/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint
new file mode 100644
index 0000000000..4bb65e55e7
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+org.apache.tuscany.sca.contribution.resolver.DefaultModelResolverExtensionPoint
diff --git a/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.scanner.ContributionScannerExtensionPoint b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.scanner.ContributionScannerExtensionPoint
new file mode 100644
index 0000000000..727f8f6ce7
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.scanner.ContributionScannerExtensionPoint
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+org.apache.tuscany.sca.contribution.scanner.DefaultContributionScannerExtensionPoint
diff --git a/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.service.ContributionListenerExtensionPoint b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.service.ContributionListenerExtensionPoint
new file mode 100644
index 0000000000..6e61bebf79
--- /dev/null
+++ b/sandbox/mobile-android/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.service.ContributionListenerExtensionPoint
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+org.apache.tuscany.sca.contribution.service.DefaultContributionListenerExtensionPoint