summaryrefslogtreecommitdiffstats
path: root/branches/sca-java-2.0-M3/modules/contribution/src
diff options
context:
space:
mode:
authorantelder <antelder@13f79535-47bb-0310-9956-ffa450edef68>2009-06-16 06:48:13 +0000
committerantelder <antelder@13f79535-47bb-0310-9956-ffa450edef68>2009-06-16 06:48:13 +0000
commit6f41ef61af2268d5576448974ca447b597387e88 (patch)
treede4f94cc5b532a39f5968ff4fda6e714f52818a5 /branches/sca-java-2.0-M3/modules/contribution/src
parent344bc76bba5f48b3476a8fc49d68bd3392703518 (diff)
Create 2.0 M3 release branch
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@785089 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'branches/sca-java-2.0-M3/modules/contribution/src')
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java74
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Constants.java32
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.java40
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java125
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java65
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionMetadata.java56
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultContributionFactory.java32
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultExport.java30
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultImport.java30
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java48
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java57
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/PackageType.java57
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ArtifactImpl.java94
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionFactoryImpl.java60
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionImpl.java167
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionMetadataImpl.java65
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultExportImpl.java46
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultImportImpl.java56
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/DefaultJavaImportExportFactory.java30
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaExport.java43
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImport.java58
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImportExportFactory.java42
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ClassLoaderModelResolver.java183
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ClassReferenceModelResolver.java159
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ContributionClassLoader.java386
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ContributionHelper.java78
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportImpl.java59
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportModelResolver.java76
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportProcessor.java148
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportExportFactoryImpl.java41
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportImpl.java111
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportModelResolver.java62
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportProcessor.java153
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/DefaultNamespaceImportExportFactory.java30
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceExport.java46
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImport.java59
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImportExportFactory.java42
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportImpl.java55
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportModelResolver.java54
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportProcessor.java167
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportExportFactoryImpl.java41
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportImpl.java93
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportProcessor.java171
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java47
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java619
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionException.java45
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionReadException.java95
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionResolveException.java42
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionRuntimeException.java44
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionWriteException.java62
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.java66
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java420
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXAttributeProcessorExtensionPoint.java346
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java372
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java423
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidationSchemaExtensionPoint.java110
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtendedArtifactProcessor.java40
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtendedURLArtifactProcessor.java30
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java277
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXAttributeProcessor.java264
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java158
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java59
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java56
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessor.java61
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessorExtensionPoint.java56
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/TuscanyNamespaceContext.java114
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/TuscanyXMLStreamReader.java110
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java50
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java65
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnrecognizedElementException.java48
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedContentTypeException.java43
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedPackageTypeException.java40
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLInputFactory.java30
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java403
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidationSchemaExtensionPoint.java63
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/ContributionContentProcessor.java261
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/ContributionInfoProcessor.java234
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyAttributeProcessor.java80
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyElementProcessor.java161
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/XMLDocumentStreamReader.java482
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/XMLEventsStreamReader.java444
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/XMLFragmentStreamReader.java53
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java107
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultDelegatingModelResolver.java68
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java80
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportModelResolver.java69
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolver.java88
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.java114
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java200
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.java69
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java52
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResolverExtension.java45
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResourceReference.java103
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java67
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java50
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java126
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/DirectoryContributionScanner.java112
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/JarContributionScanner.java128
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionGeneratedMetadataDocumentProcessor.java50
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataDocumentProcessor.java131
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataProcessor.java246
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionModelResolver.java72
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ContributionFactory18
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.java.JavaImportExportFactory18
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.namespace.NamespaceImportExportFactory18
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor24
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint18
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXAttributeProcessor19
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXAttributeProcessorExtensionPoint18
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor22
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint18
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidatingXMLInputFactory17
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchemaExtensionPoint18
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver19
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint18
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.scanner.ContributionScannerExtensionPoint18
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/resources/contribution-java-validation-messages.properties23
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/resources/contribution-namespace-validation-messages.properties23
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/resources/contribution-validation-messages.properties34
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/main/resources/contribution-xml-validation-messages.properties24
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/java/impl/ClassReferenceArtifactResolverTestCase.java75
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/java/impl/ContributionClassLoaderTestCase.java262
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportProcessorTestCase.java108
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportProcessorTestCase.java109
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportProcessorTestCase.java111
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportProcessorTestCase.java115
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/processor/URLartifactProcessorExtensionPointTestCase.java116
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverTestCase.java91
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolverTestCase.java134
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/TestModelResolver.java58
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataProcessorTestCase.java149
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/test/resources/deployables/sample-calculator.jarbin0 -> 26901 bytes
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/test/resources/repository/sample-calculator.jarbin0 -> 29164 bytes
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/test/resources/test.composite22
-rw-r--r--branches/sca-java-2.0-M3/modules/contribution/src/test/resources/test.ext0
135 files changed, 13588 insertions, 0 deletions
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java
new file mode 100644
index 0000000000..e3e1bd8fac
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+import org.apache.tuscany.sca.assembly.Base;
+
+
+/**
+ * Represents an artifact in an SCA contribution.
+ *
+ * @version $Rev$ $Date$
+ */
+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
+ */
+ <T> T getModel();
+
+ /**
+ * Sets the in-memory model representing the artifact.
+ *
+ * @param model The model object
+ */
+ void setModel(Object model);
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Constants.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Constants.java
new file mode 100644
index 0000000000..5fb021b523
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Constants.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;
+
+/**
+ * Constants used in SCA contribution.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface Constants {
+ String XMLSCHEMA_NS = "http://www.w3.org/2001/XMLSchema";
+
+ String SCA11_NS = "http://docs.oasis-open.org/ns/opencsa/sca/200903";
+ String SCA11_TUSCANY_NS = "http://tuscany.apache.org/xmlns/sca/1.1";
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.java
new file mode 100644
index 0000000000..81b0b08b9d
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/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$ $Date$
+ */
+@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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java
new file mode 100644
index 0000000000..bdc523c33e
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.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;
+
+import java.util.List;
+import java.util.Set;
+
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.assembly.Extensible;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * The representation of an SCA contribution.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface Contribution extends Artifact, Extensible {
+
+ /**
+ * 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";
+
+ /**
+ * 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 list of contributions that this contribution depends on.
+ *
+ * @return
+ */
+ List<Contribution> getDependencies();
+
+ /**
+ * 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);
+
+ /**
+ * Get a list of mime types that apply to this contribution archive
+ * @return
+ */
+ Set<String> getTypes();
+
+} \ No newline at end of file
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java
new file mode 100644
index 0000000000..cba867cb80
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+
+/**
+ * A factory for the contribution model.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ContributionFactory {
+
+ /**
+ * Create a contribution model object
+ *
+ * @return The new contribution model object
+ */
+ Contribution createContribution();
+
+ /**
+ * Create a contribution metadata model object
+ *
+ * @return The new contribution metadata model object
+ */
+ ContributionMetadata createContributionMetadata();
+
+ /**
+ * Create an artifact model object
+ *
+ * @return The new artifact model object
+ */
+ Artifact createArtifact();
+
+ /**
+ * Create a default import model object.
+ *
+ * @return the new default import model object
+ */
+ DefaultImport createDefaultImport();
+
+ /**
+ * Create a default export model object.
+ *
+ * @return the new default export model object
+ */
+ DefaultExport createDefaultExport();
+
+} \ No newline at end of file
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionMetadata.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionMetadata.java
new file mode 100644
index 0000000000..5f26c3d907
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionMetadata.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 java.util.List;
+
+import org.apache.tuscany.sca.assembly.Base;
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.assembly.Extensible;
+
+/**
+ * The representation of SCA contribution metadata.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ContributionMetadata extends Base, Extensible {
+
+ /**
+ * Returns a list of exports based on the contribution metadata.
+ *
+ * @return The list of exports
+ */
+ List<Export> getExports();
+
+ /**
+ * Returns a list of imports based on the contribution metadata.
+ *
+ * @return The list of imports
+ */
+ List<Import> getImports();
+
+ /**
+ * Returns the list of deployable based on the contribution metadata.
+ *
+ * @return The list of deployable composites
+ */
+ List<Composite> getDeployables();
+
+} \ No newline at end of file
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultContributionFactory.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultContributionFactory.java
new file mode 100644
index 0000000000..98954c288a
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/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$ $Date$
+ */
+public class DefaultContributionFactory extends ContributionFactoryImpl {
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultExport.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultExport.java
new file mode 100644
index 0000000000..b2eddb8336
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultExport.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+
+/**
+ * The representation of an export that exports all artifacts in
+ * a contribution.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface DefaultExport extends Export {
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultImport.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultImport.java
new file mode 100644
index 0000000000..20798dcd17
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultImport.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+
+/**
+ * The representation of a default import that imports artifacts from
+ * all contributions.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface DefaultImport extends Import {
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java
new file mode 100644
index 0000000000..a6e5afe7b8
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.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;
+
+import org.apache.tuscany.sca.assembly.Extensible;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * The representation of an export.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface Export extends Extensible {
+
+ /**
+ * 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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java
new file mode 100644
index 0000000000..256a2387f1
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+import org.apache.tuscany.sca.assembly.Extensible;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+
+/**
+ * The representation of an import.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface Import extends Extensible {
+
+ /**
+ * 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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/PackageType.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/PackageType.java
new file mode 100644
index 0000000000..c6c0aff737
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/PackageType.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+/**
+ * Constants for the main supported contribution package types.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface PackageType {
+
+ /**
+ * Java compressed contribution package
+ */
+ String JAR = "application/java-archive";
+
+ /**
+ * Zip archive contribution package
+ */
+ String ZIP = "application/zip";
+
+ /**
+ * Filesystem folder contribution package
+ */
+ String FOLDER = "application/vnd.tuscany.folder";
+
+
+ String BUNDLE = "application/osgi.bundle";
+
+ /**
+ * Java EE Web Application Archive
+ */
+ String WAR = "application/war";
+
+ /**
+ * Java EE Enterprise Application Archive
+ */
+ String EAR = "application/ear";
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ArtifactImpl.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ArtifactImpl.java
new file mode 100644
index 0000000000..a362e97fc6
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ArtifactImpl.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.impl;
+
+import org.apache.tuscany.sca.contribution.Artifact;
+
+
+/**
+ * The model representing an artifact in a contribution.
+ *
+ * @version $Rev$ $Date$
+ */
+class ArtifactImpl implements Artifact {
+ private String uri;
+ private String location;
+ private Object model;
+ private boolean unresolved;
+
+ 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 <T> T getModel() {
+ return (T) model;
+ }
+
+ public void setModel(Object model) {
+ this.model = model;
+ }
+
+ 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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionFactoryImpl.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionFactoryImpl.java
new file mode 100644
index 0000000000..64bfb20bed
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionFactoryImpl.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.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.ContributionMetadata;
+import org.apache.tuscany.sca.contribution.DefaultExport;
+import org.apache.tuscany.sca.contribution.DefaultImport;
+
+
+/**
+ * Default implementation of a contribution model factory.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ContributionFactoryImpl implements ContributionFactory {
+
+ protected ContributionFactoryImpl() {
+ }
+
+ public Contribution createContribution() {
+ return new ContributionImpl();
+ }
+
+ public ContributionMetadata createContributionMetadata() {
+ return new ContributionMetadataImpl();
+ }
+
+ public Artifact createArtifact() {
+ return new ArtifactImpl();
+ }
+
+ public DefaultExport createDefaultExport() {
+ return new DefaultExportImpl();
+ }
+
+ public DefaultImport createDefaultImport() {
+ return new DefaultImportImpl();
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionImpl.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionImpl.java
new file mode 100644
index 0000000000..7be9472fc9
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionImpl.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.impl;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.assembly.impl.ExtensibleImpl;
+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$ $Date$
+ */
+class ContributionImpl extends ExtensibleImpl 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 List<Contribution> dependencies = new ArrayList<Contribution>();
+ private ModelResolver modelResolver;
+ private Set<String> types = new HashSet<String>();
+
+ // 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 <T> T getModel() {
+ return (T) 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<Contribution> getDependencies() {
+ return dependencies;
+ }
+
+ 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;
+ }
+
+ public Set<String> getTypes() {
+ return types;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionMetadataImpl.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionMetadataImpl.java
new file mode 100644
index 0000000000..da8c879a93
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionMetadataImpl.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.assembly.impl.ExtensibleImpl;
+import org.apache.tuscany.sca.contribution.ContributionMetadata;
+import org.apache.tuscany.sca.contribution.Export;
+import org.apache.tuscany.sca.contribution.Import;
+
+/**
+ * The representation of a deployed contribution
+ *
+ * @version $Rev$ $Date$
+ */
+class ContributionMetadataImpl extends ExtensibleImpl implements ContributionMetadata {
+ private boolean unresolved;
+ private List<Export> exports = new ArrayList<Export>();
+ private List<Import> imports = new ArrayList<Import>();
+ private List<Composite> deployables = new ArrayList<Composite>();
+
+ ContributionMetadataImpl() {
+ }
+
+ public boolean isUnresolved() {
+ return unresolved;
+ }
+
+ public void setUnresolved(boolean unresolved) {
+ this.unresolved = unresolved;
+ }
+
+ public List<Export> getExports() {
+ return exports;
+ }
+
+ public List<Import> getImports() {
+ return imports;
+ }
+
+ public List<Composite> getDeployables() {
+ return deployables;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultExportImpl.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultExportImpl.java
new file mode 100644
index 0000000000..d4614e5427
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultExportImpl.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.impl;
+
+import org.apache.tuscany.sca.assembly.impl.ExtensibleImpl;
+import org.apache.tuscany.sca.contribution.DefaultExport;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * The representation of an export for the contribution
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultExportImpl extends ExtensibleImpl implements DefaultExport {
+ private ModelResolver modelResolver;
+
+ protected DefaultExportImpl() {
+ super();
+ }
+
+ public ModelResolver getModelResolver() {
+ return modelResolver;
+ }
+
+ public void setModelResolver(ModelResolver modelResolver) {
+ this.modelResolver = modelResolver;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultImportImpl.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultImportImpl.java
new file mode 100644
index 0000000000..7ab535f916
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultImportImpl.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.impl;
+
+import org.apache.tuscany.sca.assembly.impl.ExtensibleImpl;
+import org.apache.tuscany.sca.contribution.DefaultExport;
+import org.apache.tuscany.sca.contribution.DefaultImport;
+import org.apache.tuscany.sca.contribution.Export;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * The representation of an import for the contribution
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultImportImpl extends ExtensibleImpl implements DefaultImport {
+ private ModelResolver modelResolver;
+
+ protected DefaultImportImpl() {
+ super();
+ }
+
+ public ModelResolver getModelResolver() {
+ return modelResolver;
+ }
+
+ public void setModelResolver(ModelResolver modelResolver) {
+ this.modelResolver = modelResolver;
+ }
+
+
+ public boolean match(Export export) {
+ if (export instanceof DefaultExport) {
+ return true;
+ }
+ return false;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/DefaultJavaImportExportFactory.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/DefaultJavaImportExportFactory.java
new file mode 100644
index 0000000000..886c61c00a
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/DefaultJavaImportExportFactory.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.java;
+
+import org.apache.tuscany.sca.contribution.java.impl.JavaImportExportFactoryImpl;
+
+/**
+ * Default Java Import/Export Factory implementation
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultJavaImportExportFactory extends JavaImportExportFactoryImpl implements JavaImportExportFactory {
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaExport.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaExport.java
new file mode 100644
index 0000000000..41e93ec148
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaExport.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.java;
+
+import org.apache.tuscany.sca.contribution.Export;
+
+/**
+ * Base Java Export model interface
+ *
+ * @version $Rev$ $Date$
+ */
+public interface JavaExport extends Export {
+ /**
+ * Get java package that identifies the import
+ *
+ * @return The package name
+ */
+ String getPackage();
+
+ /**
+ * Set java package that identifies the import
+ *
+ * @param packageName The package name
+ */
+ void setPackage(String packageName);
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImport.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImport.java
new file mode 100644
index 0000000000..d3568f6283
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImport.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.java;
+
+import org.apache.tuscany.sca.contribution.Import;
+
+/**
+ * Base Java Import model interface
+ *
+ * @version $Rev$ $Date$
+ */
+public interface JavaImport extends Import {
+
+ /**
+ * Get the location used to resolve the definitions for this import
+ *
+ * @return The import location
+ */
+ String getLocation();
+
+ /**
+ * Set the location used to resolve the definitions for this import
+ *
+ * @param location The import location
+ */
+ void setLocation(String location);
+
+ /**
+ * Get java package that identifies the import
+ *
+ * @return The package name
+ */
+ String getPackage();
+
+ /**
+ * Set java package that identifies the import
+ *
+ * @param packageName The package name
+ */
+ void setPackage(String packageName);
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImportExportFactory.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImportExportFactory.java
new file mode 100644
index 0000000000..af2ca9cd57
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImportExportFactory.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.java;
+
+/**
+ * Base Java Import/Export model factory
+ *
+ * @version $Rev$ $Date$
+ */
+public interface JavaImportExportFactory {
+
+ /**
+ * Create a java import model object
+ *
+ * @return The new JavaImport model object
+ */
+ JavaImport createJavaImport();
+
+ /**
+ * Create a java export model object
+ *
+ * @return The new JavaExport model object
+ */
+ JavaExport createJavaExport();
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ClassLoaderModelResolver.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ClassLoaderModelResolver.java
new file mode 100644
index 0000000000..d54eac2228
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ClassLoaderModelResolver.java
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.java.impl;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.Import;
+import org.apache.tuscany.sca.contribution.java.JavaImport;
+import org.apache.tuscany.sca.contribution.resolver.ClassReference;
+import org.apache.tuscany.sca.contribution.resolver.DefaultDelegatingModelResolver;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.extensibility.ServiceDiscovery;
+
+/**
+ * A Model Resolver for ClassReferences.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ClassLoaderModelResolver extends URLClassLoader implements ModelResolver {
+ private Contribution contribution;
+ private Map<String, ModelResolver> importResolvers = new HashMap<String, ModelResolver>();
+
+ private static ClassLoader parentClassLoader(Contribution contribution) {
+ if (contribution.getClassLoader() != null) {
+ return contribution.getClassLoader();
+ }
+ ClassLoader parentClassLoader = null;
+
+ // FIXME: Need a better way to not use the ThreadContextClassLoader when running in Equinox
+ if (Thread.currentThread().getContextClassLoader() != null) {
+ if (!"org.apache.tuscany.sca.extensibility.equinox.EquinoxServiceDiscoverer".equals(ServiceDiscovery.getInstance().getServiceDiscoverer().getClass().getName())) {
+ parentClassLoader = Thread.currentThread().getContextClassLoader();
+ }
+ }
+ if (parentClassLoader == null) {
+ parentClassLoader = ServiceDiscovery.getInstance().getServiceDiscoverer().getClass().getClassLoader();
+ }
+
+ return parentClassLoader;
+ }
+
+ private static URL[] getContributionURLs(final Contribution contribution) throws IOException {
+ if (contribution.getClassLoader() != null) {
+ // Do not include the contribution url
+ return new URL[0];
+ }
+ List<URL> urls = new ArrayList<URL>();
+ urls.add(new URL(contribution.getLocation()));
+ urls.addAll(ContributionHelper.getNestedJarUrls(contribution));
+ return urls.toArray(new URL[urls.size()]);
+ }
+
+ public ClassLoaderModelResolver(final Contribution contribution, FactoryExtensionPoint modelFactories) throws IOException {
+ super(getContributionURLs(contribution), parentClassLoader(contribution));
+ this.contribution = contribution;
+
+ // Index Java import resolvers by package name
+ Map<String, List<ModelResolver>> resolverMap = new HashMap<String, List<ModelResolver>>();
+ for (Import import_: this.contribution.getImports()) {
+ if (import_ instanceof JavaImport) {
+ JavaImport javaImport = (JavaImport)import_;
+ List<ModelResolver> resolvers = resolverMap.get(javaImport.getPackage());
+ if (resolvers == null) {
+ resolvers = new ArrayList<ModelResolver>();
+ resolverMap.put(javaImport.getPackage(), resolvers);
+ }
+ resolvers.add(javaImport.getModelResolver());
+ }
+ }
+
+ // Create a delegating model resolver for each imported package
+ for (Map.Entry<String, List<ModelResolver>> entry: resolverMap.entrySet()) {
+ importResolvers.put(entry.getKey(), new DefaultDelegatingModelResolver(entry.getValue()));
+ }
+ }
+
+ 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) {
+ if (!(unresolved instanceof ClassReference)) {
+ return unresolved;
+ }
+
+ try {
+
+ // Load the class and return a class reference for it
+ String className = ((ClassReference)unresolved).getClassName();
+ Class<?> clazz = Class.forName(className, true, this);
+ return modelClass.cast(new ClassReference(clazz));
+
+ } catch (ClassNotFoundException e) {
+ return unresolved;
+ } catch (NoClassDefFoundError e) {
+ return unresolved;
+ }
+ }
+
+ @Override
+ public URL findResource(String name) {
+
+ //TODO delegate to the Java import resolvers
+
+ URL url = super.findResource(name);
+ return url;
+ }
+
+ @Override
+ public Enumeration<URL> findResources(String name) throws IOException {
+
+ //TODO delegate to the Java import resolvers
+ //Enumeration<URL> importedResources;
+
+ Enumeration<URL> resources = super.findResources(name);
+ List<URL> allResources = new ArrayList<URL>();
+ //for (; importedResources.hasMoreElements(); ) {
+ // allResources.add(importedResources.nextElement());
+ //}
+ for (; resources.hasMoreElements(); ) {
+ allResources.add(resources.nextElement());
+ }
+ return Collections.enumeration(allResources);
+ }
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+
+ // Extract the package name
+ int d = name.lastIndexOf('.');
+ String packageName;
+ if (d != -1) {
+ packageName = name.substring(0, d);
+ } else {
+ packageName = null;
+ }
+
+ // First try to load the class using the Java import resolvers
+ ModelResolver importResolver = importResolvers.get(packageName);
+ if (importResolver != null) {
+ ClassReference classReference = importResolver.resolveModel(ClassReference.class, new ClassReference(name));
+ if (!classReference.isUnresolved()) {
+ return classReference.getJavaClass();
+ }
+ }
+
+ // Next, try to load the class from the current contribution
+ Class<?> clazz = super.findClass(name);
+ return clazz;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ClassReferenceModelResolver.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ClassReferenceModelResolver.java
new file mode 100644
index 0000000000..11e13ced11
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ClassReferenceModelResolver.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.java.impl;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.resolver.ClassReference;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.extensibility.ServiceDiscovery;
+
+/**
+ * A Model Resolver for ClassReferences.
+ * @deprecated Use ClassLoaderModelResolver instead
+ * @version $Rev: 557916 $ $Date: 2007-07-20 01:04:40 -0700 (Fri, 20 Jul 2007) $
+ */
+@Deprecated()
+public class ClassReferenceModelResolver implements ModelResolver {
+ private Contribution contribution;
+ private WeakReference<ClassLoader> classLoader;
+ private Map<String, ClassReference> map = new HashMap<String, ClassReference>();
+
+ private ModelResolver osgiResolver;
+
+ public ClassReferenceModelResolver(final Contribution contribution, FactoryExtensionPoint modelFactories) {
+ this.contribution = contribution;
+ if (this.contribution != null) {
+ // Allow privileged access to get ClassLoader. Requires RuntimePermission in security policy.
+ // ClassLoader cl = contribution.getClassLoader();
+ ClassLoader cl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return contribution.getClassLoader();
+ }
+ });
+
+ if (cl == null) {
+ // Allow privileged access to get ClassLoader. Requires RuntimePermission in security policy.
+ //ClassLoader contextClassLoader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ // public ClassLoader run() {
+ // return Thread.currentThread().getContextClassLoader();
+ // }
+ //});
+ ClassLoader contextClassLoader = ServiceDiscovery.getInstance().getServiceDiscoverer().getClass().getClassLoader();
+ cl = new ContributionClassLoader(contribution, contextClassLoader);
+ contribution.setClassLoader(cl);
+ }
+ this.classLoader = new WeakReference<ClassLoader>(cl);
+ } else {
+ // This path should be used only for unit testing.
+ // Allow privileged access to get ClassLoader. Requires RuntimePermission in security policy.
+ // this.classLoader = new WeakReference<ClassLoader>(this.getClass().getClassLoader());
+ ClassLoader cl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return this.getClass().getClassLoader();
+ }
+ });
+ this.classLoader = new WeakReference<ClassLoader>( cl );
+ }
+
+ try {
+ Class<?> osgiResolverClass =
+ Class.forName("org.apache.tuscany.sca.contribution.osgi.impl.OSGiClassReferenceModelResolver");
+ if (osgiResolverClass != null) {
+ Constructor<?> constructor =
+ osgiResolverClass.getConstructor(Contribution.class, FactoryExtensionPoint.class);
+ this.osgiResolver = (ModelResolver)constructor.newInstance(contribution, modelFactories);
+ }
+ } catch (Throwable e) {
+ // Ignore error, non-OSGi classloading is used in this case
+ }
+ }
+
+ public void addModel(Object resolved) {
+ ClassReference clazz = (ClassReference)resolved;
+ map.put(clazz.getClassName(), clazz);
+ }
+
+ public Object removeModel(Object resolved) {
+ return map.remove(((ClassReference)resolved).getClassName());
+ }
+
+
+
+ public <T> T resolveModel(Class<T> modelClass, T unresolved) {
+ if (!(unresolved instanceof ClassReference)) {
+ return unresolved;
+ }
+ Object resolved = map.get(((ClassReference)unresolved).getClassName());
+
+ if (resolved != null) {
+ return modelClass.cast(resolved);
+ }
+
+ //Load a class on demand
+ Class<?> clazz = null;
+
+ if (osgiResolver != null) {
+ resolved = osgiResolver.resolveModel(modelClass, unresolved);
+ clazz = ((ClassReference)resolved).getJavaClass();
+ }
+
+ if (clazz == null) {
+ try {
+ // Search contribution ClassLoader (which has visibility of classes in the contribution
+ // as well as explicitly imported packages from other contributions)
+ clazz = Class.forName(((ClassReference)unresolved).getClassName(), true, classLoader.get());
+ } catch (ClassNotFoundException e) {
+ } catch (NoClassDefFoundError e) {
+ }
+ }
+
+ if (clazz != null) {
+ //if we load the class
+ // Store a new ClassReference wrapping the loaded class
+ ClassReference classReference = new ClassReference(clazz);
+ map.put(clazz.getName(), classReference);
+
+ // Return the resolved ClassReference
+ return modelClass.cast(classReference);
+ } else {
+ return unresolved;
+ }
+
+ }
+
+
+ /***************
+ * Helper methods
+ ***************/
+
+ private String getPackageName(ClassReference clazz) {
+ int pos = clazz.getClassName().lastIndexOf(".");
+ return clazz.getClassName().substring(0, pos);
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ContributionClassLoader.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ContributionClassLoader.java
new file mode 100644
index 0000000000..97d8dcff73
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ContributionClassLoader.java
@@ -0,0 +1,386 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.java.impl;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+
+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.java.JavaImport;
+
+
+public class ContributionClassLoader extends URLClassLoader {
+// public class ContributionClassLoader {
+
+ private Contribution contribution;
+ // private b urlClassLoader;
+
+ /**
+ * Constructor for contribution ClassLoader
+ *
+ * @param contribution
+ * @param parent
+ * @throws MalformedURLException
+ */
+ public ContributionClassLoader(Contribution contribution, final ClassLoader parent) {
+ super(new URL[0], parent);
+ // Note that privileged use of getContextClassLoader have been promoted to callers.
+ // super(new URL[0], parent == null?Thread.currentThread().getContextClassLoader(): null);
+ this.contribution = contribution;
+ if (contribution.getLocation() != null) {
+ try {
+ this.addURL(new URL(contribution.getLocation()));
+ for (URL url : ContributionHelper.getNestedJarUrls(contribution)) {
+ this.addURL(url);
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /*
+ * Return the ClassLoader corresponding to a contribution providing an export
+ * Create a new ClassLoader for the contribution if one does not exist
+ */
+ private ClassLoader getExportClassLoader(Contribution exportingContribution) {
+ ClassLoader cl = exportingContribution.getClassLoader();
+ if (!(cl instanceof ContributionClassLoader)) {
+ if (cl == null) {
+ cl = getParent();
+ }
+
+ cl = new ContributionClassLoader(exportingContribution, cl);
+ exportingContribution.setClassLoader(cl);
+ }
+ return cl;
+ }
+
+ /* (non-Javadoc)
+ * @see java.net.URLClassLoader#findClass(java.lang.String)
+ *
+ * Search path for class:
+ * This contribution
+ * Imported contributions
+ */
+ @Override
+ protected Class<?> findClass(String className) throws ClassNotFoundException {
+
+ Class<?> clazz = null;
+ try {
+ clazz = findClassFromContribution(className);
+ } catch (ClassNotFoundException e) {
+
+ for (Import import_ : this.contribution.getImports()) {
+ if (classNameMatchesImport(className, import_)) {
+ // Delegate the resolution to the imported contribution
+ for (Contribution exportingContribution : ((JavaImportModelResolver)import_.getModelResolver()).getExportContributions()) {
+
+ ClassLoader exportClassLoader = getExportClassLoader(exportingContribution);
+ if (exportClassLoader instanceof ContributionClassLoader) {
+
+ for (Export export : exportingContribution.getExports()) {
+ try {
+ if (import_.match(export)) {
+ clazz = ((ContributionClassLoader)exportClassLoader).findClassFromContribution(className);
+ break;
+ }
+ } catch (ClassNotFoundException e1) {
+ continue;
+ }
+
+ }
+ if (clazz != null) break;
+ }
+ }
+ if (clazz != null) break;
+ }
+ }
+
+ if (clazz == null) throw e;
+ }
+ return clazz;
+ }
+
+
+ /* (non-Javadoc)
+ * @see java.lang.ClassLoader#loadClass(java.lang.String, boolean)
+ *
+ * Search path for class:
+ * Parent ClassLoader
+ * This contribution
+ * Imported contributions
+ *
+ */
+ @Override
+ protected synchronized Class<?> loadClass(String className, boolean resolveClass)
+ throws ClassNotFoundException {
+
+ Class<?> clazz = null;
+ try {
+
+ if (this.getParent() != null)
+ clazz = this.getParent().loadClass(className);
+
+ } catch (ClassNotFoundException e) {
+ }
+
+ if (clazz == null)
+ clazz = findClass(className);
+
+
+ if (resolveClass)
+ this.resolveClass(clazz);
+ return clazz;
+
+ }
+
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.net.URLClassLoader#findResource(java.lang.String)
+ */
+ @Override
+ public URL findResource(String name) {
+
+ URL url = findResourceFromContribution(name);
+
+ if (url == null) {
+ for (Import import_ : this.contribution.getImports()) {
+ if (resourceNameMatchesImport(name, import_)) {
+ // Delegate the resolution to the imported contribution
+ for (Contribution exportingContribution : ((JavaImportModelResolver)import_.getModelResolver()).getExportContributions()) {
+
+ ClassLoader exportClassLoader = getExportClassLoader(exportingContribution);
+ if (exportClassLoader instanceof ContributionClassLoader) {
+
+ for (Export export : exportingContribution.getExports()) {
+ if (import_.match(export)) {
+ url = ((ContributionClassLoader)exportClassLoader).findResourceFromContribution(name);
+ if (url != null) break;
+ }
+ }
+ if (url != null) break;
+ }
+ }
+ if (url != null) break;
+ }
+ }
+
+ }
+ return url;
+ }
+
+
+ /* (non-Javadoc)
+ * @see java.net.URLClassLoader#findResources(java.lang.String)
+ */
+ @Override
+ public Enumeration<URL> findResources(String name) throws IOException {
+
+ return Collections.enumeration(findResourceSet(name));
+ }
+
+
+
+
+ /* (non-Javadoc)
+ * @see java.lang.ClassLoader#getResource(java.lang.String)
+ *
+ * Find a resource.
+ * Search path for resource:
+ * Parent ClassLoader
+ * This contribution
+ * Imported contributions
+ */
+ @Override
+ public URL getResource(String resName) {
+
+ URL resource = null;
+
+ if (this.getParent() != null) {
+ resource = this.getParent().getResource(resName);
+ }
+ if (resource == null)
+ resource = findResource(resName);
+
+ return resource;
+ }
+
+
+
+ /* (non-Javadoc)
+ * @see java.lang.ClassLoader#getResources(java.lang.String)
+ *
+ * Return list of resources from this contribution, resources
+ * imported through imported contributions and resources from parent
+ * ClassLoader.
+ */
+ @Override
+ public Enumeration<URL> getResources(String resName) throws IOException {
+
+ HashSet<URL> resourceSet = findResourceSet(resName);
+ addEnumerationToCollection(resourceSet, super.getResources(resName));
+
+ return Collections.enumeration(resourceSet);
+ }
+
+
+ /*
+ * Find set of resources
+ */
+ private HashSet<URL> findResourceSet(String name) throws IOException {
+
+ HashSet<URL> resources = new HashSet<URL>();
+
+ addEnumerationToCollection(resources, super.findResources(name));
+
+ for (Import import_ : this.contribution.getImports()) {
+ if (!(import_ instanceof JavaImport)) {
+ continue;
+ }
+ if (resourceNameMatchesImport(name, import_)) {
+ // Delegate the resolution to the imported contribution
+ for (Contribution exportingContribution : ((JavaImportModelResolver)import_.getModelResolver()).getExportContributions()) {
+
+ ClassLoader exportClassLoader = getExportClassLoader(exportingContribution);
+ if (exportClassLoader instanceof ContributionClassLoader) {
+
+ for (Export export : exportingContribution.getExports()) {
+ if (import_.match(export)) {
+ addEnumerationToCollection(resources,
+ ((ContributionClassLoader)exportClassLoader).findResources(name));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return resources;
+ }
+
+
+ /*
+ * Find class from contribution. If class has already been loaded, return loaded class.
+ */
+ private Class<?> findClassFromContribution(String className) throws ClassNotFoundException {
+
+ Class<?> clazz = findLoadedClass(className);
+ if (clazz == null)
+ clazz = super.findClass(className);
+ return clazz;
+
+ }
+
+ /*
+ * Find resource from contribution.
+ */
+ private URL findResourceFromContribution(String name) {
+
+ return super.findResource(name);
+ }
+
+ /**
+ * Check if a class name matches an import statement.
+ * Class matches if the package name used in <import.java/> matches
+ *
+ * @param name Name of class
+ * @param import_ SCA contribution import
+ * @return true if this is a matching import
+ */
+ private boolean classNameMatchesImport(String name, Import import_) {
+
+ if (import_ instanceof JavaImport && name != null && name.lastIndexOf('.') > 0) {
+ JavaImport javaImport = (JavaImport) import_;
+
+ String packageName = name.substring(0, name.lastIndexOf('.'));
+ if (javaImport.getPackage().endsWith(".*")) {
+ String prefix = javaImport.getPackage().substring(0, javaImport.getPackage().length() -1);
+ if (packageName.startsWith(prefix)) {
+ return true;
+ }
+ } else {
+ return packageName.equals(javaImport.getPackage());
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Check if a resource name matches an import statement.
+ * Resource matches if package/namespace match the directory of resource.
+ *
+ * @param name Name of resource
+ * @param import_ SCA contribution import
+ * @return true if this is a matching import
+ */
+ private boolean resourceNameMatchesImport(String name, Import import_) {
+
+
+ if (name == null || name.lastIndexOf('/') <= 0)
+ return false;
+ else if (import_ instanceof JavaImport) {
+ JavaImport javaImport = (JavaImport) import_;
+
+ if (javaImport.getPackage().endsWith(".*")) {
+ String packageName = name.substring(0, name.lastIndexOf('/')).replace('/', '.');
+ String prefix = javaImport.getPackage().substring(0, javaImport.getPackage().length() -1);
+ if (packageName.startsWith(prefix)) {
+ return true;
+ }
+ } else {
+ // 'name' is a resource : contains "/" as separators
+ // Get package name from resource name
+ String packageName = name.substring(0, name.lastIndexOf('/'));
+ return packageName.equals(javaImport.getPackage().replaceAll("\\.", "/"));
+ }
+ }
+ return false;
+ }
+
+ /*
+ * Add an enumeration to a Collection
+ */
+ private <T extends Object> void addEnumerationToCollection(Collection<T> collection, Enumeration<T> enumeration) {
+
+ while (enumeration.hasMoreElements())
+ collection.add(enumeration.nextElement());
+ }
+
+
+ @Override
+ public String toString() {
+ return "SCA Contribution ClassLoader location: " + contribution.getLocation() + " parent ClassLoader: " + getParent();
+ }
+
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ContributionHelper.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ContributionHelper.java
new file mode 100644
index 0000000000..54554bcc4e
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ContributionHelper.java
@@ -0,0 +1,78 @@
+package org.apache.tuscany.sca.contribution.java.impl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.apache.tuscany.sca.contribution.Artifact;
+import org.apache.tuscany.sca.contribution.Contribution;
+
+public class ContributionHelper {
+
+ public static List<URL> getNestedJarUrls(final Contribution contribution) throws IOException {
+ List<URL> urls = new ArrayList<URL>();
+ boolean isZipContribution = contribution.getLocation().endsWith(".zip");
+ URI uri = URI.create(contribution.getLocation());
+ boolean isFolderContribution = !isZipContribution && uri.getScheme().equals("file") && new File(uri).isDirectory();
+ if (isZipContribution || isFolderContribution) {
+ for (Artifact a : contribution.getArtifacts()) {
+ if (a.getLocation().endsWith(".jar")) {
+ if (isZipContribution) {
+ urls.add(createTempJar(a, contribution));
+ } else {
+ urls.add(new URL(a.getLocation()));
+ }
+ }
+ }
+ }
+ return urls;
+ }
+
+ /**
+ * URLClassLoader doesn't seem to work with URLs to jars within an archive so as a work around
+ * copy the jar to a temp file and use the url to that.
+ */
+ private static URL createTempJar(Artifact artifact, Contribution contribution) throws IOException {
+ FileOutputStream fileOutputStream = null;
+ ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(new File(URI.create(contribution.getLocation()))));
+ try {
+ ZipEntry zipEntry = zipInputStream.getNextEntry();
+ while (zipEntry != null) {
+ if (artifact.getLocation().endsWith(zipEntry.getName())) {
+
+ String tempName = ("tmp." + artifact.getURI().substring(0, artifact.getURI().length() - 3)).replace('/', '.');
+ File tempFile = File.createTempFile(tempName, ".jar");
+ tempFile.deleteOnExit();
+ fileOutputStream = new FileOutputStream(tempFile);
+
+ byte[] buf = new byte[2048];
+ int n;
+ while ((n = zipInputStream.read(buf, 0, buf.length)) > -1) {
+ fileOutputStream.write(buf, 0, n);
+ }
+
+ fileOutputStream.close();
+ zipInputStream.closeEntry();
+
+ return tempFile.toURI().toURL();
+
+ }
+ zipEntry = zipInputStream.getNextEntry();
+ }
+ } finally {
+ zipInputStream.close();
+ if (fileOutputStream != null) {
+ fileOutputStream.close();
+ }
+ }
+
+ throw new IllegalStateException();
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportImpl.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportImpl.java
new file mode 100644
index 0000000000..c0bd9465e4
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.java.impl;
+
+import org.apache.tuscany.sca.assembly.impl.ExtensibleImpl;
+import org.apache.tuscany.sca.contribution.java.JavaExport;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * Implementation of a Java Import model
+ *
+ * @version $Rev$ $Date$
+ */
+public class JavaExportImpl extends ExtensibleImpl implements JavaExport {
+ private ModelResolver modelResolver;
+
+ /**
+ * Java package being exported
+ */
+ private String packageName;
+
+ public JavaExportImpl() {
+ super();
+ }
+
+ public String getPackage() {
+ return this.packageName;
+ }
+
+ public void setPackage(String packageName) {
+ this.packageName = packageName;
+ }
+
+ public ModelResolver getModelResolver() {
+ return modelResolver;
+ }
+
+ public void setModelResolver(ModelResolver modelResolver) {
+ this.modelResolver = modelResolver;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportModelResolver.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportModelResolver.java
new file mode 100644
index 0000000000..8d5412f6d7
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportModelResolver.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.java.impl;
+
+import org.apache.tuscany.sca.contribution.java.JavaExport;
+import org.apache.tuscany.sca.contribution.resolver.ClassReference;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * A model resolver for Java exports.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JavaExportModelResolver implements ModelResolver {
+
+ private JavaExport export;
+ private ModelResolver resolver;
+
+ public JavaExportModelResolver(JavaExport export, ModelResolver resolver) {
+ this.export = export;
+ this.resolver = resolver;
+ }
+
+ 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) {
+ if (!(unresolved instanceof ClassReference)) {
+ return unresolved;
+ }
+
+ // Filter package name
+ ClassReference classReference = (ClassReference)unresolved;
+ String className = classReference.getClassName();
+ int d = className.lastIndexOf('.');
+ String packageName;
+ if (d != -1) {
+ packageName = className.substring(0, d);
+ } else {
+ packageName = "";
+ }
+ if (export.getPackage().equals(packageName)) {
+
+ // Package matches the exported package, delegate to the
+ // contribution's resolver
+ return resolver.resolveModel(modelClass, unresolved);
+ } else {
+
+ // Package is not exported, return the unresolved object
+ return unresolved;
+ }
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportProcessor.java
new file mode 100644
index 0000000000..6decc004a6
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportProcessor.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.java.impl;
+
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+
+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;
+
+import org.apache.tuscany.sca.contribution.java.JavaExport;
+import org.apache.tuscany.sca.contribution.java.JavaImportExportFactory;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.processor.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.processor.ContributionWriteException;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.apache.tuscany.sca.monitor.Problem.Severity;
+
+/**
+ * Artifact processor for Java Export
+ *
+ * @version $Rev$ $Date$
+ */
+public class JavaExportProcessor implements StAXArtifactProcessor<JavaExport> {
+ private static final String SCA11_NS = "http://docs.oasis-open.org/ns/opencsa/sca/200903";
+
+ private static final QName EXPORT_JAVA = new QName(SCA11_NS, "export.java");
+
+ private static final String PACKAGE = "package";
+
+ private final JavaImportExportFactory factory;
+ private final Monitor monitor;
+
+ public JavaExportProcessor(FactoryExtensionPoint modelFactories, Monitor monitor) {
+ super();
+ this.factory = modelFactories.getFactory(JavaImportExportFactory.class);
+ this.monitor = monitor;
+ }
+
+ /**
+ * Report a error.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(String message, Object model, Object... messageParameters) {
+ if (monitor != null) {
+ Problem problem = monitor.createProblem(this.getClass().getName(), "contribution-java-validation-messages", Severity.ERROR, model, message, (Object[])messageParameters);
+ monitor.problem(problem);
+ }
+ }
+
+ public QName getArtifactType() {
+ return EXPORT_JAVA;
+ }
+
+ public Class<JavaExport> getModelType() {
+ return JavaExport.class;
+ }
+
+ /**
+ * Process <export package=""/>
+ */
+ public JavaExport read(XMLStreamReader reader) throws ContributionReadException {
+ JavaExport javaExport = this.factory.createJavaExport();
+ QName element = null;
+
+ try {
+ while (reader.hasNext()) {
+ int event = reader.getEventType();
+ switch (event) {
+ case START_ELEMENT:
+ element = reader.getName();
+
+ // Read <export.java>
+ if (EXPORT_JAVA.equals(element)) {
+ String packageName = reader.getAttributeValue(null, PACKAGE);
+ if (packageName == null) {
+ error("AttributePackageMissing", reader);
+ //throw new ContributionReadException("Attribute 'package' is missing");
+ } else
+ javaExport.setPackage(packageName);
+ }
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ if (EXPORT_JAVA.equals(reader.getName())) {
+ return javaExport;
+ }
+ break;
+ }
+
+ //Read the next element
+ if (reader.hasNext()) {
+ reader.next();
+ }
+ }
+ }
+ catch (XMLStreamException e) {
+ ContributionReadException ex = new ContributionReadException(e);
+ error("XMLStreamException", reader, ex);
+ }
+
+ return javaExport;
+ }
+
+ public void write(JavaExport javaExport, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException {
+
+ // Write <export.java>
+ writer.writeStartElement(EXPORT_JAVA.getNamespaceURI(), EXPORT_JAVA.getLocalPart());
+
+ if (javaExport.getPackage() != null) {
+ writer.writeAttribute(PACKAGE, javaExport.getPackage());
+ }
+
+ writer.writeEndElement();
+ }
+
+ public void resolve(JavaExport javaExport, ModelResolver resolver) throws ContributionResolveException {
+
+ if (javaExport.getPackage() != null)
+ // Initialize the export resolver
+ javaExport.setModelResolver(new JavaExportModelResolver(javaExport, resolver));
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportExportFactoryImpl.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportExportFactoryImpl.java
new file mode 100644
index 0000000000..e5dc397f4e
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportExportFactoryImpl.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.java.impl;
+
+import org.apache.tuscany.sca.contribution.java.JavaExport;
+import org.apache.tuscany.sca.contribution.java.JavaImport;
+import org.apache.tuscany.sca.contribution.java.JavaImportExportFactory;
+
+/**
+ * Java Import/Export Factory implementation
+ *
+ * @version $Rev$ $Date$
+ */
+public class JavaImportExportFactoryImpl implements JavaImportExportFactory {
+
+ public JavaImport createJavaImport() {
+ return new JavaImportImpl();
+ }
+
+ public JavaExport createJavaExport() {
+ return new JavaExportImpl();
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportImpl.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportImpl.java
new file mode 100644
index 0000000000..f2fdb3278e
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportImpl.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.java.impl;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.impl.ExtensibleImpl;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.Export;
+import org.apache.tuscany.sca.contribution.java.JavaExport;
+import org.apache.tuscany.sca.contribution.java.JavaImport;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * Implementation of a Java Import model
+ *
+ * @version $Rev$ $Date$
+ */
+public class JavaImportImpl extends ExtensibleImpl implements JavaImport {
+ private ModelResolver modelResolver;
+ private List<Contribution> contributions;
+ /**
+ * Java package name being imported
+ */
+ private String packageName;
+ /**
+ * Contribution URI where the artifact is imported from
+ */
+ private String location;
+
+ public JavaImportImpl() {
+ super();
+ }
+
+ public String getLocation() {
+ return this.location;
+ }
+
+ public void setLocation(String location) {
+ this.location = location;
+ }
+
+ public String getPackage() {
+ return this.packageName;
+ }
+
+ public void setPackage(String packageName) {
+ this.packageName = packageName;
+ }
+
+ public ModelResolver getModelResolver() {
+ return this.modelResolver;
+ }
+
+ public void setModelResolver(ModelResolver modelResolver) {
+ this.modelResolver = modelResolver;
+ }
+ public List<Contribution> getExportContributions() {
+ return contributions;
+ }
+
+ public void setExportContributions(List<Contribution> contributions) {
+ this.contributions = contributions;
+ }
+
+ /**
+ * Match a JavaImport to a given JavaExport based on :
+ * location is not provided
+ * import and export packages match
+ */
+ public boolean match(Export export) {
+ if(export instanceof JavaExport) {
+ JavaExport javaExport = (JavaExport)export;
+ String exportedPackage = javaExport.getPackage();
+ if (packageName.equals(exportedPackage)) {
+ return true;
+ } else {
+ if (packageName.endsWith(".*")) {
+ String prefix = packageName.substring(0, packageName.length() - 1);
+ if (exportedPackage.startsWith(prefix)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(packageName);
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportModelResolver.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportModelResolver.java
new file mode 100644
index 0000000000..484eddd222
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportModelResolver.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.java.impl;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * A JavaImport specific model resolver. This model resolver is temporary
+ * and provides the ContributionClassLoader with the list of exporting
+ * contributions that it currently needs.
+ *
+ * FIXME Remove this class after the ContributionClassLoader is simplified
+ * and cleaned up.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JavaImportModelResolver implements ModelResolver {
+
+ private ModelResolver modelResolver;
+ private List<Contribution> contributions;
+
+ public JavaImportModelResolver(List<Contribution> contributions, ModelResolver modelResolver) {
+ this.modelResolver = modelResolver;
+ this.contributions = contributions;
+ }
+
+ public List<Contribution> getExportContributions() {
+ return contributions;
+ }
+
+ public void addModel(Object resolved) {
+ modelResolver.addModel(resolved);
+ }
+
+ public Object removeModel(Object resolved) {
+ return modelResolver.removeModel(resolved);
+ }
+
+ public <T> T resolveModel(Class<T> modelClass, T unresolved) {
+ return modelResolver.resolveModel(modelClass, unresolved);
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportProcessor.java
new file mode 100644
index 0000000000..48a1698bf4
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportProcessor.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.java.impl;
+
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+
+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;
+
+import org.apache.tuscany.sca.contribution.java.JavaImport;
+import org.apache.tuscany.sca.contribution.java.JavaImportExportFactory;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.processor.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.processor.ContributionWriteException;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.apache.tuscany.sca.monitor.Problem.Severity;
+
+/**
+ * Artifact Processor for Java Imports
+ *
+ * @version $Rev$ $Date$
+ */
+public class JavaImportProcessor implements StAXArtifactProcessor<JavaImport> {
+ private static final String SCA11_NS = "http://docs.oasis-open.org/ns/opencsa/sca/200903";
+
+ private static final QName IMPORT_JAVA = new QName(SCA11_NS, "import.java");
+
+ private static final String PACKAGE = "package";
+ private static final String LOCATION = "location";
+
+ private final JavaImportExportFactory factory;
+ private final Monitor monitor;
+
+ public JavaImportProcessor(FactoryExtensionPoint modelFactories, Monitor monitor) {
+ super();
+ this.factory = modelFactories.getFactory(JavaImportExportFactory.class);
+ this.monitor = monitor;
+ }
+
+ /**
+ * Report a error.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(String message, Object model, Object... messageParameters) {
+ if (monitor != null) {
+ Problem problem = monitor.createProblem(this.getClass().getName(), "contribution-java-validation-messages", Severity.ERROR, model, message, (Object[])messageParameters);
+ monitor.problem(problem);
+ }
+ }
+
+ public QName getArtifactType() {
+ return IMPORT_JAVA;
+ }
+
+ public Class<JavaImport> getModelType() {
+ return JavaImport.class;
+ }
+
+ /**
+ * Process <import.java package="" location=""/>
+ */
+ public JavaImport read(XMLStreamReader reader) throws ContributionReadException {
+ JavaImport javaImport = this.factory.createJavaImport();
+ QName element = null;
+
+ try {
+ while (reader.hasNext()) {
+ int event = reader.getEventType();
+ switch (event) {
+ case START_ELEMENT:
+ element = reader.getName();
+
+ // Read <import.java>
+ if (IMPORT_JAVA.equals(element)) {
+ String packageName = reader.getAttributeValue(null, PACKAGE);
+ if (packageName == null) {
+ error("AttributePackageMissing", reader);
+ //throw new ContributionReadException("Attribute 'package' is missing");
+ } else
+ javaImport.setPackage(packageName);
+
+ String location = reader.getAttributeValue(null, LOCATION);
+ javaImport.setLocation(location);
+ }
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ if (IMPORT_JAVA.equals(reader.getName())) {
+ return javaImport;
+ }
+ break;
+ }
+
+ // Read the next element
+ if (reader.hasNext()) {
+ reader.next();
+ }
+ }
+ }
+ catch (XMLStreamException e) {
+ ContributionReadException ex = new ContributionReadException(e);
+ error("XMLStreamException", reader, ex);
+ }
+
+ return javaImport;
+ }
+
+ public void write(JavaImport javaImport, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException {
+
+ // Write <import.java>
+ writer.writeStartElement(IMPORT_JAVA.getNamespaceURI(), IMPORT_JAVA.getLocalPart());
+
+ if (javaImport.getPackage() != null) {
+ writer.writeAttribute(PACKAGE, javaImport.getPackage());
+ }
+ if (javaImport.getLocation() != null) {
+ writer.writeAttribute(LOCATION, javaImport.getLocation());
+ }
+
+ writer.writeEndElement();
+ }
+
+
+ public void resolve(JavaImport model, ModelResolver resolver) throws ContributionResolveException {
+
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/DefaultNamespaceImportExportFactory.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/DefaultNamespaceImportExportFactory.java
new file mode 100644
index 0000000000..a71fa61a54
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/DefaultNamespaceImportExportFactory.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.namespace;
+
+import org.apache.tuscany.sca.contribution.namespace.impl.NamespaceImportExportFactoryImpl;
+
+/**
+ * Default Namespace Import/Export model factory implementation
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultNamespaceImportExportFactory extends NamespaceImportExportFactoryImpl implements NamespaceImportExportFactory {
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceExport.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceExport.java
new file mode 100644
index 0000000000..c68aee8521
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceExport.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.namespace;
+
+import org.apache.tuscany.sca.contribution.Export;
+
+
+/**
+ * The representation of an XML namespace export.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface NamespaceExport extends Export {
+
+ /**
+ * Get Namespace that identifies the export
+ *
+ * @return The exported namespace
+ */
+ String getNamespace();
+
+ /**
+ * Set Namespace that identifies the export
+ *
+ * @param namespace The exported namespace
+ */
+ void setNamespace(String namespace);
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImport.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImport.java
new file mode 100644
index 0000000000..8af36d7da0
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImport.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.namespace;
+
+import org.apache.tuscany.sca.contribution.Import;
+
+/**
+ * The representation of an XML namespace import.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface NamespaceImport extends Import {
+
+ /**
+ * Get the location used to resolve the definitions for this import
+ *
+ * @return The import location
+ */
+ String getLocation();
+
+ /**
+ * Set the location used to resolve the definitions for this import
+ *
+ * @param location The import location
+ */
+ void setLocation(String location);
+
+ /**
+ * Get Namespace that identifies the import
+ *
+ * @return The namespace
+ */
+ String getNamespace();
+
+ /**
+ * Set Namespace that identifies the import
+ *
+ * @param namespace The namespace
+ */
+ void setNamespace(String namespace);
+
+} \ No newline at end of file
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImportExportFactory.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImportExportFactory.java
new file mode 100644
index 0000000000..cfbac8bb1f
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImportExportFactory.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.namespace;
+
+/**
+ * Base Namespace import/export model factory
+ *
+ * @version $Rev$ $Date$
+ */
+public interface NamespaceImportExportFactory {
+
+ /**
+ * Create a namespace import model object
+ *
+ * @return The new NamespaceImport model object
+ */
+ NamespaceImport createNamespaceImport();
+
+ /**
+ * Create a namespace export model object
+ *
+ * @return The new NamespaceExport model object
+ */
+ NamespaceExport createNamespaceExport();
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportImpl.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportImpl.java
new file mode 100644
index 0000000000..99af328964
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportImpl.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.namespace.impl;
+
+import org.apache.tuscany.sca.assembly.impl.ExtensibleImpl;
+import org.apache.tuscany.sca.contribution.namespace.NamespaceExport;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * The representation of an export for the contribution
+ *
+ * @version $Rev$ $Date$
+ */
+public class NamespaceExportImpl extends ExtensibleImpl implements NamespaceExport {
+ private String namespace;
+ private ModelResolver modelResolver;
+
+ protected NamespaceExportImpl() {
+ super();
+ }
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+ public void setNamespace(String namespace) {
+ this.namespace = namespace;
+ }
+
+ public ModelResolver getModelResolver() {
+ return modelResolver;
+ }
+
+ public void setModelResolver(ModelResolver modelResolver) {
+ this.modelResolver = modelResolver;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportModelResolver.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportModelResolver.java
new file mode 100644
index 0000000000..5c5ae22f77
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportModelResolver.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.namespace.impl;
+
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * A model resolver for namespace exports.
+ *
+ * @version $Rev$ $Date$
+ */
+public class NamespaceExportModelResolver implements ModelResolver {
+
+ private ModelResolver resolver;
+
+ public NamespaceExportModelResolver(ModelResolver resolver) {
+ this.resolver = resolver;
+ }
+
+ 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) {
+
+ // Just delegate to the contribution's model resolver, namespace
+ // based filtering is implemented in the model specific model
+ // resolver, which know how to get the namespace of the particular
+ // type of model that they handle
+ return resolver.resolveModel(modelClass, unresolved);
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportProcessor.java
new file mode 100644
index 0000000000..030fc1754b
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportProcessor.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.namespace.impl;
+
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+
+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;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.contribution.namespace.NamespaceExport;
+import org.apache.tuscany.sca.contribution.namespace.NamespaceImportExportFactory;
+import org.apache.tuscany.sca.contribution.processor.BaseStAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.processor.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.processor.ContributionWriteException;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXAttributeProcessor;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.apache.tuscany.sca.monitor.Problem.Severity;
+
+/**
+ * Artifact processor for Namespace export
+ *
+ * @version $Rev$ $Date$
+ */
+public class NamespaceExportProcessor extends BaseStAXArtifactProcessor implements StAXArtifactProcessor<NamespaceExport> {
+
+ private static final String SCA11_NS = "http://docs.oasis-open.org/ns/opencsa/sca/200903";
+ private static final QName EXPORT = new QName(SCA11_NS, "export");
+ private static final String NAMESPACE = "namespace";
+
+ private final NamespaceImportExportFactory factory;
+ private final AssemblyFactory extensionFactory;
+ private final StAXArtifactProcessor<Object> extensionProcessor;
+ private final StAXAttributeProcessor<Object> attributeProcessor;
+ private final Monitor monitor;
+
+ public NamespaceExportProcessor(FactoryExtensionPoint modelFactories,
+ StAXArtifactProcessor<Object> extensionProcessor,
+ StAXAttributeProcessor<Object> attributeProcessor,
+ Monitor monitor) {
+ this.factory = modelFactories.getFactory(NamespaceImportExportFactory.class);
+ this.extensionFactory = modelFactories.getFactory(AssemblyFactory.class);
+ this.extensionProcessor = extensionProcessor;
+ this.attributeProcessor = attributeProcessor;
+ this.monitor = monitor;
+ }
+
+ /**
+ * Report a warning.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(String message, Object model, Object... messageParameters) {
+ if (monitor != null) {
+ Problem problem = monitor.createProblem(this.getClass().getName(), "contribution-namespace-validation-messages", Severity.ERROR, model, message, (Object[])messageParameters);
+ monitor.problem(problem);
+ }
+ }
+
+ public QName getArtifactType() {
+ return EXPORT;
+ }
+
+ public Class<NamespaceExport> getModelType() {
+ return NamespaceExport.class;
+ }
+
+ /**
+ * Process <export namespace=""/>
+ */
+ public NamespaceExport read(XMLStreamReader reader) throws ContributionReadException {
+ NamespaceExport namespaceExport = this.factory.createNamespaceExport();
+ QName element = null;
+
+ try {
+ while (reader.hasNext()) {
+ int event = reader.getEventType();
+ switch (event) {
+ case START_ELEMENT:
+ element = reader.getName();
+
+ // Read <export>
+ if (EXPORT.equals(element)) {
+ String ns = reader.getAttributeValue(null, NAMESPACE);
+ if (ns == null) {
+ error("AttributeNameSpaceMissing", reader);
+ //throw new ContributionReadException("Attribute 'namespace' is missing");
+ } else {
+ namespaceExport.setNamespace(ns);
+ }
+ readExtendedAttributes(reader, namespaceExport, attributeProcessor, extensionFactory);
+ } else {
+ readExtendedElement(reader, namespaceExport, extensionProcessor);
+ }
+
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ if (EXPORT.equals(reader.getName())) {
+ return namespaceExport;
+ }
+ break;
+ }
+
+ // Read the next element
+ if (reader.hasNext()) {
+ reader.next();
+ }
+ }
+ }
+ catch (XMLStreamException e) {
+ ContributionReadException ex = new ContributionReadException(e);
+ error("XMLStreamException", reader, ex);
+ }
+
+ return namespaceExport;
+ }
+
+ public void write(NamespaceExport namespaceExport, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException {
+
+ // Write <export>
+ writer.writeStartElement(EXPORT.getNamespaceURI(), EXPORT.getLocalPart());
+
+ if (namespaceExport.getNamespace() != null) {
+ writer.writeAttribute(NAMESPACE, namespaceExport.getNamespace());
+ }
+
+ writeExtendedAttributes(writer, namespaceExport, attributeProcessor);
+
+ writeExtendedElements(writer, namespaceExport, extensionProcessor);
+
+ writer.writeEndElement();
+ }
+
+ public void resolve(NamespaceExport namespaceExport, ModelResolver resolver) throws ContributionResolveException {
+
+ if (namespaceExport.getNamespace() != null)
+ // Initialize the export's resolver
+ namespaceExport.setModelResolver(new NamespaceExportModelResolver(resolver));
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportExportFactoryImpl.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportExportFactoryImpl.java
new file mode 100644
index 0000000000..1146e593a9
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportExportFactoryImpl.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.namespace.impl;
+
+import org.apache.tuscany.sca.contribution.namespace.NamespaceExport;
+import org.apache.tuscany.sca.contribution.namespace.NamespaceImport;
+import org.apache.tuscany.sca.contribution.namespace.NamespaceImportExportFactory;
+
+/**
+ * Namespace Import/Export model factory implementation
+ *
+ * @version $Rev$ $Date$
+ */
+public class NamespaceImportExportFactoryImpl implements NamespaceImportExportFactory {
+
+ public NamespaceImport createNamespaceImport() {
+ return new NamespaceImportImpl();
+ }
+
+ public NamespaceExport createNamespaceExport() {
+ return new NamespaceExportImpl();
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportImpl.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportImpl.java
new file mode 100644
index 0000000000..35e2d539d4
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportImpl.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.namespace.impl;
+
+import org.apache.tuscany.sca.assembly.impl.ExtensibleImpl;
+import org.apache.tuscany.sca.contribution.Export;
+import org.apache.tuscany.sca.contribution.namespace.NamespaceExport;
+import org.apache.tuscany.sca.contribution.namespace.NamespaceImport;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * The representation of an import for the contribution
+ *
+ * @version $Rev$ $Date$
+ */
+public class NamespaceImportImpl extends ExtensibleImpl implements NamespaceImport {
+ private ModelResolver modelResolver;
+
+ /**
+ * The namespace to be imported
+ */
+ private String namespace;
+ /**
+ * Optional location URI pointing to a Contribution that exports the namespace
+ */
+ private String location;
+
+
+ protected NamespaceImportImpl() {
+ super();
+ }
+
+ public String getLocation() {
+ return location;
+ }
+
+ public void setLocation(String location) {
+ this.location = location;
+ }
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+ public void setNamespace(String namespace) {
+ this.namespace = namespace;
+ }
+
+ public ModelResolver getModelResolver() {
+ return modelResolver;
+ }
+
+ public void setModelResolver(ModelResolver modelResolver) {
+ this.modelResolver = modelResolver;
+ }
+
+
+ /**
+ * Match a NamespaceImport to a given NamespaceExport based on :
+ * location is not provided
+ * import and export namespaces match
+ */
+ public boolean match(Export export) {
+ if (export instanceof NamespaceExport) {
+ if (this.getNamespace().equals(((NamespaceExport)export).getNamespace())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(namespace);
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportProcessor.java
new file mode 100644
index 0000000000..b213d5e899
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportProcessor.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.namespace.impl;
+
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+
+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;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.contribution.namespace.NamespaceImport;
+import org.apache.tuscany.sca.contribution.namespace.NamespaceImportExportFactory;
+import org.apache.tuscany.sca.contribution.processor.BaseStAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.processor.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.processor.ContributionWriteException;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXAttributeProcessor;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.apache.tuscany.sca.monitor.Problem.Severity;
+
+/**
+ * Artifact processor for Namespace import
+ *
+ * @version $Rev$ $Date$
+ */
+public class NamespaceImportProcessor extends BaseStAXArtifactProcessor implements StAXArtifactProcessor<NamespaceImport> {
+ private static final String SCA11_NS = "http://docs.oasis-open.org/ns/opencsa/sca/200903";
+
+ private static final QName IMPORT = new QName(SCA11_NS, "import");
+
+ private static final String NAMESPACE = "namespace";
+ private static final String LOCATION = "location";
+
+ private final NamespaceImportExportFactory factory;
+ private final AssemblyFactory extensionFactory;
+ private final StAXArtifactProcessor<Object> extensionProcessor;
+ private final StAXAttributeProcessor<Object> attributeProcessor;
+ private final Monitor monitor;
+
+ public NamespaceImportProcessor(FactoryExtensionPoint modelFactories,
+ StAXArtifactProcessor<Object> extensionProcessor,
+ StAXAttributeProcessor<Object> attributeProcessor,
+ Monitor monitor) {
+ this.factory = modelFactories.getFactory(NamespaceImportExportFactory.class);
+ this.monitor = monitor;
+ this.extensionFactory = modelFactories.getFactory(AssemblyFactory.class);
+ this.extensionProcessor = extensionProcessor;
+ this.attributeProcessor = attributeProcessor;
+ }
+
+ /**
+ * Report a warning.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(String message, Object model, Object... messageParameters) {
+ if (monitor != null) {
+ Problem problem = monitor.createProblem(this.getClass().getName(), "contribution-namespace-validation-messages", Severity.ERROR, model, message, (Object[])messageParameters);
+ monitor.problem(problem);
+ }
+ }
+
+ public QName getArtifactType() {
+ return IMPORT;
+ }
+
+ public Class<NamespaceImport> getModelType() {
+ return NamespaceImport.class;
+ }
+
+ /**
+ * Process <import namespace="" location=""/>
+ */
+ public NamespaceImport read(XMLStreamReader reader) throws ContributionReadException {
+ NamespaceImport namespaceImport = this.factory.createNamespaceImport();
+ QName element;
+
+ try {
+ while (reader.hasNext()) {
+ int event = reader.getEventType();
+ switch (event) {
+ case START_ELEMENT:
+ element = reader.getName();
+
+ // Read <import>
+ if (IMPORT.equals(element)) {
+ String ns = reader.getAttributeValue(null, NAMESPACE);
+ if (ns == null) {
+ error("AttributeNameSpaceMissing", reader);
+ //throw new ContributionReadException("Attribute 'namespace' is missing");
+ } else {
+ namespaceImport.setNamespace(ns);
+ }
+
+ String location = reader.getAttributeValue(null, LOCATION);
+ if (location != null) {
+ namespaceImport.setLocation(location);
+ }
+ readExtendedAttributes(reader, namespaceImport, attributeProcessor, extensionFactory);
+ } else {
+ readExtendedElement(reader, namespaceImport, extensionProcessor);
+ }
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ if (IMPORT.equals(reader.getName())) {
+ return namespaceImport;
+ }
+ break;
+ }
+
+ // Read the next element
+ if (reader.hasNext()) {
+ reader.next();
+ }
+ }
+ }
+ catch (XMLStreamException e) {
+ ContributionReadException ex = new ContributionReadException(e);
+ error("XMLStreamException", reader, ex);
+ }
+
+ return namespaceImport;
+ }
+
+ public void write(NamespaceImport namespaceImport, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException {
+
+ // Write <import>
+ writer.writeStartElement(IMPORT.getNamespaceURI(), IMPORT.getLocalPart());
+
+ if (namespaceImport.getNamespace() != null) {
+ writer.writeAttribute(NAMESPACE, namespaceImport.getNamespace());
+ }
+ if (namespaceImport.getLocation() != null) {
+ writer.writeAttribute(LOCATION, namespaceImport.getLocation());
+ }
+
+ writeExtendedAttributes(writer, namespaceImport, attributeProcessor);
+ writeExtendedElements(writer, namespaceImport, extensionProcessor);
+ writer.writeEndElement();
+ }
+
+
+ public void resolve(NamespaceImport model, ModelResolver resolver) throws ContributionResolveException {
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java
new file mode 100644
index 0000000000..5be0b188f4
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.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.processor;
+
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * Base interface for artifact processors.
+ *
+ * @version $Rev$ $Date$
+ */
+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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java
new file mode 100644
index 0000000000..e9da0b5780
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java
@@ -0,0 +1,619 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Extensible;
+import org.apache.tuscany.sca.assembly.Extension;
+
+
+/**
+ * A base class with utility methods for the other artifact processors in this module.
+ *
+ * @version $Rev$ $Date$
+ */
+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);
+ writer.writeStartElement(uri, name);
+ if (prefix != null){
+ writer.writeNamespace(prefix,uri);
+ }
+ writeAttributePrefixes(writer, attrs);
+ 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);
+ }
+ }
+
+ /**
+ *
+ * @param reader
+ * @param elementName
+ * @param extensible
+ * @param extensionAttributeProcessor
+ * @param extensionAttributeProcessor
+ * @param extensionFactory
+ * @throws ContributionReadException
+ * @throws XMLStreamException
+ */
+ protected void readExtendedAttributes(XMLStreamReader reader,
+ Extensible extensible,
+ StAXAttributeProcessor extensionAttributeProcessor,
+ AssemblyFactory extensionFactory) throws ContributionReadException,
+ XMLStreamException {
+ QName elementName = reader.getName();
+ for (int a = 0; a < reader.getAttributeCount(); a++) {
+ QName attributeName = reader.getAttributeName(a);
+ if (attributeName.getNamespaceURI() != null && attributeName.getNamespaceURI().length() > 0) {
+ if (!elementName.getNamespaceURI().equals(attributeName.getNamespaceURI())) {
+ Object attributeValue = extensionAttributeProcessor.read(attributeName, reader);
+ Extension attributeExtension;
+ if (attributeValue instanceof Extension) {
+ attributeExtension = (Extension)attributeValue;
+ } else {
+ attributeExtension = extensionFactory.createExtension();
+ attributeExtension.setQName(attributeName);
+ attributeExtension.setValue(attributeValue);
+ attributeExtension.setAttribute(true);
+ }
+ extensible.getAttributeExtensions().add(attributeExtension);
+ }
+ }
+ }
+ }
+
+ /**
+ *
+ * @param attributeModel
+ * @param writer
+ * @param extensibleElement
+ * @param extensionAttributeProcessor
+ * @throws ContributionWriteException
+ * @throws XMLStreamException
+ */
+ protected void writeExtendedAttributes(XMLStreamWriter writer,
+ Extensible extensibleElement,
+ StAXAttributeProcessor extensionAttributeProcessor)
+ throws ContributionWriteException, XMLStreamException {
+ for (Extension extension : extensibleElement.getAttributeExtensions()) {
+ if (extension.isAttribute()) {
+ extensionAttributeProcessor.write(extension, writer);
+ }
+ }
+ }
+
+ protected void readExtendedElement(XMLStreamReader reader,
+ Extensible extensible,
+ StAXArtifactProcessor extensionProcessor) throws ContributionReadException,
+ XMLStreamException {
+ Object ext = extensionProcessor.read(reader);
+ if (extensible != null) {
+ extensible.getExtensions().add(ext);
+ }
+ }
+
+ protected void writeExtendedElements(XMLStreamWriter writer,
+ Extensible extensible,
+ StAXArtifactProcessor extensionProcessor) throws ContributionWriteException,
+ XMLStreamException {
+ for (Object ext : extensible.getExtensions()) {
+ extensionProcessor.write(ext, writer);
+ }
+ }
+
+ /**
+ * Represents an XML attribute that needs to be written to a document.
+ */
+ public static class XAttr {
+
+ private static final String SCA11_NS = "http://docs.oasis-open.org/ns/opencsa/sca/200903";
+
+ private String uri = SCA11_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, Integer value) {
+ this.uri = uri;
+ this.name = name;
+ this.value = value;
+ }
+
+ public XAttr(String name, Integer value) {
+ this(null, name, value);
+ }
+
+ public XAttr(String uri, String name, Double value) {
+ this.uri = uri;
+ this.name = name;
+ this.value = value;
+ }
+
+ public XAttr(String name, Double 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) {
+
+ // Use the prefix already bound to the given URI
+ if (prefix.length() > 0) {
+ return prefix + ":" + qname.getLocalPart();
+ } else {
+
+ // Empty prefix, just return the local part of the given qname
+ return 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);
+ writer.writeNamespace(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(SCA11_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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionException.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionException.java
new file mode 100644
index 0000000000..3b99eba586
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/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.processor;
+
+/**
+ * Base class for exceptions raised by contribution services.
+ *
+ * @version $Rev$ $Date$
+ */
+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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionReadException.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionReadException.java
new file mode 100644
index 0000000000..6fd7d0c91e
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionReadException.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+
+/**
+ * Denotes an exception while reading artifacts inside an SCA contribution.
+ *
+ * @version $Rev$ $Date$
+ */
+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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionResolveException.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionResolveException.java
new file mode 100644
index 0000000000..fe1a09d398
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionResolveException.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.processor;
+
+
+/**
+ * Denotes a problem while resolving models inside an SCA contribution.
+ *
+ * @version $Rev$ $Date$
+ */
+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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionRuntimeException.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionRuntimeException.java
new file mode 100644
index 0000000000..0039dd9f8b
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/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.processor;
+
+/**
+ * Base class for runtime exceptions raised by contribution services.
+ *
+ * @version $Rev$ $Date$
+ */
+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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionWriteException.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionWriteException.java
new file mode 100644
index 0000000000..286c9dc791
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionWriteException.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+
+
+/**
+ * Denotes an exception while writing artifacts inside an SCA contribution.
+ *
+ * @version $Rev$ $Date$
+ */
+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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..c871e4c868
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/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$ $Date$
+ */
+abstract class DefaultArtifactProcessorExtensionPoint<P extends ArtifactProcessor<?>> {
+ 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 <T> P getProcessor(Class<T> 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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..0d2c7714ee
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java
@@ -0,0 +1,420 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.Collection;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+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.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.extensibility.ServiceDeclaration;
+import org.apache.tuscany.sca.extensibility.ServiceDiscovery;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.MonitorFactory;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.apache.tuscany.sca.monitor.Problem.Severity;
+
+/**
+ * The default implementation of an extension point for StAX artifact processors.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultStAXArtifactProcessorExtensionPoint extends
+ DefaultArtifactProcessorExtensionPoint<StAXArtifactProcessor<?>> implements StAXArtifactProcessorExtensionPoint {
+
+ private ExtensionPointRegistry extensionPoints;
+ private FactoryExtensionPoint modelFactories;
+ private MonitorFactory monitorFactory;
+ private boolean loaded;
+ private StAXArtifactProcessor<Object> extensibleStAXProcessor;
+ private StAXAttributeProcessor<Object> extensibleStAXAttributeProcessor;
+ private Monitor monitor = null;
+
+ /**
+ * Constructs a new extension point.
+ */
+ public DefaultStAXArtifactProcessorExtensionPoint(ExtensionPointRegistry extensionPoints) {
+ this.extensionPoints = extensionPoints;
+ this.modelFactories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class);
+ XMLInputFactory inputFactory = modelFactories.getFactory(XMLInputFactory.class);
+ XMLOutputFactory outputFactory = modelFactories.getFactory(XMLOutputFactory.class);
+ UtilityExtensionPoint utilities = this.extensionPoints.getExtensionPoint(UtilityExtensionPoint.class);
+ MonitorFactory monitorFactory = utilities.getUtility(MonitorFactory.class);
+ if (monitorFactory != null)
+ this.monitor = monitorFactory.createMonitor();
+ this.extensibleStAXProcessor =
+ new ExtensibleStAXArtifactProcessor(this, inputFactory, outputFactory, this.monitor);
+
+ StAXAttributeProcessorExtensionPoint attributeExtensionPoint =
+ extensionPoints.getExtensionPoint(StAXAttributeProcessorExtensionPoint.class);
+ this.extensibleStAXAttributeProcessor =
+ new ExtensibleStAXAttributeProcessor(attributeExtensionPoint, inputFactory, outputFactory, this.monitor);
+ }
+
+ /**
+ * Report a exception.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(String message, Object model, Exception ex) {
+ if (monitor != null) {
+ Problem problem =
+ monitor.createProblem(this.getClass().getName(),
+ "contribution-validation-messages",
+ Severity.ERROR,
+ model,
+ message,
+ ex);
+ monitor.problem(problem);
+ }
+ }
+
+ public void addArtifactProcessor(StAXArtifactProcessor<?> artifactProcessor) {
+ if (artifactProcessor.getArtifactType() != null) {
+ processorsByArtifactType.put((Object)artifactProcessor.getArtifactType(), artifactProcessor);
+ }
+ if (artifactProcessor.getModelType() != null) {
+ processorsByModelType.put(artifactProcessor.getModelType(), artifactProcessor);
+ }
+ }
+
+ public void removeArtifactProcessor(StAXArtifactProcessor<?> artifactProcessor) {
+ if (artifactProcessor.getArtifactType() != null) {
+ processorsByArtifactType.remove((Object)artifactProcessor.getArtifactType());
+ }
+ if (artifactProcessor.getModelType() != null) {
+ processorsByModelType.remove(artifactProcessor.getModelType());
+ }
+ }
+
+ @Override
+ public <T> StAXArtifactProcessor<T> getProcessor(Class<T> modelType) {
+ loadArtifactProcessors();
+ return (StAXArtifactProcessor<T>)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 synchronized void loadArtifactProcessors() {
+ if (loaded)
+ return;
+
+ // Get the processor service declarations
+ Collection<ServiceDeclaration> processorDeclarations;
+ try {
+ processorDeclarations =
+ ServiceDiscovery.getInstance().getServiceDeclarations(StAXArtifactProcessor.class.getName());
+ } catch (IOException e) {
+ IllegalStateException ie = new IllegalStateException(e);
+ error("IllegalStateException", extensibleStAXProcessor, ie);
+ throw ie;
+ }
+
+ 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(artifactType, modelTypeName, factoryName, processorDeclaration,
+ extensionPoints, modelFactories, extensibleStAXProcessor,
+ extensibleStAXAttributeProcessor, monitor);
+ 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 ExtensionPointRegistry extensionPoints;
+ private QName artifactType;
+ private String modelTypeName;
+ private String factoryName;
+ private ServiceDeclaration processorDeclaration;
+ private StAXArtifactProcessor<?> processor;
+ private Class<?> modelType;
+ private StAXArtifactProcessor<Object> extensionProcessor;
+ private StAXAttributeProcessor<Object> extensionAttributeProcessor;
+ private Monitor monitor;
+
+ LazyStAXArtifactProcessor(QName artifactType,
+ String modelTypeName,
+ String factoryName,
+ ServiceDeclaration processorDeclaration,
+ ExtensionPointRegistry extensionPoints,
+ FactoryExtensionPoint modelFactories,
+ StAXArtifactProcessor<Object> extensionProcessor,
+ StAXAttributeProcessor<Object> extensionAttributeProcessor,
+ Monitor monitor) {
+
+ this.extensionPoints = extensionPoints;
+ this.artifactType = artifactType;
+ this.modelTypeName = modelTypeName;
+ this.factoryName = factoryName;
+ this.processorDeclaration = processorDeclaration;
+ this.extensionProcessor = extensionProcessor;
+ this.extensionAttributeProcessor = extensionAttributeProcessor;
+ this.monitor = monitor;
+ }
+
+ public QName getArtifactType() {
+ return artifactType;
+ }
+
+ private void error(String message, Object model, Exception ex) {
+ if (monitor != null) {
+ Problem problem =
+ monitor.createProblem(this.getClass().getName(),
+ "contribution-validation-messages",
+ Severity.ERROR,
+ model,
+ message,
+ ex);
+ monitor.problem(problem);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private StAXArtifactProcessor getProcessor() {
+ if (processor == null) {
+
+ if (processorDeclaration.getClassName()
+ .equals("org.apache.tuscany.sca.assembly.xml.DefaultBeanModelProcessor")) {
+
+ // Specific initialization for the DefaultBeanModelProcessor
+ FactoryExtensionPoint modelFactories =
+ extensionPoints.getExtensionPoint(FactoryExtensionPoint.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(FactoryExtensionPoint.class,
+ QName.class,
+ Class.class,
+ Object.class,
+ Monitor.class);
+ processor =
+ constructor
+ .newInstance(modelFactories, artifactType, getModelType(), modelFactory, monitor);
+ } catch (Exception e) {
+ IllegalStateException ie = new IllegalStateException(e);
+ error("IllegalStateException", processor, ie);
+ throw ie;
+ }
+ } else {
+ FactoryExtensionPoint modelFactories =
+ extensionPoints.getExtensionPoint(FactoryExtensionPoint.class);
+
+ // Load and instantiate the processor class
+ try {
+ Class<StAXArtifactProcessor> processorClass =
+ (Class<StAXArtifactProcessor>)processorDeclaration.loadClass();
+ try {
+ Constructor<StAXArtifactProcessor> constructor =
+ processorClass.getConstructor(FactoryExtensionPoint.class, Monitor.class);
+ processor = constructor.newInstance(modelFactories, monitor);
+ } catch (NoSuchMethodException e) {
+ try {
+ Constructor<StAXArtifactProcessor> constructor =
+ processorClass.getConstructor(ExtensionPointRegistry.class, Monitor.class);
+ processor = constructor.newInstance(extensionPoints, monitor);
+ } catch (NoSuchMethodException e1) {
+ try {
+ Constructor<StAXArtifactProcessor> constructor =
+ processorClass.getConstructor(FactoryExtensionPoint.class,
+ StAXArtifactProcessor.class,
+ Monitor.class);
+ processor = constructor.newInstance(modelFactories, extensionProcessor, monitor);
+ } catch (NoSuchMethodException e2) {
+ try {
+ Constructor<StAXArtifactProcessor> constructor =
+ processorClass.getConstructor(FactoryExtensionPoint.class,
+ StAXArtifactProcessor.class,
+ StAXAttributeProcessor.class,
+ Monitor.class);
+ processor =
+ constructor.newInstance(modelFactories,
+ extensionProcessor,
+ extensionAttributeProcessor,
+ monitor);
+ } catch (NoSuchMethodException e2a) {
+ try {
+ Constructor<StAXArtifactProcessor> constructor =
+ processorClass.getConstructor(ExtensionPointRegistry.class,
+ StAXArtifactProcessor.class,
+ Monitor.class);
+ processor =
+ constructor.newInstance(extensionPoints, extensionProcessor, monitor);
+ } catch (NoSuchMethodException e3) {
+ try {
+ Constructor<StAXArtifactProcessor> constructor =
+ processorClass.getConstructor(ExtensionPointRegistry.class,
+ StAXArtifactProcessor.class,
+ StAXAttributeProcessor.class,
+ Monitor.class);
+ processor =
+ constructor.newInstance(extensionPoints,
+ extensionProcessor,
+ extensionAttributeProcessor,
+ monitor);
+ } catch (NoSuchMethodException e3a) {
+
+ try {
+ Constructor<StAXArtifactProcessor> constructor =
+ processorClass.getConstructor(FactoryExtensionPoint.class);
+ processor = constructor.newInstance(modelFactories);
+ } catch (NoSuchMethodException e4) {
+ try {
+ Constructor<StAXArtifactProcessor> constructor =
+ processorClass.getConstructor(ExtensionPointRegistry.class);
+ processor = constructor.newInstance(extensionPoints);
+ } catch (NoSuchMethodException e4a) {
+ try {
+ Constructor<StAXArtifactProcessor> constructor =
+ processorClass
+ .getConstructor(FactoryExtensionPoint.class,
+ StAXArtifactProcessor.class);
+ processor =
+ constructor.newInstance(modelFactories,
+ extensionProcessor);
+ } catch (NoSuchMethodException e5) {
+ Constructor<StAXArtifactProcessor> constructor =
+ processorClass
+ .getConstructor(ExtensionPointRegistry.class,
+ StAXArtifactProcessor.class);
+ processor =
+ constructor.newInstance(extensionPoints,
+ extensionProcessor);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ IllegalStateException ie = new IllegalStateException(e);
+ error("IllegalStateException", processor, ie);
+ throw ie;
+ }
+ }
+ }
+ 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 (modelTypeName != null && modelType == null) {
+ try {
+ modelType = processorDeclaration.loadClass(modelTypeName);
+ } catch (Exception e) {
+ IllegalStateException ie = new IllegalStateException(e);
+ error("IllegalStateException", processorDeclaration, ie);
+ throw ie;
+ }
+ }
+ return modelType;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void resolve(Object model, ModelResolver resolver) throws ContributionResolveException {
+ getProcessor().resolve(model, resolver);
+ }
+
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXAttributeProcessorExtensionPoint.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXAttributeProcessorExtensionPoint.java
new file mode 100644
index 0000000000..314f8ebf07
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXAttributeProcessorExtensionPoint.java
@@ -0,0 +1,346 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.Collection;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+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.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.extensibility.ServiceDeclaration;
+import org.apache.tuscany.sca.extensibility.ServiceDiscovery;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.MonitorFactory;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.apache.tuscany.sca.monitor.Problem.Severity;
+
+/**
+ * The default implementation of an extension point for StAX artifact processors.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultStAXAttributeProcessorExtensionPoint extends
+ DefaultArtifactProcessorExtensionPoint<StAXAttributeProcessor<?>> implements StAXAttributeProcessorExtensionPoint {
+
+ private ExtensionPointRegistry extensionPoints;
+ private FactoryExtensionPoint modelFactories;
+ private StAXAttributeProcessor<Object> extensibleStAXAttributeProcessor;
+ private boolean loaded;
+ private Monitor monitor = null;
+
+ /**
+ * Constructs a new extension point.
+ */
+ public DefaultStAXAttributeProcessorExtensionPoint(ExtensionPointRegistry extensionPoints) {
+ this.extensionPoints = extensionPoints;
+ this.modelFactories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class);
+ XMLInputFactory inputFactory = modelFactories.getFactory(XMLInputFactory.class);
+ XMLOutputFactory outputFactory = modelFactories.getFactory(XMLOutputFactory.class);
+ UtilityExtensionPoint utilities = this.extensionPoints.getExtensionPoint(UtilityExtensionPoint.class);
+ MonitorFactory monitorFactory = utilities.getUtility(MonitorFactory.class);
+ if (monitorFactory != null) {
+ this.monitor = monitorFactory.createMonitor();
+ }
+ this.extensibleStAXAttributeProcessor =
+ new ExtensibleStAXAttributeProcessor(this, inputFactory, outputFactory, this.monitor);
+ }
+
+ /**
+ * Report a exception.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(String message, Object model, Exception ex) {
+ if (monitor != null) {
+ Problem problem =
+ monitor.createProblem(this.getClass().getName(),
+ "contribution-validation-messages",
+ Severity.ERROR,
+ model,
+ message,
+ ex);
+ monitor.problem(problem);
+ }
+ }
+
+ public void addArtifactProcessor(StAXAttributeProcessor<?> artifactProcessor) {
+ if (artifactProcessor.getArtifactType() != null) {
+ processorsByArtifactType.put((Object)artifactProcessor.getArtifactType(), artifactProcessor);
+ }
+ if (artifactProcessor.getModelType() != null) {
+ processorsByModelType.put(artifactProcessor.getModelType(), artifactProcessor);
+ }
+ }
+
+ public void removeArtifactProcessor(StAXAttributeProcessor<?> artifactProcessor) {
+ if (artifactProcessor.getArtifactType() != null) {
+ processorsByArtifactType.remove((Object)artifactProcessor.getArtifactType());
+ }
+ if (artifactProcessor.getModelType() != null) {
+ processorsByModelType.remove(artifactProcessor.getModelType());
+ }
+ }
+
+ @Override
+ public <T> StAXAttributeProcessor<T> getProcessor(Class<T> modelType) {
+ loadArtifactProcessors();
+ return (StAXAttributeProcessor<T>)super.getProcessor(modelType);
+ }
+
+ @Override
+ public StAXAttributeProcessor<?> 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 synchronized void loadArtifactProcessors() {
+ if (loaded)
+ return;
+
+ // Get the processor service declarations
+ Collection<ServiceDeclaration> processorDeclarations;
+ try {
+ processorDeclarations =
+ ServiceDiscovery.getInstance().getServiceDeclarations(StAXAttributeProcessor.class.getName());
+ } catch (IOException e) {
+ IllegalStateException ie = new IllegalStateException(e);
+ error("IllegalStateException", extensibleStAXAttributeProcessor, ie);
+ throw ie;
+ }
+
+ 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
+ StAXAttributeProcessor<?> processor =
+ new LazyStAXAttributeProcessor(artifactType, modelTypeName, factoryName, processorDeclaration,
+ extensionPoints, modelFactories, extensibleStAXAttributeProcessor,
+ monitor);
+ addArtifactProcessor(processor);
+ }
+
+ loaded = true;
+ }
+
+ /**
+ * A wrapper around an Artifact processor class allowing lazy loading and
+ * initialization of artifact processors.
+ */
+ private static class LazyStAXAttributeProcessor implements StAXAttributeProcessor {
+
+ private ExtensionPointRegistry extensionPoints;
+ private QName artifactType;
+ private String modelTypeName;
+ private String factoryName;
+ private ServiceDeclaration processorDeclaration;
+ private StAXAttributeProcessor<?> processor;
+ private Class<?> modelType;
+ private StAXAttributeProcessor<Object> extensionProcessor;
+ private Monitor monitor;
+
+ LazyStAXAttributeProcessor(QName artifactType,
+ String modelTypeName,
+ String factoryName,
+ ServiceDeclaration processorDeclaration,
+ ExtensionPointRegistry extensionPoints,
+ FactoryExtensionPoint modelFactories,
+ StAXAttributeProcessor<Object> extensionProcessor,
+ Monitor monitor) {
+
+ this.extensionPoints = extensionPoints;
+ this.artifactType = artifactType;
+ this.modelTypeName = modelTypeName;
+ this.factoryName = factoryName;
+ this.processorDeclaration = processorDeclaration;
+ this.extensionProcessor = extensionProcessor;
+ this.monitor = monitor;
+ }
+
+ public QName getArtifactType() {
+ return artifactType;
+ }
+
+ private void error(String message, Object model, Exception ex) {
+ if (monitor != null) {
+ Problem problem =
+ monitor.createProblem(this.getClass().getName(),
+ "contribution-validation-messages",
+ Severity.ERROR,
+ model,
+ message,
+ ex);
+ monitor.problem(problem);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private StAXAttributeProcessor getProcessor() {
+ if (processor == null) {
+ FactoryExtensionPoint modelFactories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class);
+
+ // Load and instantiate the processor class
+ try {
+ Class<StAXAttributeProcessor> processorClass =
+ (Class<StAXAttributeProcessor>)processorDeclaration.loadClass();
+ try {
+ Constructor<StAXAttributeProcessor> constructor =
+ processorClass.getConstructor(FactoryExtensionPoint.class, Monitor.class);
+ processor = constructor.newInstance(modelFactories, monitor);
+ } catch (NoSuchMethodException e) {
+ try {
+ Constructor<StAXAttributeProcessor> constructor =
+ processorClass.getConstructor(ExtensionPointRegistry.class, Monitor.class);
+ processor = constructor.newInstance(extensionPoints, monitor);
+ } catch (NoSuchMethodException e1) {
+ try {
+ Constructor<StAXAttributeProcessor> constructor =
+ processorClass.getConstructor(FactoryExtensionPoint.class,
+ StAXArtifactProcessor.class,
+ Monitor.class);
+ processor = constructor.newInstance(modelFactories, extensionProcessor, monitor);
+ } catch (NoSuchMethodException e2) {
+ try {
+ Constructor<StAXAttributeProcessor> constructor =
+ processorClass.getConstructor(ExtensionPointRegistry.class,
+ StAXArtifactProcessor.class,
+ Monitor.class);
+ processor = constructor.newInstance(extensionPoints, extensionProcessor, monitor);
+ } catch (NoSuchMethodException e3) {
+ try {
+ Constructor<StAXAttributeProcessor> constructor =
+ processorClass.getConstructor(FactoryExtensionPoint.class);
+ processor = constructor.newInstance(modelFactories);
+ } catch (NoSuchMethodException e4) {
+ try {
+ Constructor<StAXAttributeProcessor> constructor =
+ processorClass.getConstructor(ExtensionPointRegistry.class);
+ processor = constructor.newInstance(extensionPoints);
+ } catch (NoSuchMethodException e4a) {
+ try {
+ Constructor<StAXAttributeProcessor> constructor =
+ processorClass.getConstructor(FactoryExtensionPoint.class,
+ StAXArtifactProcessor.class);
+ processor = constructor.newInstance(modelFactories, extensionProcessor);
+ } catch (NoSuchMethodException e5) {
+ Constructor<StAXAttributeProcessor> constructor =
+ processorClass.getConstructor(ExtensionPointRegistry.class,
+ StAXArtifactProcessor.class);
+ processor =
+ constructor.newInstance(extensionPoints, extensionProcessor);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ IllegalStateException ie = new IllegalStateException(e);
+ error("IllegalStateException", processor, ie);
+ throw ie;
+ }
+
+ }
+ return processor;
+ }
+
+ public Object read(QName attributeName, XMLStreamReader inputSource) throws ContributionReadException,
+ XMLStreamException {
+ return getProcessor().read(attributeName, inputSource);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void write(Object model, XMLStreamWriter outputSource) throws ContributionWriteException,
+ XMLStreamException {
+ getProcessor().write(model, outputSource);
+ }
+
+ public Class<?> getModelType() {
+ if (modelTypeName != null && modelType == null) {
+ try {
+ modelType = processorDeclaration.loadClass(modelTypeName);
+ } catch (Exception e) {
+ IllegalStateException ie = new IllegalStateException(e);
+ error("IllegalStateException", processorDeclaration, ie);
+ throw ie;
+ }
+ }
+ return modelType;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void resolve(Object model, ModelResolver resolver) throws ContributionResolveException {
+ getProcessor().resolve(model, resolver);
+ }
+
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..3c7c2f1430
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java
@@ -0,0 +1,372 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.extensibility.ServiceDeclaration;
+import org.apache.tuscany.sca.extensibility.ServiceDiscovery;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.MonitorFactory;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.apache.tuscany.sca.monitor.Problem.Severity;
+
+/**
+ * The default implementation of a URL artifact processor extension point.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultURLArtifactProcessorExtensionPoint extends
+ DefaultArtifactProcessorExtensionPoint<URLArtifactProcessor<?>> implements URLArtifactProcessorExtensionPoint {
+
+ private ExtensionPointRegistry extensionPoints;
+ private StAXArtifactProcessor<?> staxProcessor;
+ private boolean loaded;
+ private Monitor monitor = null;
+
+ /**
+ * Constructs a new extension point.
+ */
+ public DefaultURLArtifactProcessorExtensionPoint(ExtensionPointRegistry extensionPoints) {
+ this.extensionPoints = extensionPoints;
+ FactoryExtensionPoint modelFactories = this.extensionPoints.getExtensionPoint(FactoryExtensionPoint.class);
+ XMLInputFactory inputFactory = modelFactories.getFactory(XMLInputFactory.class);
+ XMLOutputFactory outputFactory = modelFactories.getFactory(XMLOutputFactory.class);
+ UtilityExtensionPoint utilities = this.extensionPoints.getExtensionPoint(UtilityExtensionPoint.class);
+ MonitorFactory monitorFactory = utilities.getUtility(MonitorFactory.class);
+ if (monitorFactory != null)
+ this.monitor = monitorFactory.createMonitor();
+ StAXArtifactProcessorExtensionPoint staxProcessors =
+ extensionPoints.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class);
+ staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, inputFactory, outputFactory, this.monitor);
+ }
+
+ /**
+ * Report a exception.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(String message, Object model, Exception ex) {
+ if (monitor != null) {
+ Problem problem =
+ monitor.createProblem(this.getClass().getName(),
+ "contribution-validation-messages",
+ Severity.ERROR,
+ model,
+ message,
+ ex);
+ monitor.problem(problem);
+ }
+ }
+
+ public void addArtifactProcessor(URLArtifactProcessor<?> artifactProcessor) {
+ if (artifactProcessor.getArtifactType() != null) {
+ Pattern pattern = Pattern.compile(wildcard2regex(artifactProcessor.getArtifactType()));
+ processorsByArtifactType.put(pattern, artifactProcessor);
+ }
+ if (artifactProcessor.getModelType() != null) {
+ processorsByModelType.put(artifactProcessor.getModelType(), artifactProcessor);
+ }
+ }
+
+ public void removeArtifactProcessor(URLArtifactProcessor<?> artifactProcessor) {
+ if (artifactProcessor.getArtifactType() != null) {
+ String regex = wildcard2regex(artifactProcessor.getArtifactType());
+ for (Object key : processorsByArtifactType.keySet()) {
+ if ((key instanceof Pattern) && ((Pattern)key).pattern().equals(regex)) {
+ processorsByArtifactType.remove(key);
+ }
+ }
+ processorsByArtifactType.remove((Object)artifactProcessor.getArtifactType());
+ }
+ if (artifactProcessor.getModelType() != null) {
+ processorsByModelType.remove(artifactProcessor.getModelType());
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> URLArtifactProcessor<T> getProcessor(Class<T> modelType) {
+ loadProcessors();
+ return (URLArtifactProcessor<T>)super.getProcessor(modelType);
+ }
+
+ public Collection<URLArtifactProcessor<?>> getProcessors(Object artifactType) {
+ loadProcessors();
+ String uri = (String)artifactType;
+ if (uri.endsWith("/")) {
+ // Ignore directories
+ return Collections.emptyList();
+ }
+ if (!uri.startsWith("/")) {
+ uri = "/" + uri;
+ }
+ List<URLArtifactProcessor<?>> processors = new ArrayList<URLArtifactProcessor<?>>();
+ for (Map.Entry<Object, URLArtifactProcessor<?>> e : processorsByArtifactType.entrySet()) {
+ Pattern pattern = (Pattern)e.getKey();
+ if (pattern.matcher(uri).matches()) {
+ processors.add(e.getValue());
+ }
+ }
+ return processors;
+ }
+
+ @SuppressWarnings("unchecked")
+ public URLArtifactProcessor<?> getProcessor(Object artifactType) {
+ Collection<URLArtifactProcessor<?>> processors = getProcessors(artifactType);
+ return processors.isEmpty() ? null : processors.iterator().next();
+ }
+
+ private static String wildcard2regex(String pattern) {
+ String wildcard = pattern;
+ if (wildcard.endsWith("/")) {
+ // Directory: xyz/ --> xyz/**
+ wildcard = wildcard + "**";
+ }
+ if (wildcard.startsWith(".")) {
+ // File extension: .xyz --> **/*.xyz
+ wildcard = "**/*" + wildcard;
+ } else if (wildcard.indexOf('/') == -1) {
+ // File name: abc.txt --> **/abc.txt
+ wildcard = "**/" + wildcard;
+ } else if (!(wildcard.startsWith("/") || wildcard.startsWith("**"))) {
+ wildcard = '/' + wildcard;
+ }
+ StringBuffer regex = new StringBuffer();
+ char[] chars = wildcard.toCharArray();
+ for (int i = 0; i < chars.length; i++) {
+ switch (chars[i]) {
+ case '*':
+ if (i < chars.length - 1 && chars[i + 1] == '*') {
+ // Next char is '*'
+ if (i < chars.length - 2) {
+ if (chars[i + 2] == '/') {
+ // The wildcard is **/, it matches zero or more directories
+ regex.append("(.*/)*");
+ i += 2; // Skip */
+ } else {
+ // ** can only be followed by /
+ throw new IllegalArgumentException("** can only be used as the name for a directory");
+ }
+ } else {
+ regex.append(".*");
+ i++; // Skip next *
+ }
+ } else {
+ // Non-directory
+ regex.append("[^/]*");
+ }
+ break;
+ case '?':
+ regex.append("[^/]");
+ break;
+ case '\\':
+ case '|':
+ case '(':
+ case ')':
+ // case '[':
+ // case ']':
+ // case '{':
+ // case '}':
+ case '^':
+ case '$':
+ case '+':
+ case '.':
+ case '<':
+ case '>':
+ regex.append("\\").append(chars[i]);
+ break;
+ default:
+ regex.append(chars[i]);
+ break;
+ }
+ }
+ return regex.toString();
+ }
+
+ /**
+ * Lazily load artifact processors registered in the extension point.
+ */
+ private synchronized void loadProcessors() {
+ if (loaded)
+ return;
+
+ // Get the processor service declarations
+ Collection<ServiceDeclaration> processorDeclarations;
+ try {
+ processorDeclarations =
+ ServiceDiscovery.getInstance().getServiceDeclarations(URLArtifactProcessor.class.getName());
+ } catch (IOException e) {
+ IllegalStateException ie = new IllegalStateException(e);
+ error("IllegalStateException", staxProcessor, ie);
+ throw ie;
+ }
+
+ 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(artifactType, modelTypeName, processorDeclaration, extensionPoints,
+ staxProcessor, monitor);
+ addArtifactProcessor(processor);
+ }
+
+ loaded = true;
+ }
+
+ /**
+ * A wrapper around an Artifact processor class allowing lazy loading and
+ * initialization of artifact processors.
+ */
+ private static class LazyURLArtifactProcessor implements ExtendedURLArtifactProcessor {
+
+ private ExtensionPointRegistry extensionPoints;
+ private String artifactType;
+ private String modelTypeName;
+ private ServiceDeclaration processorDeclaration;
+ private URLArtifactProcessor<?> processor;
+ private Class<?> modelType;
+ private StAXArtifactProcessor<?> staxProcessor;
+ private Monitor monitor;
+
+ LazyURLArtifactProcessor(String artifactType,
+ String modelTypeName,
+ ServiceDeclaration processorDeclaration,
+ ExtensionPointRegistry extensionPoints,
+ StAXArtifactProcessor<?> staxProcessor,
+ Monitor monitor) {
+ this.artifactType = artifactType;
+ this.modelTypeName = modelTypeName;
+ this.processorDeclaration = processorDeclaration;
+ this.extensionPoints = extensionPoints;
+ this.staxProcessor = staxProcessor;
+ this.monitor = monitor;
+ }
+
+ public String getArtifactType() {
+ return artifactType;
+ }
+
+ private void error(String message, Object model, Exception ex) {
+ if (monitor != null) {
+ Problem problem =
+ monitor.createProblem(this.getClass().getName(),
+ "contribution-validation-messages",
+ Severity.ERROR,
+ model,
+ message,
+ ex);
+ monitor.problem(problem);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private URLArtifactProcessor getProcessor() {
+ if (processor == null) {
+ try {
+ FactoryExtensionPoint modelFactories =
+ extensionPoints.getExtensionPoint(FactoryExtensionPoint.class);
+ Class<URLArtifactProcessor> processorClass =
+ (Class<URLArtifactProcessor>)processorDeclaration.loadClass();
+ try {
+ Constructor<URLArtifactProcessor> constructor =
+ processorClass.getConstructor(FactoryExtensionPoint.class, Monitor.class);
+ processor = constructor.newInstance(modelFactories, monitor);
+ } catch (NoSuchMethodException e) {
+ try {
+ Constructor<URLArtifactProcessor> constructor =
+ processorClass.getConstructor(FactoryExtensionPoint.class,
+ StAXArtifactProcessor.class,
+ Monitor.class);
+ processor = constructor.newInstance(modelFactories, staxProcessor, monitor);
+ } catch (NoSuchMethodException e2) {
+ Constructor<URLArtifactProcessor> constructor =
+ processorClass.getConstructor(ExtensionPointRegistry.class,
+ StAXArtifactProcessor.class,
+ Monitor.class);
+ processor = constructor.newInstance(extensionPoints, staxProcessor, monitor);
+ }
+ }
+ } catch (Throwable e) {
+ IllegalStateException ie = new IllegalStateException("Exception during getProcessor() for " +
+ processorDeclaration.getClassName(), e);
+ error("IllegalStateException", processor, ie);
+ throw ie;
+ }
+ }
+ return processor;
+ }
+
+ public Object read(URL contributionURL, URI artifactURI, URL artifactURL) throws ContributionReadException {
+ return getProcessor().read(contributionURL, artifactURI, artifactURL);
+ }
+
+ public Class<?> getModelType() {
+ if (modelTypeName != null && modelType == null) {
+ try {
+ modelType = processorDeclaration.loadClass(modelTypeName);
+ } catch (ClassNotFoundException e) {
+ IllegalStateException ie = new IllegalStateException(e);
+ error("IllegalStateException", processorDeclaration, ie);
+ throw ie;
+ }
+ }
+ return modelType;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void resolve(Object model, ModelResolver resolver) throws ContributionResolveException {
+ getProcessor().resolve(model, resolver);
+ } // end method resolve
+
+ /**
+ * Preresolve phase, for ExtendedURLArtifactProcessors only
+ */
+ @SuppressWarnings("unchecked")
+ public void preResolve( Object model, ModelResolver resolver ) throws ContributionResolveException {
+ URLArtifactProcessor<?> processor = getProcessor();
+ if( processor instanceof ExtendedURLArtifactProcessor ) {
+ ((ExtendedURLArtifactProcessor)processor).preResolve(model, resolver);
+ } // end if
+ } // end method resolve
+
+ } // end class LazyURLArtifactProcessor
+} // end class DefaultURLArtifactProcessorExtensionPoint
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java
new file mode 100644
index 0000000000..8aac0ce3f6
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java
@@ -0,0 +1,423 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.net.URLConnection;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+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.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.MonitorFactory;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.apache.tuscany.sca.monitor.Problem.Severity;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.ls.DOMImplementationLS;
+import org.w3c.dom.ls.LSInput;
+import org.w3c.dom.ls.LSResourceResolver;
+import org.xml.sax.SAXException;
+
+/**
+ * Default implementation of an XMLInputFactory that creates validating
+ * XMLStreamReaders.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultValidatingXMLInputFactory extends ValidatingXMLInputFactory implements LSResourceResolver {
+
+ private XMLInputFactory inputFactory;
+ private DocumentBuilderFactory documentBuilderFactory;
+ private DOMImplementationLS ls;
+ private ValidationSchemaExtensionPoint schemas;
+ private Monitor monitor;
+ private boolean initialized;
+ private boolean hasSchemas;
+ private Schema aggregatedSchema;
+
+ public DefaultValidatingXMLInputFactory(ExtensionPointRegistry registry) {
+ FactoryExtensionPoint factoryExtensionPoint = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ this.inputFactory = factoryExtensionPoint.getFactory(XMLInputFactory.class);
+ this.documentBuilderFactory = factoryExtensionPoint.getFactory(DocumentBuilderFactory.class);
+ this.schemas = registry.getExtensionPoint(ValidationSchemaExtensionPoint.class);
+ this.monitor =
+ registry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(MonitorFactory.class).createMonitor();
+ }
+
+ /**
+ * Constructs a new XMLInputFactory.
+ *
+ * @param inputFactory
+ * @param schemas
+ */
+ public DefaultValidatingXMLInputFactory(XMLInputFactory inputFactory, ValidationSchemaExtensionPoint schemas, Monitor monitor) {
+ this.inputFactory = inputFactory;
+ this.schemas = schemas;
+ this.monitor = monitor;
+ }
+
+ /**
+ * Report a exception.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(String message, Object model, Throwable ex) {
+ if (monitor != null) {
+ Problem problem =
+ monitor.createProblem(this.getClass().getName(),
+ "contribution-validation-messages",
+ Severity.ERROR,
+ model,
+ message,
+ ex);
+ monitor.problem(problem);
+ }
+ }
+
+ private void warn(String message, Object model, Throwable ex) {
+ if (monitor != null) {
+ Problem problem =
+ monitor.createProblem(this.getClass().getName(),
+ "contribution-validation-messages",
+ Severity.WARNING,
+ model,
+ message,
+ ex);
+ monitor.problem(problem);
+ }
+ }
+
+ /**
+ * 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();
+ if (n ==0) {
+ return;
+ } else {
+ hasSchemas = true;
+ }
+ 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) {
+ error("PrivilegedActionException", url, (IOException)e.getException());
+ 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);
+
+ /*
+ // Set the feature to avoid DTD processing
+ try {
+ schemaFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
+ schemaFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+ schemaFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+ } catch (SAXException e) {
+ // Ignore
+ }
+ */
+
+ DOMImplementation impl = null;
+ try {
+ impl = documentBuilderFactory.newDocumentBuilder().getDOMImplementation();
+ } catch (ParserConfigurationException e) {
+ // Ignore
+ }
+ if (impl instanceof DOMImplementationLS) {
+ ls = (DOMImplementationLS)impl;
+ schemaFactory.setResourceResolver(this);
+ }
+ // 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) {
+ warn("PrivilegedActionException", schemaFactory, (SAXException)e.getException());
+ hasSchemas = false;
+ throw (SAXException)e.getException();
+ }
+
+ } catch (SAXException e) {
+// IllegalStateException ie = new IllegalStateException(e);
+// error("IllegalStateException", schemas, ie);
+// throw ie;
+ } catch (Throwable e) {
+ //FIXME Log this, some old JDKs don't support XMLSchema validation
+ warn(e.getMessage(), schemas, e);
+ hasSchemas = false;
+ }
+ }
+
+ @Override
+ public XMLEventReader createFilteredReader(XMLEventReader arg0, EventFilter arg1) throws XMLStreamException {
+ return inputFactory.createFilteredReader(arg0, arg1);
+ }
+
+ @Override
+ public XMLStreamReader createFilteredReader(XMLStreamReader arg0, StreamFilter arg1) throws XMLStreamException {
+ return inputFactory.createFilteredReader(arg0, arg1);
+ }
+
+ @Override
+ public XMLEventReader createXMLEventReader(InputStream arg0, String arg1) throws XMLStreamException {
+ return inputFactory.createXMLEventReader(arg0, arg1);
+ }
+
+ @Override
+ public XMLEventReader createXMLEventReader(InputStream arg0) throws XMLStreamException {
+ return inputFactory.createXMLEventReader(arg0);
+ }
+
+ @Override
+ public XMLEventReader createXMLEventReader(Reader arg0) throws XMLStreamException {
+ return inputFactory.createXMLEventReader(arg0);
+ }
+
+ @Override
+ public XMLEventReader createXMLEventReader(Source arg0) throws XMLStreamException {
+ return inputFactory.createXMLEventReader(arg0);
+ }
+
+ @Override
+ public XMLEventReader createXMLEventReader(String arg0, InputStream arg1) throws XMLStreamException {
+ return inputFactory.createXMLEventReader(arg0, arg1);
+ }
+
+ @Override
+ public XMLEventReader createXMLEventReader(String arg0, Reader arg1) throws XMLStreamException {
+ return inputFactory.createXMLEventReader(arg0, arg1);
+ }
+
+ @Override
+ public XMLEventReader createXMLEventReader(XMLStreamReader arg0) throws XMLStreamException {
+ return inputFactory.createXMLEventReader(arg0);
+ }
+
+ @Override
+ public XMLStreamReader createXMLStreamReader(InputStream arg0, String arg1) throws XMLStreamException {
+ initializeSchemas();
+ if (hasSchemas) {
+ return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0, arg1), aggregatedSchema, monitor);
+ }else {
+ return inputFactory.createXMLStreamReader(arg0, arg1);
+ }
+ }
+
+ @Override
+ public XMLStreamReader createXMLStreamReader(InputStream arg0) throws XMLStreamException {
+ initializeSchemas();
+ if (hasSchemas) {
+ return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0), aggregatedSchema, monitor);
+ } else {
+ return inputFactory.createXMLStreamReader(arg0);
+ }
+ }
+
+ @Override
+ public XMLStreamReader createXMLStreamReader(Reader arg0) throws XMLStreamException {
+ initializeSchemas();
+ if (hasSchemas) {
+ return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0), aggregatedSchema, monitor);
+ } else {
+ return inputFactory.createXMLStreamReader(arg0);
+ }
+ }
+
+ @Override
+ public XMLStreamReader createXMLStreamReader(Source arg0) throws XMLStreamException {
+ initializeSchemas();
+ if (hasSchemas) {
+ return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0), aggregatedSchema, monitor);
+ } else {
+ return inputFactory.createXMLStreamReader(arg0);
+ }
+ }
+
+ @Override
+ public XMLStreamReader createXMLStreamReader(String arg0, InputStream arg1) throws XMLStreamException {
+ initializeSchemas();
+ if (hasSchemas) {
+ return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0, arg1), aggregatedSchema, monitor);
+ } else {
+ return inputFactory.createXMLStreamReader(arg0, arg1);
+ }
+ }
+
+ @Override
+ public XMLStreamReader createXMLStreamReader(String arg0, Reader arg1) throws XMLStreamException {
+ initializeSchemas();
+ if (hasSchemas) {
+ return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0, arg1), aggregatedSchema, monitor);
+ } else {
+ return inputFactory.createXMLStreamReader(arg0, arg1);
+ }
+ }
+
+ @Override
+ public XMLEventAllocator getEventAllocator() {
+ return inputFactory.getEventAllocator();
+ }
+
+ @Override
+ public Object getProperty(String arg0) throws IllegalArgumentException {
+ return inputFactory.getProperty(arg0);
+ }
+
+ @Override
+ public XMLReporter getXMLReporter() {
+ return inputFactory.getXMLReporter();
+ }
+
+ @Override
+ public XMLResolver getXMLResolver() {
+ return inputFactory.getXMLResolver();
+ }
+
+ @Override
+ public boolean isPropertySupported(String arg0) {
+ return inputFactory.isPropertySupported(arg0);
+ }
+
+ @Override
+ public void setEventAllocator(XMLEventAllocator arg0) {
+ inputFactory.setEventAllocator(arg0);
+ }
+
+ @Override
+ public void setProperty(String arg0, Object arg1) throws IllegalArgumentException {
+ inputFactory.setProperty(arg0, arg1);
+ }
+
+ @Override
+ public void setXMLReporter(XMLReporter arg0) {
+ inputFactory.setXMLReporter(arg0);
+ }
+
+ @Override
+ public void setXMLResolver(XMLResolver arg0) {
+ inputFactory.setXMLResolver(arg0);
+ }
+
+ /**
+ * Cache for public XSDs and DTDs
+ */
+ private static Map<String, URL> cachedXSDs = new HashMap<String, URL>();
+ static {
+ cachedXSDs
+ .put("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
+ DefaultValidatingXMLInputFactory.class
+ .getResource("/org/apache/tuscany/sca/assembly/xsd/oasis-200401-wss-wssecurity-secext-1.0.xsd"));
+ cachedXSDs
+ .put("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd",
+ DefaultValidatingXMLInputFactory.class
+ .getResource("/org/apache/tuscany/sca/assembly/xsd/oasis-200401-wss-wssecurity-utility-1.0.xsd"));
+ cachedXSDs.put("http://www.w3.org/2005/08/addressing", DefaultValidatingXMLInputFactory.class
+ .getResource("/org/apache/tuscany/sca/assembly/xsd/ws-addr.xsd"));
+ cachedXSDs.put("http://www.w3.org/ns/ws-policy", DefaultValidatingXMLInputFactory.class
+ .getResource("/org/apache/tuscany/sca/assembly/xsd/ws-policy.xsd"));
+ cachedXSDs.put("http://www.w3.org/ns/wsdl-instance", DefaultValidatingXMLInputFactory.class
+ .getResource("/org/apache/tuscany/sca/assembly/xsd/wsdli.xsd"));
+ cachedXSDs.put("http://www.w3.org/XML/1998/namespace", DefaultValidatingXMLInputFactory.class
+ .getResource("/org/apache/tuscany/sca/assembly/xsd/xml.xsd"));
+ cachedXSDs.put("http://www.w3.org/2000/09/xmldsig#", DefaultValidatingXMLInputFactory.class
+ .getResource("/org/apache/tuscany/sca/assembly/xsd/xmldsig-core-schema.xsd"));
+
+ cachedXSDs.put("-//W3C//DTD XMLSCHEMA 200102//EN", DefaultValidatingXMLInputFactory.class
+ .getResource("/org/apache/tuscany/sca/assembly/xsd/XMLSchema.dtd"));
+ cachedXSDs.put("datatypes", DefaultValidatingXMLInputFactory.class
+ .getResource("/org/apache/tuscany/sca/assembly/xsd/datatypes.dtd"));
+ };
+
+ public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) {
+ String key = null;
+ if("http://www.w3.org/2001/XMLSchema".equals(type)) {
+ key = namespaceURI;
+ } else if("http://www.w3.org/TR/REC-xml".equals(type)) {
+ key = publicId;
+ }
+ URL url = cachedXSDs.get(key);
+ if (url != null) {
+ systemId = url.toString();
+ }
+
+ LSInput input = ls.createLSInput();
+ input.setBaseURI(baseURI);
+ input.setPublicId(publicId);
+ input.setSystemId(systemId);
+ return input;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidationSchemaExtensionPoint.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidationSchemaExtensionPoint.java
new file mode 100644
index 0000000000..920afbef5a
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidationSchemaExtensionPoint.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.Collection;
+import java.util.Collections;
+import java.util.List;
+
+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$ $Date$
+ */
+public class DefaultValidationSchemaExtensionPoint implements ValidationSchemaExtensionPoint {
+ private boolean enabled;
+ 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 synchronized void loadSchemas() {
+ if (loaded || (!enabled))
+ return;
+
+ // Get the schema declarations
+ Collection<ServiceDeclaration> schemaDeclarations;
+ try {
+ schemaDeclarations =
+ ServiceDiscovery.getInstance()
+ .getServiceDeclarations("org.apache.tuscany.sca.contribution.processor.ValidationSchema");
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+
+ // TODO - temp fix to ensure that the schema tuscany-sca.xsd always comes first
+ String tuscanyScaXsd = null;
+
+ // Find each schema
+ for (ServiceDeclaration schemaDeclaration : schemaDeclarations) {
+ URL url = schemaDeclaration.getResource(schemaDeclaration.getClassName());
+ if (url == null) {
+ throw new IllegalArgumentException(new FileNotFoundException(schemaDeclaration.getClassName()));
+ }
+
+ if (url.toString().contains("tuscany-sca-1.1.xsd")) {
+ tuscanyScaXsd = url.toString();
+ } else {
+ schemas.add(url.toString());
+ }
+ }
+
+ if (tuscanyScaXsd != null) {
+ schemas.add(0, tuscanyScaXsd);
+ }
+
+ loaded = true;
+ }
+
+ public List<String> getSchemas() {
+ if (enabled) {
+ loadSchemas();
+ return schemas;
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtendedArtifactProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtendedArtifactProcessor.java
new file mode 100644
index 0000000000..98d3fcca88
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtendedArtifactProcessor.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.processor;
+
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * Interface for extended Artifact Processors which require a pre-resolve phase prior to the resolve phase
+ *
+ * @version $Rev: 704156 $ $Date: 2008-10-13 17:31:59 +0100 (Mon, 13 Oct 2008) $
+ */
+public interface ExtendedArtifactProcessor<M> extends ArtifactProcessor<M> {
+
+ /**
+ * Pre-resolve references from this model to other models. Used for models where initial setup of
+ * the resolve phase is required. An example is Contribution models with imports and exports which must
+ * be set up prior to the main resolve phase
+ *
+ * @param model The model to resolve
+ * @param resolver The resolver to use to resolve referenced models
+ */
+ void preResolve(M model, ModelResolver resolver) throws ContributionResolveException;
+
+} // end interface
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtendedURLArtifactProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtendedURLArtifactProcessor.java
new file mode 100644
index 0000000000..872b9804ce
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtendedURLArtifactProcessor.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+
+/**
+ * An extended artifact processor that can read models from a URL.
+ *
+ * @version $Rev: 704156 $ $Date: 2008-10-13 17:31:59 +0100 (Mon, 13 Oct 2008) $
+ */
+public interface ExtendedURLArtifactProcessor<M> extends ExtendedArtifactProcessor<M>, URLArtifactProcessor<M> {
+
+} // end interface
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java
new file mode 100644
index 0000000000..35793899c0
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java
@@ -0,0 +1,277 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.sca.contribution.Constants;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.apache.tuscany.sca.monitor.Problem.Severity;
+
+/**
+ * Implementation of an extensible StAX artifact processor.
+ *
+ * Takes a StAXArtifactProcessorExtensionPoint and delegates to the proper
+ * StAXArtifactProcessor by element QName
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExtensibleStAXArtifactProcessor implements StAXArtifactProcessor<Object> {
+ private static final Logger logger = Logger.getLogger(ExtensibleStAXArtifactProcessor.class.getName());
+
+ private static final QName ANY_ELEMENT = new QName(Constants.XMLSCHEMA_NS, "anyElement");
+
+ private XMLInputFactory inputFactory;
+ private XMLOutputFactory outputFactory;
+ private StAXArtifactProcessorExtensionPoint processors;
+ private Monitor monitor;
+
+ /**
+ * Constructs a new ExtensibleStAXArtifactProcessor.
+ * @param processors
+ * @param inputFactory
+ * @param outputFactory
+ */
+ public ExtensibleStAXArtifactProcessor(StAXArtifactProcessorExtensionPoint processors,
+ XMLInputFactory inputFactory,
+ XMLOutputFactory outputFactory,
+ Monitor monitor) {
+ super();
+ this.processors = processors;
+ this.inputFactory = inputFactory;
+ this.outputFactory = outputFactory;
+ if (this.outputFactory != null) {
+ this.outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", Boolean.TRUE);
+ }
+ this.monitor = monitor;
+ }
+
+ /**
+ * Report a warning.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void warning(String message, Object model, Object... messageParameters) {
+ if (monitor != null) {
+ Problem problem =
+ monitor.createProblem(this.getClass().getName(),
+ "contribution-validation-messages",
+ Severity.WARNING,
+ model,
+ message,
+ (Object[])messageParameters);
+ monitor.problem(problem);
+ }
+ }
+
+ /**
+ * Report a error.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(String message, Object model, Object... messageParameters) {
+ if (monitor != null) {
+ Problem problem =
+ monitor.createProblem(this.getClass().getName(),
+ "contribution-validation-messages",
+ Severity.ERROR,
+ model,
+ message,
+ (Object[])messageParameters);
+ monitor.problem(problem);
+ }
+ }
+
+ /**
+ * Report a exception.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(String message, Object model, Exception ex) {
+ if (monitor != null) {
+ Problem problem =
+ monitor.createProblem(this.getClass().getName(),
+ "contribution-validation-messages",
+ Severity.ERROR,
+ model,
+ message,
+ ex);
+ monitor.problem(problem);
+ }
+ }
+
+ public Object read(XMLStreamReader source) throws ContributionReadException, XMLStreamException {
+
+ // Delegate to the processor associated with the element QName
+ int event = source.getEventType();
+ if (event == XMLStreamConstants.START_DOCUMENT) {
+ source.nextTag();
+ }
+ QName name = source.getName();
+ StAXArtifactProcessor<?> processor = (StAXArtifactProcessor<?>)processors.getProcessor(name);
+ if (processor == null) {
+ Location location = source.getLocation();
+ if (logger.isLoggable(Level.WARNING)) {
+ logger.warning("Element " + name + " cannot be processed. (" + location + ")");
+ }
+ warning("ElementCannotBeProcessed", processors, name, location);
+
+ StAXArtifactProcessor anyElementProcessor = processors.getProcessor(ANY_ELEMENT);
+ if (anyElementProcessor != null) {
+ return anyElementProcessor.read(source);
+ } else {
+ 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());
+ }
+ if (!XMLStreamReader.class.isInstance(model)) {
+ warning("NoStaxProcessor", processors, model.getClass());
+ }
+ StAXArtifactProcessor anyElementProcessor = processors.getProcessor(ANY_ELEMENT);
+ if (anyElementProcessor != null) {
+ anyElementProcessor.write(model, outputSource);
+ }
+ }
+ }
+ }
+
+ @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 {
+ error("UnrecognizedElementException", reader, name);
+ UnrecognizedElementException e = new UnrecognizedElementException(name);
+ throw e;
+ }
+ } catch (ContributionReadException e) {
+ Location location = reader.getLocation();
+ e.setLine(location.getLineNumber());
+ e.setColumn(location.getColumnNumber());
+ error("ContributionReadException", reader, e);
+ 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);
+ error("ContributionReadException", inputFactory, ce);
+ 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) {
+ ContributionWriteException cw = new ContributionWriteException(e);
+ error("ContributionWriteException", outputFactory, cw);
+ throw cw;
+ }
+ }
+
+ public QName getArtifactType() {
+ return null;
+ }
+
+ public Class<Object> getModelType() {
+ return null;
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXAttributeProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXAttributeProcessor.java
new file mode 100644
index 0000000000..d8b66562a2
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXAttributeProcessor.java
@@ -0,0 +1,264 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI;
+
+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.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.sca.assembly.Extension;
+import org.apache.tuscany.sca.contribution.Constants;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.apache.tuscany.sca.monitor.Problem.Severity;
+
+/**
+ * Implementation of an extensible StAX attribute processor.
+ *
+ * Takes a StAXAttributeProcessorExtensionPoint and delegates to the proper
+ * StAXAttributeProcessor by attribute QName
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExtensibleStAXAttributeProcessor implements StAXAttributeProcessor<Object> {
+
+ private static final Logger logger = Logger.getLogger(ExtensibleStAXAttributeProcessor.class.getName());
+
+ private static final QName ANY_ATTRIBUTE = new QName(Constants.XMLSCHEMA_NS, "anyAttribute");
+
+ private XMLInputFactory inputFactory;
+ private XMLOutputFactory outputFactory;
+ private StAXAttributeProcessorExtensionPoint processors;
+ private Monitor monitor;
+
+ /**
+ * Constructs a new ExtensibleStAXArtifactProcessor.
+ * @param processors
+ * @param inputFactory
+ * @param outputFactory
+ */
+ public ExtensibleStAXAttributeProcessor(StAXAttributeProcessorExtensionPoint processors,
+ XMLInputFactory inputFactory,
+ XMLOutputFactory outputFactory,
+ Monitor monitor) {
+ super();
+ this.processors = processors;
+ this.inputFactory = inputFactory;
+ this.outputFactory = outputFactory;
+ if (this.outputFactory != null) {
+ this.outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", Boolean.TRUE);
+ }
+ this.monitor = monitor;
+ }
+
+ /**
+ * Report a warning.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void warning(String message, Object model, Object... messageParameters) {
+ if (monitor != null) {
+ Problem problem =
+ monitor.createProblem(this.getClass().getName(),
+ "contribution-validation-messages",
+ Severity.WARNING,
+ model,
+ message,
+ (Object[])messageParameters);
+ monitor.problem(problem);
+ }
+ }
+
+ /**
+ * Report a error.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(String message, Object model, Object... messageParameters) {
+ if (monitor != null) {
+ Problem problem =
+ monitor.createProblem(this.getClass().getName(),
+ "contribution-validation-messages",
+ Severity.ERROR,
+ model,
+ message,
+ (Object[])messageParameters);
+ monitor.problem(problem);
+ }
+ }
+
+ /**
+ * Report a exception.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(String message, Object model, Exception ex) {
+ if (monitor != null) {
+ Problem problem =
+ monitor.createProblem(this.getClass().getName(),
+ "contribution-validation-messages",
+ Severity.ERROR,
+ model,
+ message,
+ ex);
+ monitor.problem(problem);
+ }
+ }
+
+ public Object read(QName attributeName, XMLStreamReader source) throws ContributionReadException,
+ XMLStreamException {
+ // Delegate to the processor associated with the attribute QName
+ int event = source.getEventType();
+ if (event == XMLStreamConstants.START_DOCUMENT) {
+ source.nextTag();
+ }
+
+ StAXAttributeProcessor<?> processor = null;
+
+ //lookup for registered attribute processors
+ processor = (StAXAttributeProcessor<?>)processors.getProcessor(attributeName);
+ if (processor == null) {
+ Location location = source.getLocation();
+ // Skip xsi:type, xsi:nil and xsi:schemaLocation etc
+ if (!W3C_XML_SCHEMA_INSTANCE_NS_URI.equals(attributeName.getNamespaceURI())) {
+ if (logger.isLoggable(Level.WARNING)) {
+ logger.warning("Attribute " + attributeName + " cannot be processed. (" + location + ")");
+ }
+ warning("AttributeCannotBeProcessed", processors, attributeName, location);
+ }
+ } else {
+ return processor.read(attributeName, source);
+ }
+
+ //handle extension attributes without processors
+ processor = (StAXAttributeProcessor<?>)processors.getProcessor(ANY_ATTRIBUTE);
+ if (processor == null) {
+ Location location = source.getLocation();
+ if (logger.isLoggable(Level.WARNING)) {
+ logger.warning("Could not find Default Attribute processor !");
+ }
+ warning("DefaultAttributeProcessorNotAvailable", processors, ANY_ATTRIBUTE, location);
+ }
+
+ return processor == null ? null : processor.read(attributeName, source);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void write(Object model, XMLStreamWriter outputSource) throws ContributionWriteException, XMLStreamException {
+
+ if (model == null) {
+ return;
+ }
+
+ // Delegate to the processor associated with the model type
+ StAXAttributeProcessor processor = processors.getProcessor(model.getClass());
+ if (processor == null) {
+ if (!Extension.class.isInstance(model)) {
+ if (logger.isLoggable(Level.WARNING)) {
+ logger.warning("No StAX processor is configured to handle " + model.getClass());
+ }
+ warning("NoStaxProcessor", processors, model.getClass());
+ }
+ } else {
+ processor.write(model, outputSource);
+ return;
+ }
+
+ //handle extension attributes without processors
+ processor = (StAXAttributeProcessor<?>)processors.getProcessor(ANY_ATTRIBUTE);
+ if (processor == null) {
+ if (logger.isLoggable(Level.WARNING)) {
+ logger.warning("No Default StAX processor is configured to handle " + model.getClass());
+ }
+ warning("NoDefaultStaxProcessor", processors, model.getClass());
+ } else {
+ processor.write(model, outputSource);
+ return;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public void resolve(Object model, ModelResolver resolver) throws ContributionResolveException {
+
+ // Delegate to the processor associated with the model type
+ if (model != null) {
+ StAXAttributeProcessor 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 {
+ return null;
+ }
+
+ /**
+ * 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) {
+ ContributionWriteException cw = new ContributionWriteException(e);
+ error("ContributionWriteException", outputFactory, cw);
+ throw cw;
+ }
+ }
+
+ public QName getArtifactType() {
+ return null;
+ }
+
+ public Class<Object> getModelType() {
+ return null;
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java
new file mode 100644
index 0000000000..7b4a7cff3a
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.apache.tuscany.sca.monitor.Problem.Severity;
+
+/**
+ * Implementation of an extensible URL artifact processor.
+ *
+ * Takes a URLArtifactProcessorExtensionPoint and delegates to the proper URLArtifactProcessor
+ * by either fileName or fileExtention
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExtensibleURLArtifactProcessor implements URLArtifactProcessor<Object> {
+
+ private URLArtifactProcessorExtensionPoint processors;
+ private Monitor monitor;
+
+ /**
+ * Constructs a new ExtensibleURLArtifactProcessor.
+ *
+ * @param processors
+ */
+ public ExtensibleURLArtifactProcessor(URLArtifactProcessorExtensionPoint processors, Monitor monitor) {
+ this.processors = processors;
+ this.monitor = monitor;
+ }
+
+ /**
+ * Report a error.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(String message, Object model, Object... messageParameters) {
+ if (monitor != null) {
+ Problem problem =
+ monitor.createProblem(this.getClass().getName(),
+ "contribution-validation-messages",
+ Severity.ERROR,
+ model,
+ message,
+ (Object[])messageParameters);
+ monitor.problem(problem);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object read(URL contributionURL, URI sourceURI, URL sourceURL) throws ContributionReadException {
+ URLArtifactProcessor<Object> processor = null;
+ if (sourceURI != null) {
+ //try to retrieve a processor for the specific URI
+ String uri = sourceURI.toString();
+ if (!uri.startsWith("/")) {
+ uri = "/" + uri;
+ }
+ // Register the URI as the artifact type starts with /
+ processor = (URLArtifactProcessor<Object>)processors.getProcessor(uri);
+ }
+
+ /*
+ if (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) {
+ // File extensions are registered as .<extension>
+ 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());
+ error("UnrecognizedElementException", processors, 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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java
new file mode 100644
index 0000000000..1bf9b4d494
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+
+/**
+ * An artifact processor that can read models from a StAX XMLStreamReader.
+ *
+ * @version $Rev$ $Date$
+ */
+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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..0cfcf004b2
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.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.processor;
+
+/**
+ * An extension point for StAX artifact processors.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface StAXArtifactProcessorExtensionPoint {
+ /**
+ * Add an artifact processor.
+ *
+ * @param artifactProcessor The artifact processor to add
+ */
+ void addArtifactProcessor(StAXArtifactProcessor<?> artifactProcessor);
+
+ /**
+ * Remove an artifact processor.
+ *
+ * @param artifactProcessor The artifact processor to remove
+ */
+ void removeArtifactProcessor(StAXArtifactProcessor<?> artifactProcessor);
+
+ /**
+ * Returns the processor associated with the given artifact type.
+ *
+ * @param artifactType An artifact type
+ * @return The processor associated with the given artifact type
+ */
+ <T> StAXArtifactProcessor<T> 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
+ */
+ <T> StAXArtifactProcessor<T> getProcessor(Class<T> modelType);
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessor.java
new file mode 100644
index 0000000000..b25bf0d669
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessor.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;
+
+
+
+/**
+ * An artifact processor that can read attributes from a StAX XMLStreamReader.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface StAXAttributeProcessor<M> extends ArtifactProcessor<M>{
+
+ /**
+ * Reads a model from an XMLStreamReader.
+ *
+ * @param reader The XMLStreamReader
+ * @return A model representation of the input.
+ */
+ M read(QName attributeName, 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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessorExtensionPoint.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessorExtensionPoint.java
new file mode 100644
index 0000000000..dbc0a2c7bc
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessorExtensionPoint.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.processor;
+
+/**
+ * An extension point for StAX artifact processors.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface StAXAttributeProcessorExtensionPoint {
+ /**
+ * Add an artifact processor.
+ *
+ * @param artifactProcessor The artifact processor to add
+ */
+ void addArtifactProcessor(StAXAttributeProcessor<?> artifactProcessor);
+
+ /**
+ * Remove an artifact processor.
+ *
+ * @param artifactProcessor The artifact processor to remove
+ */
+ void removeArtifactProcessor(StAXAttributeProcessor<?> artifactProcessor);
+
+ /**
+ * Returns the processor associated with the given artifact type.
+ *
+ * @param artifactType An artifact type
+ * @return The processor associated with the given artifact type
+ */
+ <T> StAXAttributeProcessor<T> 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
+ */
+ <T> StAXAttributeProcessor<T> getProcessor(Class<T> modelType);
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/TuscanyNamespaceContext.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/TuscanyNamespaceContext.java
new file mode 100644
index 0000000000..2ddba7527e
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/TuscanyNamespaceContext.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.processor;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
+
+import javax.xml.namespace.NamespaceContext;
+
+/**
+ * Tuscany specialized class to handle NamespaceContext
+ *
+ */
+public class TuscanyNamespaceContext implements NamespaceContext {
+
+ private Stack<List<String>[]> context = null;
+
+ public TuscanyNamespaceContext(Stack<List<String>[]> context) {
+ this.context = context;
+ }
+
+ public String getNamespaceURI(String prefix) {
+ if (prefix == null) {
+ throw new IllegalArgumentException();
+ }
+ return (String)getResult("getNSUri", prefix);
+ }
+
+ public String getPrefix(String namespaceURI) {
+ if (namespaceURI == null) {
+ throw new IllegalArgumentException();
+ }
+ return (String)getResult("getPrefix", namespaceURI);
+ }
+
+ @SuppressWarnings("unchecked")
+ public Iterator<String> getPrefixes(String namespaceURI) {
+ if (namespaceURI == null) {
+ throw new IllegalArgumentException();
+ }
+
+ Iterator<String> iterator = (Iterator<String>)getResult("getPrefixes", namespaceURI);
+ return iterator;
+ }
+
+ /*
+ * Generic method to Iterate through the Stack and return required result(s)
+ */
+ private Object getResult(String operation, String arg) {
+
+ List<String>[] contextList = null;
+ Iterator<String> prefItr = null;
+ Iterator<String> uriItr = null;
+
+ List<String> list = new ArrayList<String>();
+
+ String toCompare = null;
+
+ String tempPrefix = null;
+ String tempUri = null;
+
+ for (int i = context.size() - 1; i >= 0; i--) {
+ contextList = context.get(i);
+ prefItr = contextList[0].iterator();
+ uriItr = contextList[1].iterator();
+ while (uriItr.hasNext()) {
+ tempPrefix = prefItr.next();
+ tempUri = uriItr.next();
+ if (operation.equalsIgnoreCase("getNSUri")) {
+ toCompare = tempPrefix;
+ } else if (operation.equalsIgnoreCase("getPrefix")) {
+ toCompare = tempUri;
+ } else if (operation.equalsIgnoreCase("getPrefixes")) {
+ toCompare = tempUri;
+ }
+ if (toCompare != null && arg.equalsIgnoreCase(toCompare)) {
+ if (operation.equalsIgnoreCase("getNSUri")) {
+ return tempUri;
+ } else if (operation.equalsIgnoreCase("getPrefix")) {
+ return tempPrefix;
+ } else if (operation.equalsIgnoreCase("getPrefixes")) {
+ list.add(tempPrefix);
+ }
+
+ }
+ }
+ }
+
+ if (operation.equalsIgnoreCase("getPrefixes")) {
+ return Collections.unmodifiableList(list).iterator();
+ }
+
+ return null;
+ }
+} \ No newline at end of file
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/TuscanyXMLStreamReader.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/TuscanyXMLStreamReader.java
new file mode 100644
index 0000000000..3352e76a0d
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/TuscanyXMLStreamReader.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.ArrayList;
+import java.util.List;
+import java.util.Stack;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.util.StreamReaderDelegate;
+
+/*
+ * Custom implementaion of the XMLStreamReader to keep track of the namespace context for each element
+ */
+public class TuscanyXMLStreamReader extends StreamReaderDelegate implements XMLStreamReader {
+
+ Stack<List<String>[]> context = new Stack<List<String>[]>();
+
+ List<String>[] contextList;
+ List<String> prefixList;
+ List<String> uriList;
+
+ public TuscanyXMLStreamReader(XMLStreamReader reader) {
+ super(reader);
+ }
+
+ public void pushContext() throws XMLStreamException {
+ contextList = new List[2];
+ prefixList = new ArrayList<String>();
+ uriList = new ArrayList<String>();
+ int namespaceCount = this.getNamespaceCount();
+ for (int i = 0; i < namespaceCount; i++) {
+ prefixList.add(checkString(this.getNamespacePrefix(i)));
+ uriList.add(this.getNamespaceURI(i));
+ }
+ contextList[0] = prefixList;
+ contextList[1] = uriList;
+ context.push(contextList);
+ }
+
+ private String checkString(String namespacePrefix) {
+ if (namespacePrefix == null) {
+ return XMLConstants.DEFAULT_NS_PREFIX;
+ } else {
+ return namespacePrefix;
+ }
+ }
+
+ public void popContext() throws XMLStreamException {
+ context.pop();
+ }
+
+ /*
+ * Overriding the next() method to perform PUSH and POP operations
+ * for the NamespaceContext for the current element
+ */
+
+ @Override
+ public int next() throws XMLStreamException {
+ // POP the context if the element ends
+ if (this.getEventType() == END_ELEMENT) {
+ popContext();
+ }
+
+ //get the next event
+ int nextEvent = super.next();
+ //PUSH the events info onto the Stack
+ if (nextEvent == START_ELEMENT) {
+ pushContext();
+ }
+ return nextEvent;
+ }
+
+ @Override
+ public int nextTag() throws XMLStreamException {
+ int event = super.nextTag();
+ if (event == START_ELEMENT) {
+ pushContext();
+ }
+ if (event == END_ELEMENT) {
+ popContext();
+ }
+ return event;
+ }
+
+ @Override
+ public NamespaceContext getNamespaceContext() {
+ return new TuscanyNamespaceContext((Stack<List<String>[]>)context.clone());
+ }
+} \ No newline at end of file
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java
new file mode 100644
index 0000000000..c44ca0c66a
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.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;
+
+import java.net.URI;
+import java.net.URL;
+
+
+/**
+ * An artifact processor that can read models from a URL.
+ *
+ * @version $Rev$ $Date$
+ */
+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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..4806d443eb
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.util.Collection;
+
+/**
+ * An extension point for URL artifact processors.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface URLArtifactProcessorExtensionPoint {
+ /**
+ * Add an artifact processor.
+ *
+ * @param artifactProcessor The artifact processor to add
+ */
+ void addArtifactProcessor(URLArtifactProcessor<?> artifactProcessor);
+
+ /**
+ * Remove an artifact processor.
+ *
+ * @param artifactProcessor The artifact processor to remove
+ */
+ void removeArtifactProcessor(URLArtifactProcessor<?> artifactProcessor);
+
+ /**
+ * Returns the processor associated with the given artifact type.
+ *
+ * @param artifactType An artifact type
+ * @return The processor associated with the given artifact type
+ */
+ <T> URLArtifactProcessor<T> 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
+ */
+ <T> URLArtifactProcessor<T> getProcessor(Class<T> modelType);
+
+ /**
+ * Return a collection of artifact processors that match the artifactType
+ * @param artifactType
+ * @return A collection of processors
+ */
+ Collection<URLArtifactProcessor<?>> getProcessors(Object artifactType);
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnrecognizedElementException.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnrecognizedElementException.java
new file mode 100644
index 0000000000..4c6f0b7282
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/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.processor;
+
+import javax.xml.namespace.QName;
+
+/**
+ * Exception that indicates an element was encountered that could not be handled.
+ *
+ * @version $Rev$ $Date$
+ */
+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);
+ 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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedContentTypeException.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedContentTypeException.java
new file mode 100644
index 0000000000..8a166e42f0
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedContentTypeException.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+
+/**
+ * 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$ $Date$
+ */
+@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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedPackageTypeException.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedPackageTypeException.java
new file mode 100644
index 0000000000..ce94cef6a0
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedPackageTypeException.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.processor;
+
+
+/**
+ * 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$ $Date$
+ */
+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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLInputFactory.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLInputFactory.java
new file mode 100644
index 0000000000..c0eef5a7a8
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLInputFactory.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import javax.xml.stream.XMLInputFactory;
+
+/**
+ * Base marker class for validating XML input factories.
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class ValidatingXMLInputFactory extends XMLInputFactory {
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java
new file mode 100644
index 0000000000..ac7b644703
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java
@@ -0,0 +1,403 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.NamespaceContext;
+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.validation.Schema;
+import javax.xml.validation.ValidatorHandler;
+
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.apache.tuscany.sca.monitor.Problem.Severity;
+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$ $Date$
+ */
+class ValidatingXMLStreamReader extends TuscanyXMLStreamReader implements XMLStreamReader {
+
+ private static final Logger logger = Logger.getLogger(ValidatingXMLStreamReader.class.getName());
+
+ private int level;
+ private ValidatorHandler handler;
+ private final Monitor monitor;
+
+ /**
+ * Constructs a new ValidatingXMLStreamReader.
+ *
+ * @param reader
+ * @param schema
+ * @throws XMLStreamException
+ */
+ ValidatingXMLStreamReader(XMLStreamReader reader, Schema schema, Monitor monitor) throws XMLStreamException {
+ super(reader);
+ this.monitor = monitor;
+ 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) {
+ XMLStreamException xse = new XMLStreamException(e);
+ error("XMLStreamException", handler, xse);
+ throw xse;
+ }
+
+ // 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: " + getArtifactName( e.getSystemId() ) + ", line: " + e.getLineNumber() + ", column: " + e.getColumnNumber() + "\n" + e.getMessage();
+ }
+
+ public void error(SAXParseException exception) throws SAXException {
+ if (ValidatingXMLStreamReader.this.monitor == null)
+ logger.warning(getMessage(exception));
+ else
+ ValidatingXMLStreamReader.this.error("SchemaError", ValidatingXMLStreamReader.this.getClass(), getArtifactName( exception.getSystemId() ),
+ exception.getLineNumber(), exception.getColumnNumber(), exception.getMessage());
+ }
+
+ public void fatalError(SAXParseException exception) throws SAXException {
+ if (ValidatingXMLStreamReader.this.monitor == null)
+ logger.warning(getMessage(exception));
+ else
+ ValidatingXMLStreamReader.this.error("SchemaFatalError", ValidatingXMLStreamReader.this.getClass(), getArtifactName( exception.getSystemId() ),
+ exception.getLineNumber(), exception.getColumnNumber(), exception.getMessage());
+ }
+
+ public void warning(SAXParseException exception) throws SAXException {
+ if (ValidatingXMLStreamReader.this.monitor == null)
+ logger.warning(getMessage(exception));
+ else
+ ValidatingXMLStreamReader.this.warning("SchemaWarning", ValidatingXMLStreamReader.this.getClass(), getArtifactName( exception.getSystemId() ),
+ exception.getLineNumber(), exception.getColumnNumber(), exception.getMessage());
+ }
+
+ private String getArtifactName( String input ) {
+ String artifactName = input;
+ if( ValidatingXMLStreamReader.this.monitor != null ) {
+ artifactName = ValidatingXMLStreamReader.this.monitor.getArtifactName();
+ }
+ return artifactName;
+ }
+ });
+ }
+
+ /**
+ * Report a warning.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void warning(String message, Object model, Object... messageParameters) {
+ if (monitor != null) {
+ Problem problem = monitor.createProblem(this.getClass().getName(), "contribution-validation-messages", Severity.WARNING, model, message, (Object[])messageParameters);
+ monitor.problem(problem);
+ }
+ }
+
+ /**
+ * Report a error.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(String message, Object model, Object... messageParameters) {
+ if (monitor != null) {
+ Problem problem = monitor.createProblem(this.getClass().getName(), "contribution-validation-messages", Severity.ERROR, model, message, (Object[])messageParameters);
+ monitor.problem(problem);
+ }
+ }
+
+ @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) {
+ XMLStreamException xse = new XMLStreamException(e.getMessage(), e);
+ error("XMLStreamException", handler, xse);
+ throw xse;
+ }
+ 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();
+ pushContext();
+ 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--;
+ popContext();
+ return event;
+ case XMLStreamConstants.END_DOCUMENT:
+ handler.endDocument();
+ return event;
+ }
+ } catch (SAXException e) {
+ XMLStreamException xse = new XMLStreamException(e);
+ error("XMLStreamException", handler, xse);
+ throw xse;
+ }
+ 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;
+ }
+ }
+ }
+
+ @Override
+ public NamespaceContext getNamespaceContext(){
+ return super.getNamespaceContext();
+ }
+
+ /**
+ * 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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidationSchemaExtensionPoint.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidationSchemaExtensionPoint.java
new file mode 100644
index 0000000000..67ec55b72e
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidationSchemaExtensionPoint.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.util.List;
+
+
+/**
+ * An extension point for XML schemas used for validation.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ValidationSchemaExtensionPoint {
+ /**
+ * Set the flag to control if schema validation should be enabled
+ * @param enabled
+ */
+ void setEnabled(boolean enabled);
+
+ /**
+ * Test the schema validation is enabled
+ * @return
+ */
+ boolean isEnabled();
+
+ /**
+ * 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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/ContributionContentProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/ContributionContentProcessor.java
new file mode 100644
index 0000000000..5d8b950c45
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/ContributionContentProcessor.java
@@ -0,0 +1,261 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.impl;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+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.ContributionFactory;
+import org.apache.tuscany.sca.contribution.ContributionMetadata;
+import org.apache.tuscany.sca.contribution.DefaultExport;
+import org.apache.tuscany.sca.contribution.DefaultImport;
+import org.apache.tuscany.sca.contribution.Export;
+import org.apache.tuscany.sca.contribution.Import;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.processor.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.processor.ExtendedURLArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.ExtensibleURLArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint;
+import org.apache.tuscany.sca.contribution.resolver.DefaultModelResolver;
+import org.apache.tuscany.sca.contribution.resolver.ExtensibleModelResolver;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint;
+import org.apache.tuscany.sca.contribution.scanner.ContributionScanner;
+import org.apache.tuscany.sca.contribution.scanner.ContributionScannerExtensionPoint;
+import org.apache.tuscany.sca.contribution.scanner.impl.DirectoryContributionScanner;
+import org.apache.tuscany.sca.contribution.scanner.impl.JarContributionScanner;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.monitor.Monitor;
+
+/**
+ * URLArtifactProcessor that handles contribution files and the artifacts they contain
+ * and returns a contribution model.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ContributionContentProcessor implements ExtendedURLArtifactProcessor<Contribution>{
+ private ContributionFactory contributionFactory;
+ private ModelResolverExtensionPoint modelResolvers;
+ private FactoryExtensionPoint modelFactories;
+ private URLArtifactProcessor<Object> artifactProcessor;
+ private StAXArtifactProcessor<Object> extensionProcessor;
+ // private UtilityExtensionPoint utilities;
+ private Monitor monitor;
+ private ContributionScannerExtensionPoint scanners;
+ // Marks pre-resolve phase completed
+ private boolean preResolved = false;
+
+ public ContributionContentProcessor(ExtensionPointRegistry extensionPoints, StAXArtifactProcessor<Object> extensionProcessor, Monitor monitor) {
+ this.modelFactories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class);
+ this.modelResolvers = extensionPoints.getExtensionPoint(ModelResolverExtensionPoint.class);
+ this.monitor = monitor;
+ URLArtifactProcessorExtensionPoint artifactProcessors = extensionPoints.getExtensionPoint(URLArtifactProcessorExtensionPoint.class);
+ this.artifactProcessor = new ExtensibleURLArtifactProcessor(artifactProcessors, this.monitor);
+ this.extensionProcessor = extensionProcessor;
+ this.contributionFactory = modelFactories.getFactory(ContributionFactory.class);
+ this.scanners = extensionPoints.getExtensionPoint(ContributionScannerExtensionPoint.class);
+ }
+
+ /*
+ public ContributionContentProcessor(FactoryExtensionPoint modelFactories, ModelResolverExtensionPoint modelResolvers,
+ URLArtifactProcessor<Object> artifactProcessor, StAXArtifactProcessor<Object> extensionProcessor, Monitor monitor) {
+ this.modelFactories = modelFactories;
+ this.modelResolvers = modelResolvers;
+ hackResolvers(modelResolvers);
+ this.artifactProcessor = artifactProcessor;
+ this.extensionProcessor = extensionProcessor;
+ this.contributionFactory = modelFactories.getFactory(ContributionFactory.class);
+ this.monitor = monitor;
+ }
+ */
+
+ public String getArtifactType() {
+ return ".contribution/content";
+ }
+
+ public Class<Contribution> getModelType() {
+ return Contribution.class;
+ }
+
+ public Contribution read(URL parentURL, URI contributionURI, URL contributionURL) throws ContributionReadException {
+
+ // Create contribution model
+ Contribution contribution = contributionFactory.createContribution();
+ contribution.setURI(contributionURI.toString());
+ contribution.setLocation(contributionURL.toString());
+ ModelResolver modelResolver = new ExtensibleModelResolver(contribution, modelResolvers, modelFactories);
+ contribution.setModelResolver(modelResolver);
+ contribution.setUnresolved(true);
+
+ // Create a contribution scanner
+ ContributionScanner scanner = scanners.getContributionScanner(contributionURL.getProtocol());
+ if (scanner == null) {
+ try {
+ if ("file".equals(contributionURL.getProtocol()) && new File(contributionURL.toURI().getPath()).isDirectory()) {
+ scanner = new DirectoryContributionScanner();
+ } else {
+ scanner = new JarContributionScanner();
+ }
+ } catch (URISyntaxException e) {
+ throw new ContributionReadException(e);
+ }
+ }
+
+ // Scan the contribution and list the artifacts contained in it
+ List<Artifact> artifacts = contribution.getArtifacts();
+ boolean contributionMetadata = false;
+ List<String> artifactURIs = scanner.scan(contribution);
+ for (String artifactURI: artifactURIs) {
+ URL artifactURL = scanner.getArtifactURL(contribution, artifactURI);
+
+ // Add the deployed artifact model to the contribution
+ Artifact artifact = this.contributionFactory.createArtifact();
+ artifact.setURI(artifactURI);
+ artifact.setLocation(artifactURL.toString());
+ artifacts.add(artifact);
+ modelResolver.addModel(artifact);
+
+ // Read each artifact
+ Object model = artifactProcessor.read(contributionURL, URI.create(artifactURI), artifactURL);
+ if (model != null) {
+ artifact.setModel(model);
+
+ // Add the loaded model to the model resolver
+ modelResolver.addModel(model);
+
+ // Merge contribution metadata into the contribution model
+ if (model instanceof ContributionMetadata) {
+ contributionMetadata = true;
+ ContributionMetadata c = (ContributionMetadata)model;
+ contribution.getImports().addAll(c.getImports());
+ contribution.getExports().addAll(c.getExports());
+ contribution.getDeployables().addAll(c.getDeployables());
+ contribution.getExtensions().addAll(c.getExtensions());
+ contribution.getAttributeExtensions().addAll(c.getAttributeExtensions());
+ }
+ }
+ }
+
+ // If no sca-contribution.xml file was provided then just consider
+ // all composites in the contribution as deployables
+ if (!contributionMetadata) {
+ for (Artifact artifact: artifacts) {
+ if (artifact.getModel() instanceof Composite) {
+ contribution.getDeployables().add((Composite)artifact.getModel());
+ }
+ }
+
+ // Add default contribution import and export
+ DefaultImport defaultImport = contributionFactory.createDefaultImport();
+ defaultImport.setModelResolver(new DefaultModelResolver());
+ contribution.getImports().add(defaultImport);
+ DefaultExport defaultExport = contributionFactory.createDefaultExport();
+ contribution.getExports().add(defaultExport);
+ }
+ return contribution;
+ }
+
+ /**
+ * A pre-resolution step, which is required for Contributions to handle the resolution of imports and exports so that
+ * at resolve time, imports can be followed to exports and anything exported that is required can be resolved on demand
+ * without the need to have already resolved the whole of the Contribution containing the export
+ * @param contribution - the Contribution
+ * @param resolver - the Resolver to use
+ * @throws ContributionResolveException
+ */
+ public void preResolve(Contribution contribution, ModelResolver resolver) throws ContributionResolveException {
+ // Resolve the contribution model itself
+ ModelResolver contributionResolver = contribution.getModelResolver();
+ contribution.setUnresolved(false);
+ contributionResolver.addModel(contribution);
+
+ // Resolve Exports
+ resolveExports(contribution, contributionResolver);
+ // Resolve Imports
+ resolveImports(contribution, contributionResolver);
+
+ preResolved = true;
+ } // end method preResolve
+
+ public void resolve(Contribution contribution, ModelResolver resolver) throws ContributionResolveException {
+
+ if( !preResolved ) preResolve( contribution, resolver);
+ ModelResolver contributionResolver = contribution.getModelResolver();
+
+ // Resolve all artifact models
+ for (Artifact artifact : contribution.getArtifacts()) {
+ Object model = artifact.getModel();
+ if (model != null) {
+ try {
+ artifactProcessor.resolve(model, contributionResolver);
+ } catch (Throwable e) {
+ throw new ContributionResolveException(e);
+ }
+ }
+ }
+
+ // Resolve deployable composites
+ List<Composite> deployables = contribution.getDeployables();
+ for (int i = 0, n = deployables.size(); i < n; i++) {
+ Composite deployable = deployables.get(i);
+ Composite resolved = (Composite)contributionResolver.resolveModel(Composite.class, deployable);
+ if (resolved != deployable) {
+ deployables.set(i, resolved);
+ }
+ } // end for
+ } // end method resolve
+
+ /**
+ * Resolves the Exports of the contribution
+ * @param contribution
+ * @param resolver
+ */
+ private void resolveExports(Contribution contribution, ModelResolver resolver) throws ContributionResolveException {
+ for (Export export: contribution.getExports()) {
+ if (export instanceof DefaultExport) {
+ // Initialize the default export's resolver
+ export.setModelResolver(resolver);
+ } else {
+ extensionProcessor.resolve(export, resolver);
+ } // end if
+ } // end for
+
+ } // end method resolveExports
+
+ /**
+ * Resolves the Imports of the contribution
+ * @param contribution
+ * @param resolver
+ */
+ private void resolveImports(Contribution contribution, ModelResolver resolver) throws ContributionResolveException {
+ for (Import import_: contribution.getImports()) {
+ extensionProcessor.resolve(import_, resolver);
+ } // end for
+ } // end method resolveImports
+
+} // end class ContributionContentProcessor
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/ContributionInfoProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/ContributionInfoProcessor.java
new file mode 100644
index 0000000000..ef435d6aed
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/ContributionInfoProcessor.java
@@ -0,0 +1,234 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.ContributionFactory;
+import org.apache.tuscany.sca.contribution.ContributionMetadata;
+import org.apache.tuscany.sca.contribution.DefaultExport;
+import org.apache.tuscany.sca.contribution.DefaultImport;
+import org.apache.tuscany.sca.contribution.Export;
+import org.apache.tuscany.sca.contribution.Import;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.processor.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.processor.ExtensibleURLArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint;
+import org.apache.tuscany.sca.contribution.resolver.ClassReference;
+import org.apache.tuscany.sca.contribution.resolver.DefaultModelResolver;
+import org.apache.tuscany.sca.contribution.resolver.ExtensibleModelResolver;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint;
+import org.apache.tuscany.sca.contribution.scanner.ContributionScanner;
+import org.apache.tuscany.sca.contribution.scanner.impl.DirectoryContributionScanner;
+import org.apache.tuscany.sca.contribution.scanner.impl.JarContributionScanner;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.monitor.Monitor;
+
+/**
+ * URLArtifactProcessor that handles contribution files and returns a contribution
+ * info model.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ContributionInfoProcessor implements URLArtifactProcessor<Contribution>{
+ private ContributionFactory contributionFactory;
+ private ModelResolverExtensionPoint modelResolvers;
+ private FactoryExtensionPoint modelFactories;
+ private URLArtifactProcessorExtensionPoint artifactProcessors;
+ private URLArtifactProcessor<Object> artifactProcessor;
+ private StAXArtifactProcessor<Object> extensionProcessor;
+
+ public ContributionInfoProcessor(ExtensionPointRegistry extensionPoints, StAXArtifactProcessor<Object> extensionProcessor, Monitor monitor) {
+ this.modelFactories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class);
+ this.modelResolvers = extensionPoints.getExtensionPoint(ModelResolverExtensionPoint.class);
+ hackResolvers(modelResolvers);
+ URLArtifactProcessorExtensionPoint artifactProcessors = extensionPoints.getExtensionPoint(URLArtifactProcessorExtensionPoint.class);
+ this.artifactProcessors = artifactProcessors;
+ this.artifactProcessor = new ExtensibleURLArtifactProcessor(artifactProcessors, monitor);
+ this.extensionProcessor = extensionProcessor;
+ this.contributionFactory = modelFactories.getFactory(ContributionFactory.class);
+ }
+
+ public ContributionInfoProcessor(FactoryExtensionPoint modelFactories, ModelResolverExtensionPoint modelResolvers, URLArtifactProcessor<Object> artifactProcessor) {
+ this.modelFactories = modelFactories;
+ this.modelResolvers = modelResolvers;
+ hackResolvers(modelResolvers);
+ this.artifactProcessor = artifactProcessor;
+ this.contributionFactory = modelFactories.getFactory(ContributionFactory.class);
+ }
+
+ public String getArtifactType() {
+ return ".contribution/info";
+ }
+
+ public Class<Contribution> getModelType() {
+ return null;
+ }
+
+ public Contribution read(URL parentURL, URI contributionURI, URL contributionURL) throws ContributionReadException {
+
+ // Create contribution model
+ Contribution contribution = contributionFactory.createContribution();
+ contribution.setURI(contributionURI.toString());
+ contribution.setLocation(contributionURL.toString());
+ ModelResolver modelResolver = new ExtensibleModelResolver(contribution, modelResolvers, modelFactories);
+ contribution.setModelResolver(modelResolver);
+ contribution.setUnresolved(true);
+
+ // Create a contribution scanner
+ ContributionScanner scanner = null;
+ if (scanner == null) {
+ try {
+ if ("file".equals(contributionURL.getProtocol()) && new File(contributionURL.toURI()).isDirectory()) {
+ scanner = new DirectoryContributionScanner();
+ } else {
+ scanner = new JarContributionScanner();
+ }
+ } catch (URISyntaxException e) {
+ throw new ContributionReadException(e);
+ }
+ }
+
+ // Read generated and user sca-contribution.xml files
+ boolean contributionMetadata = false;
+ for (String path: new String[]{
+ Contribution.SCA_CONTRIBUTION_GENERATED_META,
+ Contribution.SCA_CONTRIBUTION_META}) {
+ URL url = scanner.getArtifactURL(contribution, path);
+ try {
+ // Check if the file actually exists before trying to read it
+ URLConnection connection = url.openConnection();
+ connection.setUseCaches(false);
+ InputStream is = connection.getInputStream();
+ is.close();
+ } catch (IOException e) {
+ continue;
+ }
+ contributionMetadata = true;
+
+ // Read the sca-contribution.xml file
+ ContributionMetadata c = (ContributionMetadata)artifactProcessor.read(contributionURL, URI.create(path), url);
+ contribution.getImports().addAll(c.getImports());
+ contribution.getExports().addAll(c.getExports());
+ contribution.getDeployables().addAll(c.getDeployables());
+ contribution.getExtensions().addAll(c.getExtensions());
+ contribution.getAttributeExtensions().addAll(c.getAttributeExtensions());
+ }
+
+ // If no sca-contribution.xml file was provided then consider
+ // all composites in the contribution as deployables, and also
+ // read any files that are explicitly asssigned artifact processors
+ // as they are likely to provide relevant metadata info
+ if (!contributionMetadata) {
+ List<String> artifactURIs;
+ try {
+ artifactURIs = scanner.scan(contribution);
+ } catch (ContributionReadException e) {
+ artifactURIs = null;
+ }
+ if (artifactURIs != null) {
+ for (String artifactURI: artifactURIs) {
+ boolean read = false;
+ if (artifactURI.endsWith(".composite")) {
+ read = true;
+ } else {
+ int s= artifactURI.lastIndexOf("/");
+ String fileName = artifactURI.substring(s + 1);
+ if (artifactProcessors.getProcessor(fileName) != null) {
+ read = true;
+ }
+ }
+ if (read) {
+ URL artifactURL = scanner.getArtifactURL(contribution, artifactURI);
+
+ // Read each artifact
+ Object model = artifactProcessor.read(contributionURL, URI.create(artifactURI), artifactURL);
+
+ // In the absence of more info, consider all composites as deployable
+ if (model instanceof Composite) {
+ contribution.getDeployables().add((Composite)model);
+ }
+ }
+ }
+ }
+
+ // Add default contribution import and export
+ DefaultImport defaultImport = contributionFactory.createDefaultImport();
+ defaultImport.setModelResolver(new DefaultModelResolver());
+ contribution.getImports().add(defaultImport);
+ DefaultExport defaultExport = contributionFactory.createDefaultExport();
+ contribution.getExports().add(defaultExport);
+ }
+
+ return contribution;
+ }
+
+ public void resolve(Contribution contribution, ModelResolver resolver) throws ContributionResolveException {
+
+ // Mark the contribution model resolved
+ ModelResolver contributionResolver = contribution.getModelResolver();
+ contribution.setUnresolved(false);
+ contributionResolver.addModel(contribution);
+
+ // Resolve imports and exports
+ for (Export export: contribution.getExports()) {
+ if (export instanceof DefaultExport) {
+
+ // Initialize the default export's resolver
+ export.setModelResolver(contributionResolver);
+
+ } else {
+ extensionProcessor.resolve(export, contributionResolver);
+ }
+ }
+ for (Import import_: contribution.getImports()) {
+ extensionProcessor.resolve(import_, contributionResolver);
+ }
+
+ }
+
+ /**
+ * FIXME Temporary hack for testing the ClassLoaderModelResolver.
+ *
+ * @param modelResolvers
+ */
+ private static void hackResolvers(ModelResolverExtensionPoint modelResolvers) {
+ Class<?> resolverClass = modelResolvers.getResolver(ClassReference.class);
+ if (resolverClass==null || !resolverClass.getName().equals("org.apache.tuscany.sca.contribution.java.impl.ClassLoaderModelResolver")) {
+ try {
+ Class<?> loaderResolverClass = Class.forName("org.apache.tuscany.sca.contribution.java.impl.ClassLoaderModelResolver", true, ContributionContentProcessor.class.getClassLoader());
+ modelResolvers.addResolver(ClassReference.class, (Class<? extends ModelResolver>)loaderResolverClass);
+ } catch (ClassNotFoundException e) {
+ }
+ }
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyAttributeProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyAttributeProcessor.java
new file mode 100644
index 0000000000..aad7747522
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyAttributeProcessor.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.processor.xml;
+
+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.assembly.Extension;
+import org.apache.tuscany.sca.contribution.Constants;
+import org.apache.tuscany.sca.contribution.processor.BaseStAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.processor.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.processor.ContributionWriteException;
+import org.apache.tuscany.sca.contribution.processor.StAXAttributeProcessor;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.monitor.Monitor;
+
+/**
+ * A Policy Processor used for testing.
+ *
+ * @version $Rev$ $Date$
+ */
+public class AnyAttributeProcessor extends BaseStAXArtifactProcessor implements StAXAttributeProcessor<Extension> {
+ private static final QName ANY_ATTRIBUTE = new QName(Constants.XMLSCHEMA_NS, "anyAttribute");
+
+ private AssemblyFactory assemblyFactory;
+
+ public AnyAttributeProcessor(FactoryExtensionPoint modelFactories, Monitor monitor) {
+ this.assemblyFactory = modelFactories.getFactory(AssemblyFactory.class);
+ }
+
+ public QName getArtifactType() {
+ return ANY_ATTRIBUTE;
+ }
+
+ public Class<Extension> getModelType() {
+ return Extension.class;
+ }
+
+ public Extension read(QName attributeName, XMLStreamReader reader) throws ContributionReadException, XMLStreamException {
+ String attributeValue = reader.getAttributeValue(attributeName.getNamespaceURI(), attributeName.getLocalPart());
+ Extension ext = assemblyFactory.createExtension();
+ ext.setQName(attributeName);
+ ext.setAttribute(true);
+ ext.setValue(attributeValue);
+ return ext;
+ }
+
+ public void write(Extension attributeExtension, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException {
+ writer.writeAttribute(attributeExtension.getQName().getPrefix(),
+ attributeExtension.getQName().getNamespaceURI(),
+ attributeExtension.getQName().getLocalPart(),
+ attributeExtension.getValue().toString()); //for extended attributes, we can assume values
+ // are just the string representation fo the attribute
+ }
+
+ public void resolve(Extension arg0, ModelResolver arg1) throws ContributionResolveException {
+
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyElementProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyElementProcessor.java
new file mode 100644
index 0000000000..68c46a2301
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyElementProcessor.java
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor.xml;
+
+import static javax.xml.stream.XMLStreamConstants.CDATA;
+import static javax.xml.stream.XMLStreamConstants.CHARACTERS;
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.stream.events.XMLEvent;
+
+import org.apache.tuscany.sca.contribution.Constants;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.processor.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.monitor.Monitor;
+
+public class AnyElementProcessor implements StAXArtifactProcessor<Object> {
+ private static final QName ANY_ELEMENT = new QName(Constants.XMLSCHEMA_NS, "anyElement");
+
+ private XMLInputFactory xmlInputFactory;
+ @SuppressWarnings("unused")
+ private Monitor monitor;
+
+
+ public AnyElementProcessor(FactoryExtensionPoint modelFactories, Monitor monitor) {
+ xmlInputFactory = modelFactories.getFactory(XMLInputFactory.class);
+ this.monitor = monitor;
+ }
+
+ public QName getArtifactType() {
+ return ANY_ELEMENT;
+ }
+
+ public Class<Object> getModelType() {
+ return Object.class;
+ }
+
+ /**
+ * Reads the contetns of the unknown elements and generates a custom
+ * implementation of XMLStreamReader i.e. XMLEventsStreamReader
+ *
+ * @param reader
+ * @return
+ * @throws XMLStreamException
+ */
+ @SuppressWarnings("unchecked")
+ public Object read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException {
+
+ // Custom variables
+ String currentElement = null;
+ List eventsList = new ArrayList();
+
+ Map<String, NamespaceContext> eventContext = new HashMap<String, NamespaceContext>();
+
+ try {
+ // Cast the block of unknown elements into document
+ XMLDocumentStreamReader docReader = new XMLDocumentStreamReader(reader);
+
+ XMLEventReader xmlEventReader = xmlInputFactory.createXMLEventReader(docReader);
+
+ while (xmlEventReader.hasNext()) {
+ XMLEvent event = xmlEventReader.nextEvent();
+
+ // Populate the eventContext map with the current element's name
+ // and corresponding NamesapceContext
+ if (currentElement != null && !(eventContext.containsKey(currentElement))) {
+ eventContext.put(currentElement, reader.getNamespaceContext());
+ }
+
+ // Populate the list with the XMLEvents
+ eventsList.add(event);
+ if (event.isStartElement()) {
+ currentElement = reader.getName().getLocalPart();
+ }
+ if (event.isEndDocument()) {
+ return new XMLEventsStreamReader(eventsList, eventContext);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * Writes unknown portions back to the writer
+ *
+ * @param model
+ * @param writer
+ */
+ public void write(Object model, XMLStreamWriter writer) throws XMLStreamException {
+ if (!(model instanceof XMLStreamReader)) {
+ return;
+ }
+ XMLStreamReader reader = (XMLStreamReader)model;
+
+ int event = reader.getEventType();
+ while (reader.hasNext()) {
+ switch (event) {
+ case START_ELEMENT:
+
+ writer.writeStartElement(reader.getPrefix(), reader.getLocalName(), reader.getNamespaceURI());
+ for (int i = 1; i <= reader.getAttributeCount(); i++) {
+ writer.writeAttribute(reader.getAttributePrefix(i), reader.getAttributeNamespace(i), reader
+ .getAttributeLocalName(i), reader.getAttributeValue(i));
+ }
+ break;
+
+ case CHARACTERS:
+ writer.writeCharacters(reader.getText());
+ break;
+
+ case CDATA:
+ writer.writeCData(reader.getText());
+ break;
+
+ case END_ELEMENT:
+ writer.writeEndElement();
+ break;
+ }
+ if (reader.hasNext()) {
+ event = reader.next();
+ }
+ }
+ }
+
+ public void resolve(Object model, ModelResolver resolver) throws ContributionResolveException {
+
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/XMLDocumentStreamReader.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/XMLDocumentStreamReader.java
new file mode 100644
index 0000000000..7e8b3a9d9e
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/XMLDocumentStreamReader.java
@@ -0,0 +1,482 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.xml;
+
+import java.util.NoSuchElementException;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+/**
+ * This class is derived from Apache Axis2 class
+ * org.apache.axis2.util.StreamWrapper</a>. It's used wrap a XMLStreamReader to
+ * create a XMLStreamReader representing a document and it will produce
+ * START_DOCUMENT, END_DOCUMENT events.
+ *
+ * @version $Rev: 659153 $ $Date: 2008-05-22 09:43:58 -0700 (Thu, 22 May 2008) $
+ */
+public class XMLDocumentStreamReader implements XMLStreamReader {
+ private static final int STATE_COMPLETE_AT_NEXT = 2; // The wrapper
+ // will produce
+ // END_DOCUMENT
+
+ private static final int STATE_COMPLETED = 3; // Done
+
+ private static final int STATE_INIT = 0; // The wrapper will produce
+ // START_DOCUMENT
+
+ private static final int STATE_SWITCHED = 1; // The real reader will
+ // produce events
+
+ private XMLStreamReader realReader;
+ private boolean fragment;
+ private int level = 0;
+
+ private int state = STATE_INIT;
+
+ public XMLDocumentStreamReader(XMLStreamReader realReader) {
+ if (realReader == null) {
+ throw new UnsupportedOperationException("Reader cannot be null");
+ }
+
+ this.realReader = realReader;
+
+ if (realReader instanceof XMLFragmentStreamReader) {
+ ((XMLFragmentStreamReader)realReader).init();
+ }
+
+ // If the real reader is positioned at START_DOCUMENT, always use
+ // the real reader
+ if (realReader.getEventType() == START_DOCUMENT) {
+ fragment = false;
+ state = STATE_SWITCHED;
+ }
+ }
+
+ public void close() throws XMLStreamException {
+ realReader.close();
+ }
+
+ public int getAttributeCount() {
+ if (isDelegating()) {
+ return realReader.getAttributeCount();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getAttributeLocalName(int i) {
+ if (isDelegating()) {
+ return realReader.getAttributeLocalName(i);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public QName getAttributeName(int i) {
+ if (isDelegating()) {
+ return realReader.getAttributeName(i);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getAttributeNamespace(int i) {
+ if (isDelegating()) {
+ return realReader.getAttributeNamespace(i);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getAttributePrefix(int i) {
+ if (isDelegating()) {
+ return realReader.getAttributePrefix(i);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getAttributeType(int i) {
+ if (isDelegating()) {
+ return realReader.getAttributeType(i);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getAttributeValue(int i) {
+ if (isDelegating()) {
+ return realReader.getAttributeValue(i);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getAttributeValue(String s, String s1) {
+ if (isDelegating()) {
+ return realReader.getAttributeValue(s, s1);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getCharacterEncodingScheme() {
+ return realReader.getCharacterEncodingScheme();
+ }
+
+ public String getElementText() throws XMLStreamException {
+ if (isDelegating()) {
+ return realReader.getElementText();
+ } else {
+ throw new XMLStreamException();
+ }
+ }
+
+ public String getEncoding() {
+ return realReader.getEncoding();
+ }
+
+ public int getEventType() {
+ int event = -1;
+ switch (state) {
+ case STATE_SWITCHED:
+ case STATE_COMPLETE_AT_NEXT:
+ event = realReader.getEventType();
+ break;
+ case STATE_INIT:
+ event = START_DOCUMENT;
+ break;
+ case STATE_COMPLETED:
+ event = END_DOCUMENT;
+ break;
+ }
+ return event;
+ }
+
+ public String getLocalName() {
+ if (isDelegating()) {
+ return realReader.getLocalName();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public Location getLocation() {
+ if (isDelegating()) {
+ return realReader.getLocation();
+ } else {
+ return null;
+ }
+ }
+
+ public QName getName() {
+ if (isDelegating()) {
+ return realReader.getName();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public NamespaceContext getNamespaceContext() {
+ return realReader.getNamespaceContext();
+ }
+
+ public int getNamespaceCount() {
+ if (isDelegating()) {
+ return realReader.getNamespaceCount();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getNamespacePrefix(int i) {
+ if (isDelegating()) {
+ return realReader.getNamespacePrefix(i);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getNamespaceURI() {
+ if (isDelegating()) {
+ return realReader.getNamespaceURI();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getNamespaceURI(int i) {
+ if (isDelegating()) {
+ return realReader.getNamespaceURI(i);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getNamespaceURI(String s) {
+ if (isDelegating()) {
+ return realReader.getNamespaceURI(s);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getPIData() {
+ if (isDelegating()) {
+ return realReader.getPIData();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getPITarget() {
+ if (isDelegating()) {
+ return realReader.getPITarget();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getPrefix() {
+ if (isDelegating()) {
+ return realReader.getPrefix();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public Object getProperty(String s) throws IllegalArgumentException {
+ if (isDelegating()) {
+ return realReader.getProperty(s);
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public String getText() {
+ if (isDelegating()) {
+ return realReader.getText();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public char[] getTextCharacters() {
+ if (isDelegating()) {
+ return realReader.getTextCharacters();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException {
+ if (isDelegating()) {
+ return realReader.getTextCharacters(i, chars, i1, i2);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public int getTextLength() {
+ if (isDelegating()) {
+ return realReader.getTextLength();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public int getTextStart() {
+ if (isDelegating()) {
+ return realReader.getTextStart();
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public String getVersion() {
+ if (isDelegating()) {
+ return realReader.getVersion();
+ } else {
+ return null;
+ }
+ }
+
+ public boolean hasName() {
+ if (isDelegating()) {
+ return realReader.hasName();
+ } else {
+ return false;
+ }
+ }
+
+ public boolean hasNext() throws XMLStreamException {
+ if (state == STATE_COMPLETE_AT_NEXT) {
+ return true;
+ } else if (state == STATE_COMPLETED) {
+ return false;
+ } else if (state == STATE_SWITCHED) {
+ return realReader.hasNext();
+ } else {
+ return true;
+ }
+ }
+
+ public boolean hasText() {
+ if (isDelegating()) {
+ return realReader.hasText();
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isAttributeSpecified(int i) {
+ if (isDelegating()) {
+ return realReader.isAttributeSpecified(i);
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isCharacters() {
+ if (isDelegating()) {
+ return realReader.isCharacters();
+ } else {
+ return false;
+ }
+ }
+
+ private boolean isDelegating() {
+ return state == STATE_SWITCHED || state == STATE_COMPLETE_AT_NEXT;
+ }
+
+ public boolean isEndElement() {
+ if (isDelegating()) {
+ return realReader.isEndElement();
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isStandalone() {
+ if (isDelegating()) {
+ return realReader.isStandalone();
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isStartElement() {
+ if (isDelegating()) {
+ return realReader.isStartElement();
+ } else {
+ return false;
+ }
+ }
+
+ public boolean isWhiteSpace() {
+ if (isDelegating()) {
+ return realReader.isWhiteSpace();
+ } else {
+ return false;
+ }
+ }
+
+ public int next() throws XMLStreamException {
+ int returnEvent;
+
+ switch (state) {
+ case STATE_SWITCHED:
+ returnEvent = realReader.next();
+ if (returnEvent == END_DOCUMENT) {
+ state = STATE_COMPLETED;
+ } else if (!realReader.hasNext()) {
+ state = STATE_COMPLETE_AT_NEXT;
+ }
+ if (fragment && returnEvent == END_ELEMENT) {
+ level--;
+ if (level == -1) {
+ // We are now at the end of the top-level element in the fragment
+ state = STATE_COMPLETE_AT_NEXT;
+ }
+ }
+ if (fragment && returnEvent == START_ELEMENT) {
+ level++;
+ }
+ break;
+ case STATE_INIT:
+ state = STATE_SWITCHED;
+ returnEvent = realReader.getEventType();
+ if (returnEvent == START_ELEMENT) {
+ // The real reader is positioned at the top-level element in the fragment
+ level = 0;
+ fragment = true;
+ }
+ break;
+ case STATE_COMPLETE_AT_NEXT:
+ state = STATE_COMPLETED;
+ returnEvent = END_DOCUMENT;
+ break;
+ case STATE_COMPLETED:
+ // oops - no way we can go beyond this
+ throw new NoSuchElementException("End of stream has reached.");
+ default:
+ throw new UnsupportedOperationException();
+ }
+
+ return returnEvent;
+ }
+
+ public int nextTag() throws XMLStreamException {
+ if (isDelegating()) {
+ int returnEvent = realReader.nextTag();
+ if (fragment && returnEvent == END_ELEMENT) {
+ level--;
+ if (level == 0) {
+ // We are now at the end of the top-level element in the fragment
+ state = STATE_COMPLETE_AT_NEXT;
+ }
+ }
+ if (fragment && returnEvent == START_ELEMENT) {
+ level++;
+ }
+ return returnEvent;
+ } else {
+ throw new XMLStreamException();
+ }
+ }
+
+ public void require(int i, String s, String s1) throws XMLStreamException {
+ if (isDelegating()) {
+ realReader.require(i, s, s1);
+ }
+ }
+
+ public boolean standaloneSet() {
+ if (isDelegating()) {
+ return realReader.standaloneSet();
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/XMLEventsStreamReader.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/XMLEventsStreamReader.java
new file mode 100644
index 0000000000..eecdee5ba6
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/XMLEventsStreamReader.java
@@ -0,0 +1,444 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.xml;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.Namespace;
+import javax.xml.stream.events.ProcessingInstruction;
+import javax.xml.stream.events.XMLEvent;
+
+
+public class XMLEventsStreamReader implements XMLStreamReader {
+
+ @SuppressWarnings("unused")
+ private ArrayList<XMLEvent> events = null;
+ private HashMap<String, NamespaceContext> eventContext = null;
+
+ private int state;
+ private java.util.Iterator<XMLEvent> iterator;
+ private XMLEvent current;
+
+ public XMLEventsStreamReader(List<XMLEvent> events,Map<String, NamespaceContext> map) {
+ this.events = (ArrayList<XMLEvent>) events;
+ this.eventContext = (HashMap<String, NamespaceContext>) map;
+ this.iterator = events.iterator();
+ this.current = iterator.next();
+ this.state = current.getEventType();
+ }
+
+ public void close() throws XMLStreamException {
+ this.events = null;
+ this.eventContext = null;
+ this.iterator = null;
+ this.current = null;
+ }
+
+ private void checkElementState() {
+ if (getEventType() != START_ELEMENT && getEventType() != END_ELEMENT) {
+ throw new IllegalStateException();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public int getAttributeCount() {
+ checkElementState();
+ int count = 0;
+ Iterator<Attribute> iterator = current.asStartElement().getAttributes();
+ while (iterator.hasNext()) {
+ count++;
+ iterator.next();
+ }
+ return count;
+ }
+
+ /*
+ * Custom method to get attribute from the specified index
+ */
+ @SuppressWarnings("unchecked")
+ private Attribute getAttribute(int index) {
+ checkElementState();
+ int count = 0;
+ Attribute attribute = null;
+ Iterator<Attribute> iterator = current.asStartElement().getAttributes();
+ while (iterator.hasNext()) {
+ count++;
+ if (count == index) {
+ attribute = iterator.next();
+ } else {
+ iterator.next();
+ }
+ }
+ return attribute;
+ }
+
+
+ public String getAttributeLocalName(int index) {
+ checkElementState();
+ return getAttribute(index).getName().getLocalPart();
+ }
+
+ public QName getAttributeName(int index) {
+ checkElementState();
+ return getAttribute(index).getName();
+ }
+
+ public String getAttributeNamespace(int index) {
+ checkElementState();
+ return getAttributeName(index).getNamespaceURI();
+ }
+
+ public String getAttributePrefix(int index) {
+ checkElementState();
+ return getAttributeName(index).getPrefix();
+ }
+
+ public String getAttributeType(int index) {
+ checkElementState();
+ return getAttribute(index).getDTDType();
+ }
+
+ public String getAttributeValue(int index) {
+ checkElementState();
+ return getAttribute(index).getValue();
+ }
+
+ @SuppressWarnings("unchecked")
+ public String getAttributeValue(String namespaceURI, String localName) {
+ checkElementState();
+ Iterator<Attribute> iterator = current.asStartElement().getAttributes();
+ Attribute attribute;
+ while (iterator.hasNext()) {
+ attribute = iterator.next();
+ if (attribute.getName().getNamespaceURI().equalsIgnoreCase(
+ namespaceURI)
+ && attribute.getName().getLocalPart().equalsIgnoreCase(
+ localName)) {
+ return attribute.getValue();
+ }
+ }
+ return null;
+
+ }
+
+ public String getCharacterEncodingScheme() {
+ return "UTF-8";
+ }
+
+ public String getElementText() throws XMLStreamException {
+ checkElementState();
+ int eventType = getEventType();
+ String elementText = null;
+
+ if (eventType == START_ELEMENT) {
+ elementText = current.asStartElement().getName().getLocalPart();
+ } else if (eventType == END_ELEMENT) {
+ elementText = current.asEndElement().getName().getLocalPart();
+ }
+ return elementText;
+ }
+
+ public String getEncoding() {
+ return "UTF-8";
+ }
+
+ public int getEventType() {
+ return state;
+ }
+
+ public String getLocalName() {
+ checkElementState();
+ switch (current.getEventType()) {
+ case START_ELEMENT:
+ return current.asStartElement().getName().getLocalPart();
+ case END_ELEMENT:
+ return current.asEndElement().getName().getLocalPart();
+ }
+ return null;
+ }
+
+ public Location getLocation() {
+ return current.getLocation();
+ }
+
+ public QName getName() {
+ checkElementState();
+ switch (current.getEventType()) {
+ case START_ELEMENT:
+ return current.asStartElement().getName();
+ case END_ELEMENT:
+ return current.asEndElement().getName();
+ }
+ return null;
+ }
+
+ public NamespaceContext getNamespaceContext() {
+ checkElementState();
+ //return new TuscanyNamespaceContext(eventContext.get(getLocalName()));
+ return eventContext.get(getLocalName());
+ }
+
+ @SuppressWarnings("unchecked")
+ public int getNamespaceCount() {
+ int count = 0;
+ Iterator<Namespace> itr = current.asStartElement().getNamespaces();
+ while (itr.hasNext()) {
+ count++;
+ itr.next();
+ }
+ return count;
+ }
+
+ @SuppressWarnings("unchecked")
+ public String getNamespacePrefix(int index) {
+ Iterator<Namespace> itr = current.asStartElement().getNamespaces();
+ int level = 0;
+ Namespace ns = null;
+ while (itr.hasNext()) {
+ ns = itr.next();
+ if (level == index) {
+ return ns.getPrefix();
+ }
+ level++;
+ }
+ return null;
+ }
+
+ public String getNamespaceURI() {
+ checkElementState();
+ switch (current.getEventType()) {
+ case START_ELEMENT:
+ return current.asStartElement().getName().getNamespaceURI();
+ case END_ELEMENT:
+ return current.asEndElement().getName().getNamespaceURI();
+ }
+ return null;
+ }
+
+ public String getNamespaceURI(String prefix) {
+ return getNamespaceContext().getNamespaceURI(prefix);
+ }
+
+ @SuppressWarnings("unchecked")
+ public String getNamespaceURI(int index) {
+ Iterator<Namespace> itr = current.asStartElement().getNamespaces();
+ int level = 0;
+ Namespace ns = null;
+ while (itr.hasNext()) {
+ ns = itr.next();
+ if (level == index) {
+ return ns.getNamespaceURI();
+ }
+ level++;
+ }
+ return null;
+ }
+
+ public String getPIData() {
+ if (current.isProcessingInstruction()) {
+ ProcessingInstruction pi = (ProcessingInstruction) current;
+ return pi.getData();
+ } else {
+ throw new IllegalStateException(current.toString());
+ }
+ }
+
+ public String getPITarget() {
+ if (current.isProcessingInstruction()) {
+ ProcessingInstruction pi = (ProcessingInstruction) current;
+ return pi.getTarget();
+ } else {
+ throw new IllegalStateException(current.toString());
+ }
+ }
+
+ public String getPrefix() {
+ checkElementState();
+ if (current.isStartElement()) {
+ return current.asStartElement().getName().getPrefix();
+ }
+ return null;
+ }
+
+ /*
+ * FIXME: Implementation pending...
+ *
+ * @see (non-Javadoc)
+ * javax.xml.stream.util.StreamReaderDelegate#getProperty(java.lang.String)
+ */
+ public Object getProperty(String name) throws IllegalArgumentException {
+ // TODO Auto-generated method stub
+
+ return null;
+ }
+
+ public String getText() {
+ if (current.isCharacters()) {
+ return current.asCharacters().getData();
+ } else {
+ throw new IllegalStateException(current.toString());
+ }
+ }
+
+ public char[] getTextCharacters() {
+ if (current.isCharacters()) {
+ return current.asCharacters().getData().toCharArray();
+ } else {
+ throw new IllegalStateException(current.toString());
+ }
+ }
+
+ /*
+ * FIXME: Implementation pending... (non-Javadoc)
+ *
+ * @see javax.xml.stream.util.StreamReaderDelegate#getTextCharacters(int,
+ * char[], int, int)
+ */
+ public int getTextCharacters(int sourceStart, char[] target,
+ int targetStart, int length) throws XMLStreamException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ /*
+ * FIXME:Implementaion can be improved (non-Javadoc)
+ *
+ * @see javax.xml.stream.util.StreamReaderDelegate#getTextLength()
+ */
+ public int getTextLength() {
+ if (current.isCharacters()) {
+ return current.asCharacters().getData().length();
+ } else {
+ throw new IllegalStateException(current.toString());
+ }
+ }
+
+ /*
+ * FIXME: Implementation pending... (non-Javadoc)
+ *
+ * @see javax.xml.stream.util.StreamReaderDelegate#getTextStart()
+ */
+ public int getTextStart() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ /*
+ * FIXME: Implementation pending... (non-Javadoc)
+ *
+ * @see javax.xml.stream.util.StreamReaderDelegate#getTextStart()
+ */
+ public String getVersion() {
+ // TODO Auto-generated method stub
+
+ return null;
+ }
+
+ public boolean hasName() {
+ return false;
+ }
+
+ public boolean hasNext() throws XMLStreamException {
+ return iterator.hasNext() || state != END_DOCUMENT;
+
+ }
+
+ public boolean hasText() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /*
+ * FIXME: Implementation pending... (non-Javadoc)
+ *
+ * @see javax.xml.stream.util.StreamReaderDelegate#getTextStart()
+ */
+ public boolean isAttributeSpecified(int index) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean isCharacters() {
+ return current.isCharacters();
+ }
+
+ public boolean isEndElement() {
+ return current.isEndElement();
+ }
+
+ public boolean isStandalone() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean isStartElement() {
+ return current.isStartElement();
+ }
+
+ public boolean isWhiteSpace() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public int next() throws XMLStreamException {
+ if (!hasNext()) {
+ throw new IllegalStateException("No more events");
+ }
+ if (!iterator.hasNext()) {
+ state = END_DOCUMENT;
+ current = null;
+ return state;
+ }
+ current = iterator.next();
+ state = current.getEventType();
+ return state;
+ }
+
+ public int nextTag() throws XMLStreamException {
+ return iterator.next().getEventType();
+ }
+
+ public void require(int type, String namespaceURI, String localName)
+ throws XMLStreamException {
+ boolean require = false;
+ String uri = getNamespaceURI();
+ String name = getLocalName();
+ if (state == type && namespaceURI.equals(uri) && localName.equals(name)) {
+ require = true;
+ }
+ if (require != true) {
+ throw new XMLStreamException();
+ }
+ }
+
+ public boolean standaloneSet() {
+ return false;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/XMLFragmentStreamReader.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/XMLFragmentStreamReader.java
new file mode 100644
index 0000000000..66361e1d76
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/XMLFragmentStreamReader.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor.xml;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamReader;
+
+public interface XMLFragmentStreamReader extends XMLStreamReader {
+ QName NIL_QNAME = new QName("http://www.w3.org/2001/XMLSchema-instance", "nil", "xsi");
+ String NIL_VALUE_TRUE = "true";
+
+ /**
+ * this will help to handle Text within the current element. user should
+ * pass the element text to the property list as this ELEMENT_TEXT as the
+ * key. This key deliberately has a space in it so that it is not a valid
+ * XML name
+ */
+ String ELEMENT_TEXT = "Element Text";
+
+ /**
+ * Extra method to query the state of the pullparser
+ */
+ boolean isDone();
+
+ /**
+ * add the parent namespace context to this parser
+ */
+ void setParentNamespaceContext(NamespaceContext nsContext);
+
+ /**
+ * Initiate the parser - this will do whatever the needed tasks to initiate
+ * the parser and must be called before attempting any specific parsing
+ * using this parser
+ */
+ void init();
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java
new file mode 100644
index 0000000000..f3555ee71e
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.resolver;
+
+import java.lang.ref.WeakReference;
+
+import org.apache.tuscany.sca.assembly.Base;
+
+/**
+ * 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$ $Date$
+ */
+public class ClassReference implements Base {
+
+ 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;
+ }
+
+ public boolean isUnresolved() {
+ return clazz == null;
+ }
+
+ public void setUnresolved(boolean unresolved) {
+ throw new IllegalStateException();
+ }
+
+ @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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultDelegatingModelResolver.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultDelegatingModelResolver.java
new file mode 100644
index 0000000000..13c622adf0
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultDelegatingModelResolver.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.resolver;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Base;
+
+/**
+ * A model resolver implementation that delegates to a list of model resolvers.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultDelegatingModelResolver implements ModelResolver {
+
+ private List<ModelResolver> resolvers;
+
+ public DefaultDelegatingModelResolver(List<ModelResolver> resolvers) {
+ this.resolvers = resolvers;
+ }
+
+ 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 resolvers
+ for (ModelResolver resolver: resolvers) {
+
+ Object resolved = resolver.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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java
new file mode 100644
index 0000000000..c6facd2b02
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/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 a list of contributions.
+ *
+ * @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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportModelResolver.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportModelResolver.java
new file mode 100644
index 0000000000..9ae57c41d0
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportModelResolver.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;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Base;
+import org.apache.tuscany.sca.contribution.Export;
+
+/**
+ * A model resolver implementation that delegates to a list of exports.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultImportModelResolver implements ModelResolver {
+
+ private List<Export> exports;
+
+ public DefaultImportModelResolver(List<Export> exports) {
+ this.exports = exports;
+ }
+
+ 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 exports
+ for (Export export: exports) {
+
+ 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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolver.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolver.java
new file mode 100644
index 0000000000..1803315e2e
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolver.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.resolver;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.DefaultImport;
+import org.apache.tuscany.sca.contribution.Import;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+
+/**
+ * A default implementation of a model resolver based on a map.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultModelResolver implements ModelResolver {
+
+ private Contribution contribution;
+ private Map<Object, Object> map = new HashMap<Object, Object>();
+
+ public DefaultModelResolver() {
+ }
+
+ public DefaultModelResolver(Contribution contribution, FactoryExtensionPoint modelFactories) {
+ this.contribution = contribution;
+ }
+
+ 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 {
+
+ // by default try and resolve through a default import
+ // if there is one.
+ if (contribution != null){
+ for (Import _import : contribution.getImports()){
+ if (_import instanceof DefaultImport){
+ resolved = _import.getModelResolver().resolveModel(modelClass, unresolved);
+ if (resolved != unresolved){
+ return modelClass.cast(resolved);
+ }
+ }
+ }
+ }
+
+ // Return the unresolved object
+ return unresolved;
+ }
+ }
+
+ public void addModel(Object resolved) {
+ map.put(resolved, resolved);
+ }
+
+ public Object removeModel(Object resolved) {
+ return map.remove(resolved);
+ }
+
+ // FIXME: TUSCANY-2499: temporarily give access to the models to get the jms binding
+ // use of definitions.xml working while the definitions.xml processing is being refactored
+ public Map<Object, Object> getModels() {
+ return map;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.java
new file mode 100644
index 0000000000..7cbf8d5528
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/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.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+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$ $Date$
+ */
+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 synchronized void loadModelResolvers() {
+ if (loadedResolvers != null)
+ return;
+ loadedResolvers = new HashMap<String, ServiceDeclaration>();
+
+ // Get the model resolver service declarations
+ Collection<ServiceDeclaration> modelResolverDeclarations;
+ try {
+ modelResolverDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(ModelResolver.class.getName());
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+
+ // Load model resolvers
+ for (ServiceDeclaration modelResolverDeclaration: modelResolverDeclarations) {
+ Map<String, String> attributes = modelResolverDeclaration.getAttributes();
+ String model = attributes.get("model");
+
+ loadedResolvers.put(model, modelResolverDeclaration);
+ }
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java
new file mode 100644
index 0000000000..b48742bcae
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java
@@ -0,0 +1,200 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.core.FactoryExtensionPoint;
+
+/**
+ * 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$ $Date$
+ */
+public class ExtensibleModelResolver implements ModelResolver {
+ private final ModelResolverExtensionPoint resolverExtensions;
+ private final FactoryExtensionPoint modelFactories;
+ private final Contribution contribution;
+ private ModelResolver defaultResolver;
+ private final Map<Class<?>, ModelResolver> resolversByModelType = new HashMap<Class<?>, ModelResolver>();
+ private final Map<Class<?>, ModelResolver> resolversByImplementationClass = new HashMap<Class<?>, ModelResolver>();
+ private Map<Object, Object> map = new HashMap<Object, Object>();
+ private Object lastUnresolved;
+
+ /**
+ * Constructs an extensible model resolver
+ *
+ * @param contribution
+ * @param resolverExtensions
+ * @param modelFactories
+ * @param defaultResolver
+ */
+ @Deprecated
+ public ExtensibleModelResolver(Contribution contribution,
+ ModelResolverExtensionPoint resolverExtensions,
+ FactoryExtensionPoint modelFactories,
+ ModelResolver defaultResolver) {
+ this.contribution = contribution;
+ this.resolverExtensions = resolverExtensions;
+ this.modelFactories = modelFactories;
+ //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 resolverExtensions
+ * @param contribution
+ * @param modelFactories
+ */
+ public ExtensibleModelResolver(Contribution contribution,
+ ModelResolverExtensionPoint resolverExtensions,
+ FactoryExtensionPoint modelFactories) {
+ this.contribution = contribution;
+ this.resolverExtensions = resolverExtensions;
+ this.modelFactories = modelFactories;
+ }
+
+ /**
+ * 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 = resolversByModelType.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 = resolverExtensions.getResolver(c);
+ if (resolverClass != null) {
+
+ // Construct the model resolver instance and cache it
+ resolverInstance = resolversByImplementationClass.get(resolverClass);
+ if (resolverInstance != null) {
+ resolversByModelType.put(c, resolverInstance);
+ return resolverInstance;
+ }
+ try {
+ Constructor<? extends ModelResolver> constructor =
+ resolverClass
+ .getConstructor(new Class[] {Contribution.class, FactoryExtensionPoint.class});
+ if (constructor != null) {
+
+ resolverInstance = constructor.newInstance(contribution, modelFactories);
+ resolversByImplementationClass.put(resolverClass, resolverInstance);
+ resolversByModelType.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) {
+ // Protect against dependency cycles causing infinite recursion
+ // Save the current unresolved object and check later if we are trying
+ // to resolve the same object again
+ if (unresolved == lastUnresolved) {
+ return unresolved;
+ }
+ lastUnresolved = unresolved;
+
+ ModelResolver resolver = getModelResolverInstance(unresolved.getClass());
+ if (resolver != null) {
+ Object resolved = resolver.resolveModel(modelClass, unresolved);
+ if (resolved != null && resolved != unresolved) {
+ lastUnresolved = null;
+ return modelClass.cast(resolved);
+ }
+ } 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) {
+ lastUnresolved = null;
+ return modelClass.cast(resolved);
+ }
+ }
+
+ Object resolved = map.get(unresolved);
+ if (resolved != null) {
+ // Return the resolved object
+ lastUnresolved = null;
+ return modelClass.cast(resolved);
+ }
+ }
+
+ return unresolved;
+ }
+
+ // FIXME: TUSCANY-2499: temporarily give access to the defaultResolver to get the jms binding
+ // use of definitions.xml working while the definitions.xml processing is being refactored
+ public ModelResolver getDefaultModelResolver() {
+ return defaultResolver;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.java
new file mode 100644
index 0000000000..2831bebbc4
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/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$ $Date$
+ */
+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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java
new file mode 100644
index 0000000000..4a25059792
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/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$ $Date$
+ */
+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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResolverExtension.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResolverExtension.java
new file mode 100644
index 0000000000..74f0f2d71d
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResolverExtension.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.resolver;
+
+/**
+ * Extension to assembly model implementations to provide a model resolver.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ResolverExtension {
+
+ /**
+ * 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);
+
+} \ No newline at end of file
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResourceReference.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResourceReference.java
new file mode 100644
index 0000000000..2394f4510b
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResourceReference.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.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.
+ *
+ * @version $Rev$ $Date$
+ */
+@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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java
new file mode 100644
index 0000000000..d2f29a001b
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.scanner;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.processor.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$ $Date$
+ */
+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 contribution Contribution URL
+ * @return List of artifact URIs
+ * @throws ContributionReadException
+ * @throws IOException
+ */
+ List<String> scan(Contribution contribution) 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 contribution Contribution URL
+ * @param artifact The relative URI for the artifact
+ * @throws ContributionReadException
+ * @return The artifact URL
+ */
+ URL getArtifactURL(Contribution contribution, String artifact) throws ContributionReadException;
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java
new file mode 100644
index 0000000000..1ca9def4ea
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/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$ $Date$
+ */
+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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java
new file mode 100644
index 0000000000..a1af72da72
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.scanner;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.processor.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$ $Date$
+ */
+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 synchronized void loadScanners() {
+ if (loaded)
+ return;
+
+ // Get the scanner service declarations
+ Collection<ServiceDeclaration> scannerDeclarations;
+ try {
+ scannerDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(ContributionScanner.class.getName());
+ } 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(Contribution contributionSourceURL, String artifact) throws ContributionReadException {
+ return getScanner().getArtifactURL(contributionSourceURL, artifact);
+ }
+
+ public List<String> scan(Contribution contributionSourceURL) throws ContributionReadException {
+ return getScanner().scan(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/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/DirectoryContributionScanner.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/DirectoryContributionScanner.java
new file mode 100644
index 0000000000..95a4ed69e8
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/DirectoryContributionScanner.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.scanner.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.PackageType;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.scanner.ContributionScanner;
+
+/**
+ * Folder contribution processor.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DirectoryContributionScanner implements ContributionScanner {
+
+ public DirectoryContributionScanner() {
+ }
+
+ public String getContributionType() {
+ return PackageType.FOLDER;
+ }
+
+ public URL getArtifactURL(Contribution contribution, String artifact) throws ContributionReadException {
+ File directory = directory(contribution);
+ File file = new File(directory, artifact);
+ try {
+ return file.toURI().toURL();
+ } catch (MalformedURLException e) {
+ throw new ContributionReadException(e);
+ }
+ }
+
+ public List<String> scan(Contribution contribution) throws ContributionReadException {
+ File directory = directory(contribution);
+ List<String> artifacts = new ArrayList<String>();
+ try {
+ traverse(artifacts, directory, directory);
+ } catch (IOException e) {
+ throw new ContributionReadException(e);
+ }
+ contribution.getTypes().add(getContributionType());
+ return artifacts;
+ }
+
+ /**
+ * Recursively traverse a root directory
+ *
+ * @param fileList
+ * @param file
+ * @param root
+ * @throws IOException
+ */
+ private static void traverse(List<String> fileList, File file, File root) throws IOException {
+ if (file.isFile()) {
+ fileList.add(root.toURI().relativize(file.toURI()).toString());
+ } else if (file.isDirectory()) {
+ String uri = root.toURI().relativize(file.toURI()).toString();
+ if (uri.endsWith("/")) {
+ uri = uri.substring(0, uri.length() - 1);
+ }
+ fileList.add(uri);
+
+ File[] files = file.listFiles();
+ for (File f: files) {
+ if (!f.getName().startsWith(".")) {
+ traverse(fileList, f, root);
+ }
+ }
+ }
+ }
+
+ private static File directory(Contribution contribution) throws ContributionReadException {
+ File file;
+ try {
+ file = new File(new URI(contribution.getLocation()));
+ } catch (URISyntaxException e) {
+ throw new ContributionReadException(e);
+ }
+ if (!file.exists() || !file.isDirectory()) {
+ throw new ContributionReadException(contribution.getLocation());
+ }
+ return file;
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/JarContributionScanner.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/JarContributionScanner.java
new file mode 100644
index 0000000000..f1fb6f2a70
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/JarContributionScanner.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.scanner.impl;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.PackageType;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.scanner.ContributionScanner;
+
+/**
+ * JAR Contribution processor.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JarContributionScanner implements ContributionScanner {
+
+ public JarContributionScanner() {
+ }
+
+ public String getContributionType() {
+ return PackageType.JAR;
+ }
+
+ public URL getArtifactURL(Contribution contribution, String artifact) throws ContributionReadException {
+ try {
+ URL url;
+ if (contribution.toString().startsWith("jar:")) {
+ url = new URL(new URL(contribution.getLocation()), artifact.toString());
+ } else {
+ url = new URL("jar:" + contribution.getLocation() + "!/" + artifact);
+ }
+ return url;
+ } catch (MalformedURLException e) {
+ throw new ContributionReadException(e);
+ }
+ }
+
+ public List<String> scan(Contribution contribution) throws ContributionReadException {
+
+ // Assume the URL references a JAR file
+ try {
+ URL url = new URL(contribution.getLocation());
+ URLConnection connection = url.openConnection();
+ connection.setUseCaches(false);
+ JarInputStream jar = new JarInputStream(connection.getInputStream());
+ try {
+ Set<String> names = new HashSet<String>();
+ while (true) {
+ JarEntry entry = jar.getNextJarEntry();
+ if (entry == null) {
+ // EOF
+ break;
+ }
+
+ String name = entry.getName();
+ if (name.length() != 0 && !name.startsWith(".")) {
+
+ // Trim trailing /
+ if (name.endsWith("/")) {
+ name = name.substring(0, name.length() - 1);
+ }
+
+ // Add the entry name
+ if (!names.contains(name)) {
+ names.add(name);
+
+ // Add parent folder names to the list too
+ for (;;) {
+ int s = name.lastIndexOf('/');
+ if (s == -1) {
+ name = "";
+ } else {
+ name = name.substring(0, s);
+ }
+ if (name.length() != 0 && !names.contains(name)) {
+ names.add(name);
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Return list of URIs
+ List<String> artifacts = new ArrayList<String>(names);
+ contribution.getTypes().add(getContributionType());
+ return artifacts;
+
+ } finally {
+ jar.close();
+ }
+ } catch (IOException e) {
+ throw new ContributionReadException(e);
+ }
+ }
+
+ public void postProcess(Contribution contribution) {
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionGeneratedMetadataDocumentProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionGeneratedMetadataDocumentProcessor.java
new file mode 100644
index 0000000000..0035f360ab
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionGeneratedMetadataDocumentProcessor.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.xml;
+
+import javax.xml.stream.XMLInputFactory;
+
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.monitor.Monitor;
+
+/**
+ * URLArtifactProcessor that handles sca-contribution-generated.xml files.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ContributionGeneratedMetadataDocumentProcessor extends ContributionMetadataDocumentProcessor {
+
+ public ContributionGeneratedMetadataDocumentProcessor(XMLInputFactory inputFactory,
+ StAXArtifactProcessor staxProcessor,
+ Monitor monitor) {
+ super(inputFactory, staxProcessor, monitor);
+ }
+
+ public ContributionGeneratedMetadataDocumentProcessor(FactoryExtensionPoint modelFactories,
+ StAXArtifactProcessor staxProcessor,
+ Monitor monitor) {
+ super(modelFactories, staxProcessor, monitor);
+ }
+
+ @Override
+ public String getArtifactType() {
+ return "/META-INF/sca-contribution-generated.xml";
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataDocumentProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataDocumentProcessor.java
new file mode 100644
index 0000000000..d5fa606997
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataDocumentProcessor.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.sca.contribution.ContributionMetadata;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.processor.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.ValidatingXMLInputFactory;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.apache.tuscany.sca.monitor.Problem.Severity;
+
+/**
+ * URLArtifactProcessor that handles sca-contribution.xml files.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ContributionMetadataDocumentProcessor implements URLArtifactProcessor<ContributionMetadata>{
+ private final StAXArtifactProcessor staxProcessor;
+ private final XMLInputFactory inputFactory;
+ private final Monitor monitor;
+
+ public ContributionMetadataDocumentProcessor(XMLInputFactory inputFactory,
+ StAXArtifactProcessor staxProcessor,
+ Monitor monitor) {
+ this.inputFactory = inputFactory;
+ this.staxProcessor = staxProcessor;
+ this.monitor = monitor;
+ }
+
+ public ContributionMetadataDocumentProcessor(FactoryExtensionPoint modelFactories,
+ StAXArtifactProcessor staxProcessor,
+ Monitor monitor) {
+ this.inputFactory = modelFactories.getFactory(ValidatingXMLInputFactory.class);
+ this.staxProcessor = staxProcessor;
+ this.monitor = monitor;
+ }
+
+ /**
+ * Report a exception.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(String message, Object model, Exception ex) {
+ if (monitor != null) {
+ Problem problem = monitor.createProblem(this.getClass().getName(), "contribution-xml-validation-messages", Severity.ERROR, model, message, ex);
+ monitor.problem(problem);
+ }
+ }
+
+ public String getArtifactType() {
+ return "/META-INF/sca-contribution.xml";
+ }
+
+ public Class<ContributionMetadata> getModelType() {
+ return ContributionMetadata.class;
+ }
+
+ public ContributionMetadata read(URL contributionURL, URI uri, URL url) throws ContributionReadException {
+ InputStream urlStream = null;
+ try {
+
+ // Create a stream reader
+ URLConnection connection = url.openConnection();
+ connection.setUseCaches(false);
+ urlStream = connection.getInputStream();
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(url.toString(), urlStream);
+ reader.nextTag();
+
+ // Read the contribution model
+ ContributionMetadata contribution = (ContributionMetadata)staxProcessor.read(reader);
+
+ return contribution;
+
+ } catch (XMLStreamException e) {
+ ContributionReadException ex = new ContributionReadException(e);
+ error("XMLStreamException", inputFactory, ex);
+ throw ex;
+ } catch (IOException e) {
+ ContributionReadException ex = new ContributionReadException(e);
+ error("IOException", inputFactory, ex);
+ throw ex;
+ } finally {
+ try {
+ if (urlStream != null) {
+ urlStream.close();
+ urlStream = null;
+ }
+ } catch (IOException ioe) {
+ //ignore
+ }
+ }
+ }
+
+ public void resolve(ContributionMetadata contribution, ModelResolver resolver) throws ContributionResolveException {
+ staxProcessor.resolve(contribution, resolver);
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataProcessor.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataProcessor.java
new file mode 100644
index 0000000000..7218a0fb73
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataProcessor.java
@@ -0,0 +1,246 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.xml;
+
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+
+import java.util.List;
+
+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;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.contribution.ContributionFactory;
+import org.apache.tuscany.sca.contribution.ContributionMetadata;
+import org.apache.tuscany.sca.contribution.Export;
+import org.apache.tuscany.sca.contribution.Import;
+import org.apache.tuscany.sca.contribution.processor.BaseStAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.processor.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.processor.ContributionWriteException;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXAttributeProcessor;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.apache.tuscany.sca.monitor.Problem.Severity;
+
+/**
+ * Processor for contribution metadata
+ *
+ * @version $Rev$ $Date$
+ */
+public class ContributionMetadataProcessor extends BaseStAXArtifactProcessor implements
+ StAXArtifactProcessor<ContributionMetadata> {
+ private static final String SCA11_NS = "http://docs.oasis-open.org/ns/opencsa/sca/200903";
+
+ private static final QName CONTRIBUTION_QNAME = new QName(SCA11_NS, "contribution");
+ private static final QName DEPLOYABLE_QNAME = new QName(SCA11_NS, "deployable");
+
+ private final AssemblyFactory assemblyFactory;
+ private final ContributionFactory contributionFactory;
+ private final StAXArtifactProcessor<Object> extensionProcessor;
+ private final StAXAttributeProcessor<Object> attributeProcessor;
+ private Monitor monitor;
+
+ public ContributionMetadataProcessor(FactoryExtensionPoint modelFactories,
+ StAXArtifactProcessor<Object> extensionProcessor,
+ StAXAttributeProcessor<Object> attributeProcessor,
+ Monitor monitor) {
+ this.assemblyFactory = modelFactories.getFactory(AssemblyFactory.class);
+ this.contributionFactory = modelFactories.getFactory(ContributionFactory.class);
+ this.extensionProcessor = extensionProcessor;
+ this.attributeProcessor = attributeProcessor;
+ this.monitor = monitor;
+ }
+
+ /**
+ * Report a error.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(String message, Object model, Object... messageParameters) {
+ if (monitor != null) {
+ Problem problem =
+ monitor.createProblem(this.getClass().getName(),
+ "contribution-xml-validation-messages",
+ Severity.ERROR,
+ model,
+ message,
+ (Object[])messageParameters);
+ monitor.problem(problem);
+ }
+ }
+
+ /**
+ * Report a exception.
+ *
+ * @param problems
+ * @param message
+ * @param model
+ */
+ private void error(String message, Object model, Exception ex) {
+ if (monitor != null) {
+ Problem problem =
+ monitor.createProblem(this.getClass().getName(), "contribution-xml-validation-messages", Severity.ERROR,
+ model, message, ex);
+ monitor.problem(problem);
+ }
+ }
+
+ public QName getArtifactType() {
+ return CONTRIBUTION_QNAME;
+ }
+
+ public Class<ContributionMetadata> getModelType() {
+ return ContributionMetadata.class;
+ }
+
+ public ContributionMetadata read(XMLStreamReader reader) throws ContributionReadException {
+ ContributionMetadata contribution = null;
+ QName name = null;
+
+ try {
+ while (reader.hasNext()) {
+ int event = reader.getEventType();
+ switch (event) {
+ case START_ELEMENT:
+ name = reader.getName();
+
+ if (CONTRIBUTION_QNAME.equals(name)) {
+
+ // Read <contribution>
+ contribution = this.contributionFactory.createContributionMetadata();
+ contribution.setUnresolved(true);
+ readExtendedAttributes(reader, contribution, attributeProcessor, assemblyFactory);
+
+ } else if (DEPLOYABLE_QNAME.equals(name)) {
+
+ // Read <deployable>
+ QName compositeName = getQName(reader, "composite");
+ if (compositeName == null) {
+ error("AttributeCompositeMissing", reader);
+ //throw new ContributionReadException("Attribute 'composite' is missing");
+ } else {
+ if (contribution != null) {
+ Composite composite = assemblyFactory.createComposite();
+ composite.setName(compositeName);
+ composite.setUnresolved(true);
+ contribution.getDeployables().add(composite);
+ }
+ }
+ } else {
+
+ // Read an extension element
+ Object extension = extensionProcessor.read(reader);
+ if (extension != null && contribution != null) {
+ if (extension instanceof Import) {
+ contribution.getImports().add((Import)extension);
+ } else if (extension instanceof Export) {
+ contribution.getExports().add((Export)extension);
+ } else {
+ contribution.getExtensions().add(extension);
+ }
+ }
+ }
+ break;
+
+ case XMLStreamConstants.END_ELEMENT:
+ if (CONTRIBUTION_QNAME.equals(reader.getName())) {
+ return contribution;
+ }
+ break;
+ }
+
+ //Read the next element
+ if (reader.hasNext()) {
+ reader.next();
+ }
+ }
+ } catch (XMLStreamException e) {
+ ContributionReadException ex = new ContributionReadException(e);
+ error("XMLStreamException", reader, ex);
+ }
+
+ return contribution;
+ }
+
+ public void write(ContributionMetadata contribution, XMLStreamWriter writer) throws ContributionWriteException,
+ XMLStreamException {
+
+ // Write <contribution>
+ writeStartDocument(writer, CONTRIBUTION_QNAME.getNamespaceURI(), CONTRIBUTION_QNAME.getLocalPart());
+ writeExtendedAttributes(writer, contribution, attributeProcessor);
+
+ // Write <import>
+ for (Import imp : contribution.getImports()) {
+ extensionProcessor.write(imp, writer);
+ }
+
+ // Write <export>
+ for (Export export : contribution.getExports()) {
+ extensionProcessor.write(export, writer);
+ }
+
+ // Write <deployable>
+ for (Composite deployable : contribution.getDeployables()) {
+ writeStart(writer,
+ DEPLOYABLE_QNAME.getNamespaceURI(),
+ DEPLOYABLE_QNAME.getLocalPart(),
+ new XAttr("composite", deployable.getName()));
+ writeEnd(writer);
+ }
+
+ writeEndDocument(writer);
+ }
+
+ public void resolve(ContributionMetadata contribution, ModelResolver resolver) throws ContributionResolveException {
+
+ // Resolve imports and exports
+ for (Export export : contribution.getExports()) {
+ extensionProcessor.resolve(export, resolver);
+ }
+ for (Import import_ : contribution.getImports()) {
+ extensionProcessor.resolve(import_, resolver);
+ }
+
+ // Resolve deployable composites
+ List<Composite> deployables = contribution.getDeployables();
+ for (int i = 0, n = deployables.size(); i < n; i++) {
+ Composite deployable = deployables.get(i);
+ Composite resolved = (Composite)resolver.resolveModel(Composite.class, deployable);
+ if (resolved != deployable) {
+ deployables.set(i, resolved);
+ }
+ }
+
+ for (Object ext : contribution.getExtensions()) {
+ extensionProcessor.resolve(ext, resolver);
+ }
+
+ contribution.setUnresolved(false);
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionModelResolver.java b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionModelResolver.java
new file mode 100644
index 0000000000..ddc768b61c
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionModelResolver.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.xml;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+
+/**
+ * A Model Resolver for Contribution models.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ContributionModelResolver implements ModelResolver {
+
+ private Map<String, Contribution> map = new HashMap<String, Contribution>();
+
+ public ContributionModelResolver(Contribution contribution, FactoryExtensionPoint modelFactories) {
+ }
+
+ public void addModel(Object resolved) {
+ Contribution contribution = (Contribution)resolved;
+ map.put(contribution.getURI(), contribution);
+ }
+
+ public Object removeModel(Object resolved) {
+ return map.remove(((Contribution)resolved).getURI());
+ }
+
+ public <T> T resolveModel(Class<T> modelClass, T unresolved) {
+
+ // Lookup a contribution for the given URI
+ String uri = ((Contribution)unresolved).getURI();
+ if (uri != null) {
+ Contribution resolved = (Contribution) map.get(uri);
+ if (resolved != null) {
+ return modelClass.cast(resolved);
+ }
+ return unresolved;
+ } else {
+
+ // If no URI was specified, just return the first contribution
+ if (!map.isEmpty()) {
+ Contribution resolved = map.values().iterator().next();
+ return modelClass.cast(resolved);
+ } else {
+ return unresolved;
+ }
+ }
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ContributionFactory b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ContributionFactory
new file mode 100644
index 0000000000..bcc346d9f8
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/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/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.java.JavaImportExportFactory b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.java.JavaImportExportFactory
new file mode 100644
index 0000000000..a293330a57
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.java.JavaImportExportFactory
@@ -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.java.impl.JavaImportExportFactoryImpl
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.namespace.NamespaceImportExportFactory b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.namespace.NamespaceImportExportFactory
new file mode 100644
index 0000000000..095866fb6f
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.namespace.NamespaceImportExportFactory
@@ -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.namespace.impl.NamespaceImportExportFactoryImpl
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor
new file mode 100644
index 0000000000..9fcbca5c59
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor
@@ -0,0 +1,24 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Implementation class for the artifact processor extension
+org.apache.tuscany.sca.contribution.xml.ContributionMetadataProcessor;qname=http://docs.oasis-open.org/ns/opencsa/sca/200903#contribution,model=org.apache.tuscany.sca.contribution.ContributionMetadata
+org.apache.tuscany.sca.contribution.processor.xml.AnyElementProcessor;qname=http://www.w3.org/2001/XMLSchema#anyElement,model=java.lang.Object
+org.apache.tuscany.sca.contribution.namespace.impl.NamespaceImportProcessor;qname=http://docs.oasis-open.org/ns/opencsa/sca/200903#import,model=org.apache.tuscany.sca.contribution.namespace.NamespaceImport
+org.apache.tuscany.sca.contribution.namespace.impl.NamespaceExportProcessor;qname=http://docs.oasis-open.org/ns/opencsa/sca/200903#export,model=org.apache.tuscany.sca.contribution.namespace.NamespaceExport
+org.apache.tuscany.sca.contribution.java.impl.JavaImportProcessor;qname=http://docs.oasis-open.org/ns/opencsa/sca/200903#import.java,model=org.apache.tuscany.sca.contribution.java.JavaImport
+org.apache.tuscany.sca.contribution.java.impl.JavaExportProcessor;qname=http://docs.oasis-open.org/ns/opencsa/sca/200903#export.java,model=org.apache.tuscany.sca.contribution.java.JavaExport
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint
new file mode 100644
index 0000000000..8ea5fc0a7e
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/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/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXAttributeProcessor b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXAttributeProcessor
new file mode 100644
index 0000000000..b4a13295bc
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXAttributeProcessor
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Implementation class for the attribute processor extension
+org.apache.tuscany.sca.contribution.processor.xml.AnyAttributeProcessor;qname=http://www.w3.org/2001/XMLSchema#anyAttribute,model=org.apache.tuscany.sca.assembly.Extension
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXAttributeProcessorExtensionPoint b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXAttributeProcessorExtensionPoint
new file mode 100644
index 0000000000..607725bcfe
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXAttributeProcessorExtensionPoint
@@ -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.DefaultStAXAttributeProcessorExtensionPoint
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor
new file mode 100644
index 0000000000..560bf9abcb
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Implementation class for the artifact processor extension
+org.apache.tuscany.sca.contribution.xml.ContributionMetadataDocumentProcessor;type=/META-INF/sca-contribution.xml,model=org.apache.tuscany.sca.contribution.ContributionMetadata
+org.apache.tuscany.sca.contribution.xml.ContributionGeneratedMetadataDocumentProcessor;type=/META-INF/sca-contribution-generated.xml
+org.apache.tuscany.sca.contribution.processor.impl.ContributionContentProcessor;type=.contribution/content,model=org.apache.tuscany.sca.contribution.Contribution
+org.apache.tuscany.sca.contribution.processor.impl.ContributionInfoProcessor;type=.contribution/info
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint
new file mode 100644
index 0000000000..9d78ca93d0
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/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/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidatingXMLInputFactory b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidatingXMLInputFactory
new file mode 100644
index 0000000000..f2856cb259
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidatingXMLInputFactory
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+org.apache.tuscany.sca.contribution.processor.DefaultValidatingXMLInputFactory \ No newline at end of file
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchemaExtensionPoint b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchemaExtensionPoint
new file mode 100644
index 0000000000..ae6e876df6
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/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/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver
new file mode 100644
index 0000000000..44d3daccb8
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+org.apache.tuscany.sca.contribution.xml.ContributionModelResolver;model=org.apache.tuscany.sca.contribution.Contribution
+org.apache.tuscany.sca.contribution.java.impl.ClassLoaderModelResolver;model=org.apache.tuscany.sca.contribution.resolver.ClassReference
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint
new file mode 100644
index 0000000000..4bb65e55e7
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/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/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.scanner.ContributionScannerExtensionPoint b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.scanner.ContributionScannerExtensionPoint
new file mode 100644
index 0000000000..727f8f6ce7
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/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/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/contribution-java-validation-messages.properties b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/contribution-java-validation-messages.properties
new file mode 100644
index 0000000000..09fc3e9fff
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/contribution-java-validation-messages.properties
@@ -0,0 +1,23 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#
+AttributePackageMissing = Attribute 'package' is missing
+XMLStreamException = XMLStreamException occured due to : {0}
+
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/contribution-namespace-validation-messages.properties b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/contribution-namespace-validation-messages.properties
new file mode 100644
index 0000000000..c1cbd06e7f
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/contribution-namespace-validation-messages.properties
@@ -0,0 +1,23 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#
+AttributeNameSpaceMissing = Attribute 'namespace' is missing
+XMLStreamException = XMLStreamException occured due to : {0}
+
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/contribution-validation-messages.properties b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/contribution-validation-messages.properties
new file mode 100644
index 0000000000..63c4746a4d
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/contribution-validation-messages.properties
@@ -0,0 +1,34 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#
+SchemaError = XMLSchema validation error occured in: {0} ,line = {1}, column = {2}, Message = {3}
+SchemaFatalError = XMLSchema validation fatal error occured in: {0} ,line = {1}, column = {2}, Message = {3}
+SchemaWarning = XMLSchema validation warning occured in: {0} ,line = {1}, column = {2}, Message = {3}
+UnsupportedPackageTypeException = Unsupported contribution package type: {0}
+ElementCannotBeProcessed = Element {0} cannot be processed. ({1})
+AttributeCannotBeProcessed = Attribute {0} cannot be processed. ({1})
+NoStaxProcessor = No StAX processor is configured to handle {0}
+ContributionWriteException = ContributionWriteException occured due to :
+ContributionReadException = ContributionReadException occured due to :
+UnrecognizedElementException = Unrecognized Element : {0}
+IllegalArgumentException = Invalid qname: {0}
+PrivilegedActionException = PrivilegedActionException occured due to : {0}
+AttributeCannotBeProcessed = Attribute {0} cannot be processed. ({1})
+
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/contribution-xml-validation-messages.properties b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/contribution-xml-validation-messages.properties
new file mode 100644
index 0000000000..4827fd5e94
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/main/resources/contribution-xml-validation-messages.properties
@@ -0,0 +1,24 @@
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#
+XMLStreamException = XMLStreamException occured due to : {0}
+IOException = IOException occured due to : {0}
+AttributeCompositeMissing = Attribute 'composite' is missing
+
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/java/impl/ClassReferenceArtifactResolverTestCase.java b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/java/impl/ClassReferenceArtifactResolverTestCase.java
new file mode 100644
index 0000000000..68a2c771cf
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/java/impl/ClassReferenceArtifactResolverTestCase.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.java.impl;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.tuscany.sca.contribution.resolver.ClassReference;
+import org.apache.tuscany.sca.contribution.resolver.ExtensibleModelResolver;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint;
+import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Test ClassReferenceArtifactResolver.
+ *
+ * @version $Rev: 560435 $ $Date: 2007-07-27 18:26:55 -0700 (Fri, 27 Jul 2007) $
+ */
+public class ClassReferenceArtifactResolverTestCase {
+ private static ExtensibleModelResolver resolver;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ ExtensionPointRegistry extensionPoints = new DefaultExtensionPointRegistry();
+
+ ModelResolverExtensionPoint resolvers = extensionPoints.getExtensionPoint(ModelResolverExtensionPoint.class);
+ resolvers.addResolver(ClassReference.class, ClassReferenceModelResolver.class);
+ FactoryExtensionPoint modelFactories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class);
+ resolver = new ExtensibleModelResolver(null, resolvers, modelFactories);
+ }
+
+ /**
+ * Test ClassReference resolution
+ *
+ */
+ @Test
+ public void testResolveClass() {
+ ClassReference ref = new ClassReference(getClass().getName());
+ ClassReference clazz = resolver.resolveModel(ClassReference.class, ref);
+ assertFalse(clazz.isUnresolved());
+ assertTrue(clazz.getJavaClass() == getClass());
+ }
+
+ /**
+ * Test ClassReference resolution of inexistent class
+ *
+ */
+ @Test
+ public void testUnresolvedClass() {
+ ClassReference ref = new ClassReference("NonExistentClass");
+ ClassReference clazz = resolver.resolveModel(ClassReference.class, ref);
+ assertTrue(clazz.isUnresolved());
+ assertTrue(clazz.getJavaClass() == null);
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/java/impl/ContributionClassLoaderTestCase.java b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/java/impl/ContributionClassLoaderTestCase.java
new file mode 100644
index 0000000000..779c00f71c
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/java/impl/ContributionClassLoaderTestCase.java
@@ -0,0 +1,262 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.java.impl;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.ContributionFactory;
+import org.apache.tuscany.sca.contribution.java.JavaExport;
+import org.apache.tuscany.sca.contribution.java.JavaImport;
+import org.apache.tuscany.sca.contribution.java.JavaImportExportFactory;
+import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+/**
+ * Test ContributionClassLoader.
+ *
+ */
+public class ContributionClassLoaderTestCase {
+
+ private static ContributionFactory contributionFactory;
+ private static JavaImportExportFactory javaImportExportFactory;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ ExtensionPointRegistry extensionPoints = new DefaultExtensionPointRegistry();
+ FactoryExtensionPoint modelFactories = extensionPoints.getExtensionPoint(FactoryExtensionPoint.class);
+ contributionFactory = modelFactories.getFactory(ContributionFactory.class);
+ javaImportExportFactory = modelFactories.getFactory(JavaImportExportFactory.class);
+ }
+
+ private Contribution createContribution(String fileName) throws MalformedURLException {
+ Contribution contrib = contributionFactory.createContribution();
+ File contribDir = new File(fileName);
+ contrib.setLocation(contribDir.toURI().toURL().toString());
+ ClassLoader contextClassLoader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+ public ClassLoader run() {
+ return Thread.currentThread().getContextClassLoader();
+ }
+ });
+ contrib.setClassLoader(new ContributionClassLoader(contrib, contextClassLoader));
+ return contrib;
+ }
+
+
+ @Test
+ public void testClassLoadingFromContribution() throws ClassNotFoundException, MalformedURLException {
+
+ Contribution contribA = createContribution("target/test-classes");
+ Contribution contribB = createContribution("target");
+ Contribution contribC = createContribution("target/test-classes/deployables/sample-calculator.jar");
+
+ // Class present in contribution, also in parent. Class is loaded from parent
+ Class<?> testClassA = contribA.getClassLoader().loadClass(this.getClass().getName());
+ Assert.assertNotNull(testClassA);
+ Assert.assertSame(this.getClass(), testClassA);
+
+ // Class not present in contribution, but present in parent ClassLoader
+ Class<?> testClassB = contribB.getClassLoader().loadClass(this.getClass().getName());
+ Assert.assertNotNull(testClassB);
+ Assert.assertSame(this.getClass(), testClassB);
+
+ // Class present in contribution, but not in parent
+ Class<?> testClassC = contribC.getClassLoader().loadClass("calculator.AddService");
+ Assert.assertNotNull(testClassC);
+
+ // Class not present in contribution or in parent
+ try {
+ contribA.getClassLoader().loadClass("NonExistent");
+
+ Assert.assertTrue("ClassNotFoundException not thrown as expected", false);
+
+ } catch (ClassNotFoundException e) {
+ }
+
+
+
+ }
+
+ @Test
+ public void testResourceLoadingFromContribution() throws ClassNotFoundException, MalformedURLException {
+
+ Contribution contribA = createContribution("target/test-classes");
+ Contribution contribB = createContribution("target");
+ Contribution contribC = createContribution("target/test-classes/deployables/sample-calculator.jar");
+
+ // Resource present in contribution, and in parent
+ URL resA = contribA.getClassLoader().getResource("deployables/sample-calculator.jar");
+ Assert.assertNotNull(resA);
+
+ // Resource not present in contribution, but present in parent ClassLoader
+ URL resB = contribB.getClassLoader().getResource("deployables/sample-calculator.jar");
+ Assert.assertNotNull(resB);
+
+ // Resource present in contribution, but not in parent
+ URL resC = contribC.getClassLoader().getResource("calculator/AddService.class");
+ Assert.assertNotNull(resC);
+
+ // Load Java class as resource from parent
+ String classResName = this.getClass().getName().replaceAll("\\.", "/") + ".class";
+ URL classResA = contribA.getClassLoader().getResource(classResName);
+ Assert.assertNotNull(classResA);
+
+ // Non-existent resource
+ URL res = contribA.getClassLoader().getResource("deployables/NonExistent");
+ Assert.assertNull(res);
+
+ }
+
+ private static String getPackageName(Class<?> cls) {
+ String name = cls.getName();
+ int index = name.lastIndexOf('.');
+ return index == -1 ? "" : name.substring(0, index);
+ }
+
+ @Test
+ public void testClassLoadingFromImportedContribution() throws ClassNotFoundException, MalformedURLException {
+
+ Contribution contribA = createContribution("target/test-classes");
+ Contribution contribB = createContribution("target");
+ Contribution contribC = createContribution("target/test-classes/deployables/sample-calculator.jar");
+ ArrayList<Contribution> exportContribList = new ArrayList<Contribution>();
+ exportContribList.add(contribA);
+ exportContribList.add(contribC);
+
+ JavaImport import_ = javaImportExportFactory.createJavaImport();
+ import_.setPackage(getPackageName(getClass()));
+ import_.setModelResolver(new JavaImportModelResolver(exportContribList, null));
+ contribB.getImports().add(import_);
+ import_ = javaImportExportFactory.createJavaImport();
+ import_.setPackage("calculator");
+ import_.setModelResolver(new JavaImportModelResolver(exportContribList, null));
+ contribB.getImports().add(import_);
+
+ JavaExport export = javaImportExportFactory.createJavaExport();
+ export.setPackage(getPackageName(getClass()));
+ contribA.getExports().add(export);
+ export = javaImportExportFactory.createJavaExport();
+ export.setPackage("calculator");
+ contribC.getExports().add(export);
+
+ // Load class from parent, class is also present in imported contribution. Class should
+ // be loaded from parent
+ Class<?> testClassB = contribB.getClassLoader().loadClass(this.getClass().getName());
+ Assert.assertNotNull(testClassB);
+ Assert.assertSame(this.getClass(), testClassB);
+
+ // Load class from parent, class is also present in parent. Class should be loaded
+ // from parent.
+ Class<?> testClassA = contribA.getClassLoader().loadClass(this.getClass().getName());
+ Assert.assertNotNull(testClassA);
+ Assert.assertSame(this.getClass(), testClassA);
+
+ // Imported class should be the same as the one loaded by the exporting contribution
+ Assert.assertSame(testClassA, testClassB);
+
+ // Load class from imported contribution, class is not present in parent
+ Class<?> testClassB1 = contribB.getClassLoader().loadClass("calculator.AddService");
+ Assert.assertNotNull(testClassB1);
+
+ // Imported class should be the same as the one loaded by the exporting contribution
+ Class<?> testClassC = contribC.getClassLoader().loadClass("calculator.AddService");
+ Assert.assertNotNull(testClassC);
+ Assert.assertSame(testClassC, testClassB1);
+
+
+ // Try to load class from package which is not explicitly imported - should throw ClassNotFoundException
+ try {
+ contribA.getClassLoader().loadClass("calculator.AddService");
+
+ Assert.assertTrue("ClassNotFoundException not thrown as expected", false);
+
+ } catch (ClassNotFoundException e) {
+ }
+
+ // Try to load non-existent class from imported package - should throw ClassNotFoundException
+ try {
+ contribB.getClassLoader().loadClass(getPackageName(getClass()) + ".NonExistentClass");
+
+ Assert.assertTrue("ClassNotFoundException not thrown as expected", false);
+
+ } catch (ClassNotFoundException e) {
+ }
+
+ }
+
+ @Test
+ public void testResourceLoadingFromImportedContribution() throws ClassNotFoundException, MalformedURLException {
+
+ Contribution contribA = createContribution("target/test-classes");
+ Contribution contribB = createContribution("target");
+ Contribution contribC = createContribution("target/test-classes/deployables/sample-calculator.jar");
+
+ ArrayList<Contribution> exportContribList = new ArrayList<Contribution>();
+ exportContribList.add(contribA);
+ exportContribList.add(contribC);
+
+ JavaImport import_ = javaImportExportFactory.createJavaImport();
+ import_.setPackage(getPackageName(getClass()));
+ import_.setModelResolver(new JavaImportModelResolver(exportContribList, null));
+ contribB.getImports().add(import_);
+ JavaImport import1_ = javaImportExportFactory.createJavaImport();
+ import1_.setPackage("calculator");
+ import1_.setModelResolver(new JavaImportModelResolver(exportContribList, null));
+ contribB.getImports().add(import1_);
+
+ JavaExport export = javaImportExportFactory.createJavaExport();
+ export.setPackage(getPackageName(getClass()));
+ contribA.getExports().add(export);
+ JavaExport export1 = javaImportExportFactory.createJavaExport();
+ export1.setPackage("calculator");
+ contribC.getExports().add(export1);
+
+
+ // Load resource from parent
+ URL resB = contribB.getClassLoader().getResource("deployables/sample-calculator.jar");
+ Assert.assertNotNull(resB);
+
+ // Load Java class as resource from imported contribution with JavaImport
+ String classResName = this.getClass().getName().replaceAll("\\.", "/") + ".class";
+ URL classResB = contribB.getClassLoader().getResource(classResName);
+ Assert.assertNotNull(classResB);
+
+ // Load Java class as resource from imported contribution with JavaImport
+ URL classResB1 = contribB.getClassLoader().getResource("calculator/AddService.class");
+ Assert.assertNotNull(classResB1);
+
+ // Try to load resource not explicitly imported by contribution
+ URL classResA1 = contribA.getClassLoader().getResource("calculator/AddService.class");
+ Assert.assertNull(classResA1);
+
+
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportProcessorTestCase.java b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportProcessorTestCase.java
new file mode 100644
index 0000000000..c6bd430e96
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportProcessorTestCase.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.java.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.StringReader;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.sca.contribution.java.JavaExport;
+import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint;
+import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.monitor.DefaultMonitorFactory;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.MonitorFactory;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Test JavaExportProcessorTestCase
+ *
+ * @version $Rev$ $Date$
+ */
+public class JavaExportProcessorTestCase {
+
+ private static final String VALID_XML =
+ "<?xml version=\"1.0\" encoding=\"ASCII\"?>"
+ + "<export.java xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200903\" xmlns:ns=\"http://ns\" package=\"org.apache.tuscany.sca.contribution.java\"/>";
+
+ private static final String INVALID_XML =
+ "<?xml version=\"1.0\" encoding=\"ASCII\"?>"
+ + "<export.java xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200903\"/>";
+
+ private static XMLInputFactory inputFactory;
+ private static StAXArtifactProcessor<Object> staxProcessor;
+ private static Monitor monitor;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ ExtensionPointRegistry extensionPoints = new DefaultExtensionPointRegistry();
+ inputFactory = XMLInputFactory.newInstance();
+ // Create a monitor
+ UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class);
+ MonitorFactory monitorFactory = new DefaultMonitorFactory();
+ if (monitorFactory != null) {
+ monitor = monitorFactory.createMonitor();
+ utilities.addUtility(monitorFactory);
+ }
+ StAXArtifactProcessorExtensionPoint staxProcessors = extensionPoints.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class);
+ staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, inputFactory, null, null);
+ }
+
+ /**
+ * Test loading a valid export element from a contribution metadata stream
+ * @throws Exception
+ */
+ @Test
+ public void testLoad() throws Exception {
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(VALID_XML));
+ JavaExport javaExport = (JavaExport)staxProcessor.read(reader);
+ Assert.assertEquals("org.apache.tuscany.sca.contribution.java", javaExport.getPackage());
+ }
+
+ /**
+ * Test loading an INVALID export element from a contribution metadata stream
+ * @throws Exception
+ */
+ @Test
+ public void testLoadInvalid() throws Exception {
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(INVALID_XML));
+ /*try {
+ staxProcessor.read(reader);
+ fail("readerException should have been thrown");
+ } catch (ContributionReadException e) {
+ assertTrue(true);
+ }*/
+ staxProcessor.read(reader);
+ Problem problem = monitor.getLastProblem();
+ assertNotNull(problem);
+ assertEquals("AttributePackageMissing", problem.getMessageId());
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportProcessorTestCase.java b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportProcessorTestCase.java
new file mode 100644
index 0000000000..7bcafd6c48
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportProcessorTestCase.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.java.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.StringReader;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.sca.contribution.java.JavaImport;
+import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint;
+import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.monitor.DefaultMonitorFactory;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.MonitorFactory;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Test JavaImportProcessorTestCase
+ *
+ * @version $Rev$ $Date$
+ */
+public class JavaImportProcessorTestCase {
+
+ private static final String VALID_XML =
+ "<?xml version=\"1.0\" encoding=\"ASCII\"?>"
+ + "<import.java xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200903\" xmlns:ns=\"http://ns\" package=\"org.apache.tuscany.sca.contribution.java\" location=\"sca://contributions/001\"/>";
+
+ private static final String INVALID_XML =
+ "<?xml version=\"1.0\" encoding=\"ASCII\"?>"
+ + "<import.java xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200903\" xmlns:ns=\"http://ns\" location=\"sca://contributions/001\"/>";
+
+ private static XMLInputFactory inputFactory;
+ private static StAXArtifactProcessor<Object> staxProcessor;
+ private static Monitor monitor;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ ExtensionPointRegistry extensionPoints = new DefaultExtensionPointRegistry();
+ inputFactory = XMLInputFactory.newInstance();
+ // Create a monitor
+ UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class);
+ MonitorFactory monitorFactory = new DefaultMonitorFactory();
+ if (monitorFactory != null) {
+ monitor = monitorFactory.createMonitor();
+ utilities.addUtility(monitorFactory);
+ }
+ StAXArtifactProcessorExtensionPoint staxProcessors = extensionPoints.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class);
+ staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, inputFactory, null, null);
+ }
+
+ /**
+ * Test loading a valid import element from a contribution metadata stream
+ * @throws Exception
+ */
+ @Test
+ public void testLoad() throws Exception {
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(VALID_XML));
+ JavaImport javaImport = (JavaImport)staxProcessor.read(reader);
+
+ assertEquals("org.apache.tuscany.sca.contribution.java", javaImport.getPackage());
+ assertEquals("sca://contributions/001", javaImport.getLocation());
+ }
+
+ /**
+ * Test loading a INVALID import element from a contribution metadata stream
+ * @throws Exception
+ */
+ @Test
+ public void testLoadInvalid() throws Exception {
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(INVALID_XML));
+ /*try {
+ staxProcessor.read(reader);
+ fail("readerException should have been thrown");
+ } catch (ContributionReadException e) {
+ assertTrue(true);
+ }*/
+ staxProcessor.read(reader);
+ Problem problem = monitor.getLastProblem();
+ assertNotNull(problem);
+ assertEquals("AttributePackageMissing", problem.getMessageId());
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportProcessorTestCase.java b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportProcessorTestCase.java
new file mode 100644
index 0000000000..a1c5189767
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportProcessorTestCase.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.namespace.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.StringReader;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.sca.contribution.namespace.NamespaceExport;
+import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint;
+import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.monitor.DefaultMonitorFactory;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.MonitorFactory;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Test NamespaceExportProcessorTestCase
+ *
+ * @version $Rev$ $Date$
+ */
+public class NamespaceExportProcessorTestCase {
+
+ private static final String VALID_XML =
+ "<?xml version=\"1.0\" encoding=\"ASCII\"?>"
+ + "<export xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200903\" xmlns:ns=\"http://ns\""
+ + " ns:ext=\"extended\" namespace=\"http://foo\">"
+ + "<ns:foo/></export>";
+
+ private static final String INVALID_XML =
+ "<?xml version=\"1.0\" encoding=\"ASCII\"?>" + "<export xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200903\" xmlns:ns=\"http://ns\"/>";
+
+ private static XMLInputFactory inputFactory;
+ private static StAXArtifactProcessor<Object> staxProcessor;
+ private static Monitor monitor;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ ExtensionPointRegistry extensionPoints = new DefaultExtensionPointRegistry();
+ inputFactory = XMLInputFactory.newInstance();
+ // Create a monitor
+ UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class);
+ MonitorFactory monitorFactory = new DefaultMonitorFactory();
+ if (monitorFactory != null) {
+ monitor = monitorFactory.createMonitor();
+ utilities.addUtility(monitorFactory);
+ }
+ StAXArtifactProcessorExtensionPoint staxProcessors =
+ extensionPoints.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class);
+ staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, inputFactory, null, monitor);
+ }
+
+ /**
+ * Test loading a valid export element from a contribution metadata stream
+ * @throws Exception
+ */
+ @Test
+ public void testLoad() throws Exception {
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(VALID_XML));
+ NamespaceExport namespaceExport = (NamespaceExport)staxProcessor.read(reader);
+ assertEquals("http://foo", namespaceExport.getNamespace());
+ assertEquals(1, namespaceExport.getAttributeExtensions().size());
+ assertEquals(1, namespaceExport.getExtensions().size());
+ }
+
+ /**
+ * Test loading an INVALID export element from a contribution metadata stream
+ * @throws Exception
+ */
+ @Test
+ public void testLoadInvalid() throws Exception {
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(INVALID_XML));
+ /*try {
+ staxProcessor.read(reader);
+ fail("readerException should have been thrown");
+ } catch (ContributionReadException e) {
+ assertTrue(true);
+ }*/
+ staxProcessor.read(reader);
+ Problem problem = monitor.getLastProblem();
+ assertNotNull(problem);
+ assertEquals("AttributeNameSpaceMissing", problem.getMessageId());
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportProcessorTestCase.java b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportProcessorTestCase.java
new file mode 100644
index 0000000000..676437042d
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportProcessorTestCase.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.namespace.impl;
+
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.StringReader;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.sca.contribution.namespace.NamespaceImport;
+import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint;
+import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.monitor.DefaultMonitorFactory;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.MonitorFactory;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Test NamespaceImportProcessorTestCase
+ *
+ * @version $Rev$ $Date$
+ */
+public class NamespaceImportProcessorTestCase {
+
+ private static final String VALID_XML =
+ "<?xml version=\"1.0\" encoding=\"ASCII\"?>"
+ + "<import xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200903\" xmlns:ns=\"http://ns\""
+ + " namespace=\"http://foo\" location=\"sca://contributions/001\" ns:ext=\"extended\">"
+ + "<ns:foo/></import>";
+
+ private static final String INVALID_XML =
+ "<?xml version=\"1.0\" encoding=\"ASCII\"?>"
+ + "<import xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200903\" xmlns:ns=\"http://ns\" location=\"sca://contributions/001\"/>";
+
+ private static XMLInputFactory inputFactory;
+ private static StAXArtifactProcessor<Object> staxProcessor;
+ private static Monitor monitor;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ ExtensionPointRegistry extensionPoints = new DefaultExtensionPointRegistry();
+ inputFactory = XMLInputFactory.newInstance();
+ // Create a monitor
+ UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class);
+ MonitorFactory monitorFactory = new DefaultMonitorFactory();
+ if (monitorFactory != null) {
+ monitor = monitorFactory.createMonitor();
+ utilities.addUtility(monitorFactory);
+ }
+ StAXArtifactProcessorExtensionPoint staxProcessors = extensionPoints.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class);
+ staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, inputFactory, null, monitor);
+ }
+
+ /**
+ * Test loading a valid import element from a contribution metadata stream
+ * @throws Exception
+ */
+ @Test
+ public void testLoad() throws Exception {
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(VALID_XML));
+ NamespaceImport namespaceImport = (NamespaceImport)staxProcessor.read(reader);
+
+ assertEquals("http://foo", namespaceImport.getNamespace());
+ assertEquals("sca://contributions/001", namespaceImport.getLocation());
+ assertEquals(1, namespaceImport.getAttributeExtensions().size());
+ assertEquals(1, namespaceImport.getExtensions().size());
+ }
+
+ /**
+ * Test loading a INVALID import element from a contribution metadata stream
+ * @throws Exception
+ */
+ @Test
+ public void testLoadInvalid() throws Exception {
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(INVALID_XML));
+ /*try {
+ staxProcessor.read(reader);
+ fail("readerException should have been thrown");
+ } catch (ContributionReadException e) {
+ assertTrue(true);
+ }*/
+ staxProcessor.read(reader);
+ Problem problem = monitor.getLastProblem();
+ assertNotNull(problem);
+ assertEquals("AttributeNameSpaceMissing", problem.getMessageId());
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/processor/URLartifactProcessorExtensionPointTestCase.java b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/processor/URLartifactProcessorExtensionPointTestCase.java
new file mode 100644
index 0000000000..3a18e2b987
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/processor/URLartifactProcessorExtensionPointTestCase.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.processor;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.net.URI;
+import java.net.URL;
+
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * URL Artifact Processor Extension Point test case
+ * Verifies the right registration and lookup for processors that handle filename and file types
+ *
+ * @version $Rev$ $Date$
+ */
+public class URLartifactProcessorExtensionPointTestCase {
+
+ private static URLArtifactProcessorExtensionPoint artifactProcessors;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ ExtensionPointRegistry extensionPoints = new DefaultExtensionPointRegistry();
+ artifactProcessors = new DefaultURLArtifactProcessorExtensionPoint(extensionPoints);
+ artifactProcessors.addArtifactProcessor(new FileTypeArtifactProcessor());
+ artifactProcessors.addArtifactProcessor(new FileNameArtifactProcessor());
+ }
+
+ @Test
+ public final void testFileTypeProcessor() {
+ assertNotNull(artifactProcessors.getProcessor("dir1/file1.m1"));
+ assertNotNull(artifactProcessors.getProcessor("file1.m1"));
+ }
+
+ @Test
+ public final void testFileNameProcessor() {
+ assertNotNull(artifactProcessors.getProcessor("file.m2"));
+ assertNotNull(artifactProcessors.getProcessor("dir1/file.m2"));
+ assertNull(artifactProcessors.getProcessor("onefile.m2"));
+ }
+
+ /**
+ * Internal mock classes
+ *
+ */
+
+ private class M1 {
+ }
+
+ private class M2 {
+ }
+
+ private static class FileTypeArtifactProcessor implements URLArtifactProcessor<M1> {
+ public FileTypeArtifactProcessor() {
+ }
+
+ public M1 read(URL contributionURL, URI uri, URL url) throws ContributionReadException {
+ return null;
+ }
+
+ public void resolve(M1 m1, ModelResolver resolver) throws ContributionResolveException {
+ }
+
+ public String getArtifactType() {
+ return ".m1";
+ }
+
+ public Class<M1> getModelType() {
+ return M1.class;
+ }
+ }
+
+ private static class FileNameArtifactProcessor implements URLArtifactProcessor<M2> {
+ public FileNameArtifactProcessor() {
+ }
+
+ public M2 read(URL contributionURL, URI uri, URL url) throws ContributionReadException {
+ return null;
+ }
+
+ public void resolve(M2 m2, ModelResolver resolver) throws ContributionResolveException {
+ }
+
+ public String getArtifactType() {
+ return "file.m2";
+ }
+
+ public Class<M2> getModelType() {
+ return M2.class;
+ }
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverTestCase.java b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverTestCase.java
new file mode 100644
index 0000000000..b778167217
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverTestCase.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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 static org.junit.Assert.assertTrue;
+
+import org.apache.tuscany.sca.contribution.Artifact;
+import org.apache.tuscany.sca.contribution.ContributionFactory;
+import org.apache.tuscany.sca.contribution.DefaultContributionFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test the default model resolver implementation.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultModelResolverTestCase {
+
+ private ModelResolver resolver;
+ private ContributionFactory factory;
+
+ @Before
+ public void setUp() throws Exception {
+ resolver = new DefaultModelResolver();
+ factory = new DefaultContributionFactory();
+ }
+
+ @Test
+ public void testResolved() {
+ Model a = new Model("a");
+ resolver.addModel(a);
+ Model x = new Model("a");
+ x = resolver.resolveModel(Model.class, x);
+ assertTrue(x == a);
+ }
+
+ @Test
+ public void testUnresolved() {
+ Model x = new Model("a");
+ Model y = resolver.resolveModel(Model.class, x);
+ assertTrue(x == y);
+ }
+
+ @Test
+ public void testResolvedArtifact() {
+ Artifact artifact = factory.createArtifact();
+ artifact.setURI("foo/bar");
+ resolver.addModel(artifact);
+ Artifact x = factory.createArtifact();
+ x.setURI("foo/bar");
+ x = resolver.resolveModel(Artifact.class, x);
+ assertTrue(x == artifact);
+ }
+
+ class Model {
+ private String name;
+
+ Model(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return name.equals(((Model)obj).name);
+ }
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolverTestCase.java b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolverTestCase.java
new file mode 100644
index 0000000000..2422c8fb94
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolverTestCase.java
@@ -0,0 +1,134 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* 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 static org.junit.Assert.assertTrue;
+
+import org.apache.tuscany.sca.contribution.Artifact;
+import org.apache.tuscany.sca.contribution.ContributionFactory;
+import org.apache.tuscany.sca.contribution.DefaultContributionFactory;
+import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry;
+import org.apache.tuscany.sca.core.DefaultFactoryExtensionPoint;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test DefaultArtifactResolver.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExtensibleModelResolverTestCase {
+ private ExtensibleModelResolver resolver;
+
+ private ContributionFactory factory;
+
+ @Before
+ public void setUp() throws Exception {
+
+ ModelResolverExtensionPoint resolvers = new DefaultModelResolverExtensionPoint();
+ resolvers.addResolver(Model.class, TestModelResolver.class);
+
+ FactoryExtensionPoint factories = new DefaultFactoryExtensionPoint(new DefaultExtensionPointRegistry());
+
+ resolver = new ExtensibleModelResolver(null, resolvers, factories, null);
+
+ factory = new DefaultContributionFactory();
+ }
+
+ @Test
+ public void testResolvedDefault() {
+ OtherModel a = new OtherModel("a");
+ resolver.addModel(a);
+ OtherModel x = new OtherModel("a");
+ x = resolver.resolveModel(OtherModel.class, x);
+ assertTrue(x == a);
+ }
+
+ @Test
+ public void testResolvedRegisteredClass() {
+ Model a = new Model("a");
+ resolver.addModel(a);
+ Model x = new Model("a");
+ x = resolver.resolveModel(Model.class, x);
+ assertTrue(x == a);
+ }
+
+ @Test
+ public void testUnresolvedDefault() {
+ OtherModel x = new OtherModel("a");
+ OtherModel y = resolver.resolveModel(OtherModel.class, x);
+ assertTrue(x == y);
+ }
+
+ @Test
+ public void testUnresolved() {
+ Model x = new Model("a");
+ Model y = resolver.resolveModel(Model.class, x);
+ assertTrue(x == y);
+ }
+
+ @Test
+ public void testResolvedArtifact() {
+ Artifact artifact = factory.createArtifact();
+ artifact.setURI("foo/bar");
+ resolver.addModel(artifact);
+ Artifact x = factory.createArtifact();
+ x.setURI("foo/bar");
+ x = resolver.resolveModel(Artifact.class, x);
+ assertTrue(x == artifact);
+ }
+
+ private class Model {
+ private String name;
+
+ Model(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return name.equals(((Model)obj).name);
+ }
+ }
+
+ private class OtherModel {
+ private String name;
+
+ OtherModel(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return name.equals(((OtherModel)obj).name);
+ }
+ }
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/TestModelResolver.java b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/TestModelResolver.java
new file mode 100644
index 0000000000..cd586d3b2c
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/TestModelResolver.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.resolver;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+
+/**
+ * A test implementation of a model resolver, based on a map.
+ *
+ * @version $Rev$ $Date$
+ */
+public class TestModelResolver implements ModelResolver {
+
+ private Map<Object, Object> map = new HashMap<Object, Object>();
+
+ public TestModelResolver(Contribution contribution, FactoryExtensionPoint modelFactories) {
+ }
+
+ 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);
+ }
+ // 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/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataProcessorTestCase.java b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataProcessorTestCase.java
new file mode 100644
index 0000000000..d1c18beee5
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataProcessorTestCase.java
@@ -0,0 +1,149 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.xml;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.sca.contribution.ContributionMetadata;
+import org.apache.tuscany.sca.contribution.processor.ExtensibleStAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint;
+import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.monitor.DefaultMonitorFactory;
+import org.apache.tuscany.sca.monitor.Monitor;
+import org.apache.tuscany.sca.monitor.MonitorFactory;
+import org.apache.tuscany.sca.monitor.Problem;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Test the contribution metadata processor.
+ *
+ * @version $Rev$ $Date$
+ */
+
+public class ContributionMetadataProcessorTestCase {
+
+ private static final String VALID_XML =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<contribution xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200903\""
+ + " xmlns:ns=\"http://ns\" ns:foo=\"extended\">"
+ + "<deployable composite=\"ns:Composite1\"/>"
+ + "<deployable composite=\"ns:Composite2\"/>"
+ + "<ns:bar x=\"1\"/>"
+ + "</contribution>";
+
+ private static final String INVALID_XML =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<contribution xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200903\" xmlns:ns=\"http://ns\">"
+ + "<deployable composite=\"ns:Composite1\"/>"
+ + "<deployable/>"
+ + "</contribution>";
+
+ private static XMLInputFactory inputFactory;
+ private static XMLOutputFactory outputFactory;
+ private static StAXArtifactProcessor<Object> staxProcessor;
+ private static Monitor monitor;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ ExtensionPointRegistry extensionPoints = new DefaultExtensionPointRegistry();
+
+ inputFactory = XMLInputFactory.newInstance();
+ outputFactory = XMLOutputFactory.newInstance();
+
+ // Create a monitor
+ UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class);
+ MonitorFactory monitorFactory = new DefaultMonitorFactory();
+ if (monitorFactory != null) {
+ monitor = monitorFactory.createMonitor();
+ utilities.addUtility(monitorFactory);
+ }
+ StAXArtifactProcessorExtensionPoint staxProcessors =
+ extensionPoints.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class);
+ staxProcessor = new ExtensibleStAXArtifactProcessor(staxProcessors, inputFactory, outputFactory, null);
+ }
+
+ @Test
+ public void testRead() throws Exception {
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(VALID_XML));
+ ContributionMetadata contribution = (ContributionMetadata)staxProcessor.read(reader);
+ assertNotNull(contribution);
+ assertEquals(2, contribution.getDeployables().size());
+ assertEquals(1, contribution.getAttributeExtensions().size());
+ assertEquals(1, contribution.getExtensions().size());
+ }
+
+ @Test
+ public void testReadInvalid() throws Exception {
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(INVALID_XML));
+ /*try {
+ staxProcessor.read(reader);
+ fail("InvalidException should have been thrown");
+ } catch (ContributionReadException e) {
+ assertTrue(true);
+ }*/
+ staxProcessor.read(reader);
+ Problem problem = monitor.getLastProblem();
+ assertNotNull(problem);
+ assertEquals("AttributeCompositeMissing", problem.getMessageId());
+ }
+
+ @Test
+ public void testWrite() throws Exception {
+ XMLStreamReader reader = inputFactory.createXMLStreamReader(new StringReader(VALID_XML));
+ ContributionMetadata contribution = (ContributionMetadata)staxProcessor.read(reader);
+
+ validateContribution(contribution);
+
+ //write the contribution metadata contents
+ StringWriter stringWriter = new StringWriter();
+ XMLStreamWriter writer = outputFactory.createXMLStreamWriter(stringWriter);
+ staxProcessor.write(contribution, writer);
+ stringWriter.close();
+
+ reader = inputFactory.createXMLStreamReader(new StringReader(stringWriter.toString()));
+ contribution = (ContributionMetadata)staxProcessor.read(reader);
+
+ validateContribution(contribution);
+ }
+
+ private void validateContribution(ContributionMetadata contribution) {
+ QName deployable;
+
+ assertNotNull(contribution);
+ assertEquals(2, contribution.getDeployables().size());
+ deployable = new QName("http://ns", "Composite1");
+ assertEquals(deployable, contribution.getDeployables().get(0).getName());
+ deployable = new QName("http://ns", "Composite2");
+ assertEquals(deployable, contribution.getDeployables().get(1).getName());
+ }
+
+}
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/test/resources/deployables/sample-calculator.jar b/branches/sca-java-2.0-M3/modules/contribution/src/test/resources/deployables/sample-calculator.jar
new file mode 100644
index 0000000000..0ca3a1b781
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/test/resources/deployables/sample-calculator.jar
Binary files differ
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/test/resources/repository/sample-calculator.jar b/branches/sca-java-2.0-M3/modules/contribution/src/test/resources/repository/sample-calculator.jar
new file mode 100644
index 0000000000..9c46c679d2
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/test/resources/repository/sample-calculator.jar
Binary files differ
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/test/resources/test.composite b/branches/sca-java-2.0-M3/modules/contribution/src/test/resources/test.composite
new file mode 100644
index 0000000000..1e09549194
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/test/resources/test.composite
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<composite>
+ This file just needs to exist
+</composite> \ No newline at end of file
diff --git a/branches/sca-java-2.0-M3/modules/contribution/src/test/resources/test.ext b/branches/sca-java-2.0-M3/modules/contribution/src/test/resources/test.ext
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/branches/sca-java-2.0-M3/modules/contribution/src/test/resources/test.ext