summaryrefslogtreecommitdiffstats
path: root/java/sca/modules/contribution
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--java/sca/modules/contribution-java/LICENSE205
-rw-r--r--java/sca/modules/contribution-java/META-INF/MANIFEST.MF28
-rw-r--r--java/sca/modules/contribution-java/NOTICE6
-rw-r--r--java/sca/modules/contribution-java/pom.xml58
-rw-r--r--java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/DefaultJavaImportExportFactory.java30
-rw-r--r--java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/JavaExport.java43
-rw-r--r--java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImport.java58
-rw-r--r--java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImportExportFactory.java42
-rw-r--r--java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ClassLoaderModelResolver.java161
-rw-r--r--java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ClassReferenceModelResolver.java158
-rw-r--r--java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ContributionClassLoader.java385
-rw-r--r--java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportImpl.java58
-rw-r--r--java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportModelResolver.java76
-rw-r--r--java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportProcessor.java142
-rw-r--r--java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportExportFactoryImpl.java41
-rw-r--r--java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportImpl.java110
-rw-r--r--java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportModelResolver.java62
-rw-r--r--java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportProcessor.java147
-rw-r--r--java/sca/modules/contribution-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.java.JavaImportExportFactory18
-rw-r--r--java/sca/modules/contribution-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor19
-rw-r--r--java/sca/modules/contribution-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver18
-rw-r--r--java/sca/modules/contribution-java/src/main/resources/contribution-java-validation-messages.properties22
-rw-r--r--java/sca/modules/contribution-java/src/test/java/org/apache/tuscany/sca/contribution/java/impl/ClassReferenceArtifactResolverTestCase.java75
-rw-r--r--java/sca/modules/contribution-java/src/test/java/org/apache/tuscany/sca/contribution/java/impl/ContributionClassLoaderTestCase.java262
-rw-r--r--java/sca/modules/contribution-java/src/test/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportProcessorTestCase.java109
-rw-r--r--java/sca/modules/contribution-java/src/test/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportProcessorTestCase.java109
-rw-r--r--java/sca/modules/contribution-java/src/test/resources/deployables/sample-calculator.jarbin0 -> 26901 bytes
-rw-r--r--java/sca/modules/contribution-namespace/LICENSE205
-rw-r--r--java/sca/modules/contribution-namespace/META-INF/MANIFEST.MF25
-rw-r--r--java/sca/modules/contribution-namespace/NOTICE6
-rw-r--r--java/sca/modules/contribution-namespace/pom.xml58
-rw-r--r--java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/DefaultNamespaceImportExportFactory.java30
-rw-r--r--java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceExport.java46
-rw-r--r--java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImport.java59
-rw-r--r--java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImportExportFactory.java42
-rw-r--r--java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportImpl.java54
-rw-r--r--java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportModelResolver.java54
-rw-r--r--java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportProcessor.java141
-rw-r--r--java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportExportFactoryImpl.java41
-rw-r--r--java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportImpl.java92
-rw-r--r--java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportProcessor.java147
-rw-r--r--java/sca/modules/contribution-namespace/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.namespace.NamespaceImportExportFactory18
-rw-r--r--java/sca/modules/contribution-namespace/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor19
-rw-r--r--java/sca/modules/contribution-namespace/src/main/resources/contribution-namespace-validation-messages.properties22
-rw-r--r--java/sca/modules/contribution-namespace/src/test/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportProcessorTestCase.java106
-rw-r--r--java/sca/modules/contribution-namespace/src/test/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportProcessorTestCase.java111
-rw-r--r--java/sca/modules/contribution-osgi/LICENSE205
-rw-r--r--java/sca/modules/contribution-osgi/NOTICE6
-rw-r--r--java/sca/modules/contribution-osgi/pom.xml78
-rw-r--r--java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/BundleReference.java161
-rw-r--r--java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleContributionProcessor.java161
-rw-r--r--java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleProcessor.java141
-rw-r--r--java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleReferenceModelResolver.java154
-rw-r--r--java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiClassReferenceModelResolver.java137
-rw-r--r--java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiImportExportListener.java215
-rw-r--r--java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiModelResolverImpl.java119
-rw-r--r--java/sca/modules/contribution-osgi/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.PackageProcessor18
-rw-r--r--java/sca/modules/contribution-osgi/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver18
-rw-r--r--java/sca/modules/contribution-osgi/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.service.ContributionListener18
-rw-r--r--java/sca/modules/contribution-resource/META-INF/MANIFEST.MF26
-rw-r--r--java/sca/modules/contribution-resource/pom.xml58
-rw-r--r--java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/ResourceExport.java46
-rw-r--r--java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/ResourceImport.java59
-rw-r--r--java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/ResourceImportExportFactory.java42
-rw-r--r--java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ArtifactModelResolver.java86
-rw-r--r--java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceExportImpl.java58
-rw-r--r--java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceExportModelResolver.java65
-rw-r--r--java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceExportProcessor.java141
-rw-r--r--java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceImportExportFactoryImpl.java41
-rw-r--r--java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceImportImpl.java107
-rw-r--r--java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceImportProcessor.java147
-rw-r--r--java/sca/modules/contribution-resource/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor19
-rw-r--r--java/sca/modules/contribution-resource/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver18
-rw-r--r--java/sca/modules/contribution-resource/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resource.ResourceImportExportFactory18
-rw-r--r--java/sca/modules/contribution-resource/src/main/resources/contribution-resource-validation-messages.properties22
-rw-r--r--java/sca/modules/contribution-resource/src/test/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceExportProcessorTestCase.java106
-rw-r--r--java/sca/modules/contribution-resource/src/test/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceImportProcessorTestCase.java107
-rw-r--r--java/sca/modules/contribution-xml/LICENSE205
-rw-r--r--java/sca/modules/contribution-xml/META-INF/MANIFEST.MF34
-rw-r--r--java/sca/modules/contribution-xml/NOTICE6
-rw-r--r--java/sca/modules/contribution-xml/pom.xml52
-rw-r--r--java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyAttributeProcessor.java68
-rw-r--r--java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyElementProcessor.java309
-rw-r--r--java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionGeneratedMetadataDocumentProcessor.java50
-rw-r--r--java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataDocumentProcessor.java130
-rw-r--r--java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataProcessor.java216
-rw-r--r--java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionModelResolver.java72
-rw-r--r--java/sca/modules/contribution-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor20
-rw-r--r--java/sca/modules/contribution-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor20
-rw-r--r--java/sca/modules/contribution-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver18
-rw-r--r--java/sca/modules/contribution-xml/src/main/resources/contribution-xml-validation-messages.properties23
-rw-r--r--java/sca/modules/contribution-xml/src/test/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataProcessorTestCase.java145
-rw-r--r--java/sca/modules/contribution/LICENSE205
-rw-r--r--java/sca/modules/contribution/META-INF/MANIFEST.MF46
-rw-r--r--java/sca/modules/contribution/NOTICE6
-rw-r--r--java/sca/modules/contribution/pom.xml51
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java86
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Constants.java30
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.java40
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java123
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java73
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionMetadata.java55
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultContributionFactory.java32
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultExport.java30
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultImport.java30
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DeployedArtifact.java29
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java47
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java56
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/PackageType.java42
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ArtifactImpl.java103
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionFactoryImpl.java67
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionImpl.java159
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionMetadataImpl.java64
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultExportImpl.java45
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultImportImpl.java55
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java47
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessorExtensionPoint.java58
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java539
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionException.java45
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionReadException.java95
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionResolveException.java42
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionRuntimeException.java44
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionWriteException.java62
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.java66
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java384
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXAttributeProcessorExtensionPoint.java323
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java239
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java325
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidationSchemaExtensionPoint.java95
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java266
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXAttributeProcessor.java243
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java139
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java59
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java29
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessor.java61
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessorExtensionPoint.java29
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java50
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java29
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnrecognizedElementException.java48
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedContentTypeException.java43
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedPackageTypeException.java40
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLInputFactory.java30
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java387
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidationSchemaExtensionPoint.java52
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java107
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultDelegatingModelResolver.java68
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java80
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportModelResolver.java69
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolver.java66
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.java114
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java200
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.java69
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java52
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResolverExtension.java45
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResourceReference.java103
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java67
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java50
-rw-r--r--java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java125
-rw-r--r--java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ContributionFactory18
-rw-r--r--java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ContributionPostProcessorExtensionPoint18
-rw-r--r--java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint18
-rw-r--r--java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXAttributeProcessorExtensionPoint18
-rw-r--r--java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint18
-rw-r--r--java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidatingXMLInputFactory17
-rw-r--r--java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchemaExtensionPoint18
-rw-r--r--java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint18
-rw-r--r--java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.scanner.ContributionScannerExtensionPoint18
-rw-r--r--java/sca/modules/contribution/src/main/resources/contribution-validation-messages.properties34
-rw-r--r--java/sca/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/processor/URLartifactProcessorExtensionPointTestCase.java113
-rw-r--r--java/sca/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverTestCase.java91
-rw-r--r--java/sca/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolverTestCase.java134
-rw-r--r--java/sca/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/TestModelResolver.java58
-rw-r--r--java/sca/modules/contribution/src/test/resources/deployables/sample-calculator.jarbin0 -> 26901 bytes
-rw-r--r--java/sca/modules/contribution/src/test/resources/repository/sample-calculator.jarbin0 -> 29164 bytes
-rw-r--r--java/sca/modules/contribution/src/test/resources/test.composite22
-rw-r--r--java/sca/modules/contribution/src/test/resources/test.ext0
176 files changed, 14854 insertions, 0 deletions
diff --git a/java/sca/modules/contribution-java/LICENSE b/java/sca/modules/contribution-java/LICENSE
new file mode 100644
index 0000000000..8aa906c321
--- /dev/null
+++ b/java/sca/modules/contribution-java/LICENSE
@@ -0,0 +1,205 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+
diff --git a/java/sca/modules/contribution-java/META-INF/MANIFEST.MF b/java/sca/modules/contribution-java/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..7d338e5322
--- /dev/null
+++ b/java/sca/modules/contribution-java/META-INF/MANIFEST.MF
@@ -0,0 +1,28 @@
+Manifest-Version: 1.0
+Export-Package: org.apache.tuscany.sca.contribution.java;uses:="org.ap
+ ache.tuscany.sca.contribution";version="1.4"
+Private-Package: org.apache.tuscany.sca.contribution.java.impl;version
+ ="1.4"
+Tool: Bnd-0.0.255
+Bundle-Name: Apache Tuscany SCA Java Import/Export Model
+Created-By: 1.6.0_07 (Sun Microsystems Inc.)
+Bundle-Vendor: The Apache Software Foundation
+DynamicImport-Package: org.apache.tuscany.sca.contribution.osgi.impl
+Bundle-Version: 1.4
+Bnd-LastModified: 1225397112984
+Bundle-ManifestVersion: 2
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-Description: Apache Tuscany SCA Java Import/Export Model
+Import-Package: javax.xml.namespace,
+ javax.xml.stream,
+ org.apache.tuscany.sca.assembly;version="1.4.0",
+ org.apache.tuscany.sca.contribution;version="1.4",
+ org.apache.tuscany.sca.contribution.java;version="1.4",
+ org.apache.tuscany.sca.contribution.processor;version="1.4",
+ org.apache.tuscany.sca.contribution.resolver;version="1.4",
+ org.apache.tuscany.sca.core;version="1.4",
+ org.apache.tuscany.sca.extensibility;version="1.4",
+ org.apache.tuscany.sca.monitor;version="1.4"
+Bundle-SymbolicName: org.apache.tuscany.sca.contribution.java
+Bundle-DocURL: http://www.apache.org/
+
diff --git a/java/sca/modules/contribution-java/NOTICE b/java/sca/modules/contribution-java/NOTICE
new file mode 100644
index 0000000000..fdfa0e9faa
--- /dev/null
+++ b/java/sca/modules/contribution-java/NOTICE
@@ -0,0 +1,6 @@
+${pom.name}
+Copyright (c) 2005 - 2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
diff --git a/java/sca/modules/contribution-java/pom.xml b/java/sca/modules/contribution-java/pom.xml
new file mode 100644
index 0000000000..afeca514a7
--- /dev/null
+++ b/java/sca/modules/contribution-java/pom.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-modules</artifactId>
+ <version>1.4-EQUINOX-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>tuscany-contribution-java</artifactId>
+ <name>Apache Tuscany SCA Java Import/Export Model</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-contribution</artifactId>
+ <version>1.4-EQUINOX-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-core-spi</artifactId>
+ <version>1.4-EQUINOX-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.codehaus.woodstox</groupId>
+ <artifactId>wstx-asl</artifactId>
+ <version>3.2.4</version>
+ <scope>runtime</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>stax</groupId>
+ <artifactId>stax-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/DefaultJavaImportExportFactory.java b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/DefaultJavaImportExportFactory.java
new file mode 100644
index 0000000000..886c61c00a
--- /dev/null
+++ b/java/sca/modules/contribution-java/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/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/JavaExport.java b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/JavaExport.java
new file mode 100644
index 0000000000..41e93ec148
--- /dev/null
+++ b/java/sca/modules/contribution-java/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/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImport.java b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImport.java
new file mode 100644
index 0000000000..d3568f6283
--- /dev/null
+++ b/java/sca/modules/contribution-java/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/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImportExportFactory.java b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/JavaImportExportFactory.java
new file mode 100644
index 0000000000..af2ca9cd57
--- /dev/null
+++ b/java/sca/modules/contribution-java/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/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ClassLoaderModelResolver.java b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ClassLoaderModelResolver.java
new file mode 100644
index 0000000000..fecb8406ca
--- /dev/null
+++ b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ClassLoaderModelResolver.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.java.impl;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+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() {
+ ClassLoader parentClassLoader = ServiceDiscovery.getInstance().getServiceDiscoverer().getClass().getClassLoader();
+ return parentClassLoader;
+ }
+
+ public ClassLoaderModelResolver(final Contribution contribution, FactoryExtensionPoint modelFactories) throws MalformedURLException {
+ super(new URL[] {new URL(contribution.getLocation())}, parentClassLoader());
+ 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/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ClassReferenceModelResolver.java b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ClassReferenceModelResolver.java
new file mode 100644
index 0000000000..d11753f3aa
--- /dev/null
+++ b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ClassReferenceModelResolver.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.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.
+ *
+ * @version $Rev: 557916 $ $Date: 2007-07-20 01:04:40 -0700 (Fri, 20 Jul 2007) $
+ */
+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/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ContributionClassLoader.java b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ContributionClassLoader.java
new file mode 100644
index 0000000000..aa68925376
--- /dev/null
+++ b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/ContributionClassLoader.java
@@ -0,0 +1,385 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.security.AccessController;
+import java.security.PrivilegedAction;
+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()));
+ } catch (MalformedURLException 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/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportImpl.java b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportImpl.java
new file mode 100644
index 0000000000..f35f35ac4c
--- /dev/null
+++ b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportImpl.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.impl;
+
+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 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/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportModelResolver.java b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportModelResolver.java
new file mode 100644
index 0000000000..8d5412f6d7
--- /dev/null
+++ b/java/sca/modules/contribution-java/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/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportProcessor.java b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportProcessor.java
new file mode 100644
index 0000000000..71fd03d549
--- /dev/null
+++ b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportProcessor.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.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 SCA10_NS = "http://www.osoa.org/xmlns/sca/1.0";
+
+ private static final QName EXPORT_JAVA = new QName(SCA10_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, XMLStreamException {
+ JavaExport javaExport = this.factory.createJavaExport();
+ QName element = null;
+
+ 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();
+ }
+ }
+
+ 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/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportExportFactoryImpl.java b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportExportFactoryImpl.java
new file mode 100644
index 0000000000..e5dc397f4e
--- /dev/null
+++ b/java/sca/modules/contribution-java/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/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportImpl.java b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportImpl.java
new file mode 100644
index 0000000000..cc18d5f798
--- /dev/null
+++ b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportImpl.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.java.impl;
+
+import java.util.List;
+
+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 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/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportModelResolver.java b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportModelResolver.java
new file mode 100644
index 0000000000..484eddd222
--- /dev/null
+++ b/java/sca/modules/contribution-java/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/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportProcessor.java b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportProcessor.java
new file mode 100644
index 0000000000..d191153e34
--- /dev/null
+++ b/java/sca/modules/contribution-java/src/main/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportProcessor.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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 SCA10_NS = "http://www.osoa.org/xmlns/sca/1.0";
+
+ private static final QName IMPORT_JAVA = new QName(SCA10_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, XMLStreamException {
+ JavaImport javaImport = this.factory.createJavaImport();
+ QName element = null;
+
+ 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();
+ }
+ }
+
+ 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/java/sca/modules/contribution-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.java.JavaImportExportFactory b/java/sca/modules/contribution-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.java.JavaImportExportFactory
new file mode 100644
index 0000000000..a293330a57
--- /dev/null
+++ b/java/sca/modules/contribution-java/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/java/sca/modules/contribution-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor b/java/sca/modules/contribution-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor
new file mode 100644
index 0000000000..ac1fa9aade
--- /dev/null
+++ b/java/sca/modules/contribution-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor
@@ -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.java.impl.JavaImportProcessor;qname=http://www.osoa.org/xmlns/sca/1.0#import.java,model=org.apache.tuscany.sca.contribution.java.JavaImport
+org.apache.tuscany.sca.contribution.java.impl.JavaExportProcessor;qname=http://www.osoa.org/xmlns/sca/1.0#export.java,model=org.apache.tuscany.sca.contribution.java.JavaExport
diff --git a/java/sca/modules/contribution-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver b/java/sca/modules/contribution-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver
new file mode 100644
index 0000000000..c69eb40636
--- /dev/null
+++ b/java/sca/modules/contribution-java/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver
@@ -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.ClassReferenceModelResolver;model=org.apache.tuscany.sca.contribution.resolver.ClassReference
diff --git a/java/sca/modules/contribution-java/src/main/resources/contribution-java-validation-messages.properties b/java/sca/modules/contribution-java/src/main/resources/contribution-java-validation-messages.properties
new file mode 100644
index 0000000000..70b58f75c0
--- /dev/null
+++ b/java/sca/modules/contribution-java/src/main/resources/contribution-java-validation-messages.properties
@@ -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.
+#
+#
+AttributePackageMissing = Attribute 'package' is missing
+
diff --git a/java/sca/modules/contribution-java/src/test/java/org/apache/tuscany/sca/contribution/java/impl/ClassReferenceArtifactResolverTestCase.java b/java/sca/modules/contribution-java/src/test/java/org/apache/tuscany/sca/contribution/java/impl/ClassReferenceArtifactResolverTestCase.java
new file mode 100644
index 0000000000..206d25e1e1
--- /dev/null
+++ b/java/sca/modules/contribution-java/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 junit.framework.Assert.assertFalse;
+import static junit.framework.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/java/sca/modules/contribution-java/src/test/java/org/apache/tuscany/sca/contribution/java/impl/ContributionClassLoaderTestCase.java b/java/sca/modules/contribution-java/src/test/java/org/apache/tuscany/sca/contribution/java/impl/ContributionClassLoaderTestCase.java
new file mode 100644
index 0000000000..779c00f71c
--- /dev/null
+++ b/java/sca/modules/contribution-java/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/java/sca/modules/contribution-java/src/test/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportProcessorTestCase.java b/java/sca/modules/contribution-java/src/test/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportProcessorTestCase.java
new file mode 100644
index 0000000000..8de1d61a34
--- /dev/null
+++ b/java/sca/modules/contribution-java/src/test/java/org/apache/tuscany/sca/contribution/java/impl/JavaExportProcessorTestCase.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 junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+
+import java.io.StringReader;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
+
+import junit.framework.Assert;
+
+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.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://www.osoa.org/xmlns/sca/1.0\" 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://www.osoa.org/xmlns/sca/1.0\"/>";
+
+ 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/java/sca/modules/contribution-java/src/test/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportProcessorTestCase.java b/java/sca/modules/contribution-java/src/test/java/org/apache/tuscany/sca/contribution/java/impl/JavaImportProcessorTestCase.java
new file mode 100644
index 0000000000..76a3090c28
--- /dev/null
+++ b/java/sca/modules/contribution-java/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 junit.framework.Assert.assertEquals;
+import static junit.framework.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://www.osoa.org/xmlns/sca/1.0\" 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://www.osoa.org/xmlns/sca/1.0\" 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/java/sca/modules/contribution-java/src/test/resources/deployables/sample-calculator.jar b/java/sca/modules/contribution-java/src/test/resources/deployables/sample-calculator.jar
new file mode 100644
index 0000000000..0ca3a1b781
--- /dev/null
+++ b/java/sca/modules/contribution-java/src/test/resources/deployables/sample-calculator.jar
Binary files differ
diff --git a/java/sca/modules/contribution-namespace/LICENSE b/java/sca/modules/contribution-namespace/LICENSE
new file mode 100644
index 0000000000..8aa906c321
--- /dev/null
+++ b/java/sca/modules/contribution-namespace/LICENSE
@@ -0,0 +1,205 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+
diff --git a/java/sca/modules/contribution-namespace/META-INF/MANIFEST.MF b/java/sca/modules/contribution-namespace/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..d369b9de49
--- /dev/null
+++ b/java/sca/modules/contribution-namespace/META-INF/MANIFEST.MF
@@ -0,0 +1,25 @@
+Manifest-Version: 1.0
+Export-Package: org.apache.tuscany.sca.contribution.namespace;uses:="o
+ rg.apache.tuscany.sca.contribution";version="1.4"
+Private-Package: org.apache.tuscany.sca.contribution.namespace.impl;ve
+ rsion="1.4"
+Tool: Bnd-0.0.255
+Bundle-Name: Apache Tuscany SCA Namespace Import/Export Model
+Created-By: 1.6.0_07 (Sun Microsystems Inc.)
+Bundle-Vendor: The Apache Software Foundation
+Bundle-Version: 1.4
+Bnd-LastModified: 1225397110468
+Bundle-ManifestVersion: 2
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-Description: Apache Tuscany SCA Namespace Import/Export Model
+Import-Package: javax.xml.namespace,
+ javax.xml.stream,
+ org.apache.tuscany.sca.contribution;version="1.4",
+ org.apache.tuscany.sca.contribution.namespace;version="1.4",
+ org.apache.tuscany.sca.contribution.processor;version="1.4",
+ org.apache.tuscany.sca.contribution.resolver;version="1.4",
+ org.apache.tuscany.sca.core;version="1.4",
+ org.apache.tuscany.sca.monitor;version="1.4"
+Bundle-SymbolicName: org.apache.tuscany.sca.contribution.namespace
+Bundle-DocURL: http://www.apache.org/
+
diff --git a/java/sca/modules/contribution-namespace/NOTICE b/java/sca/modules/contribution-namespace/NOTICE
new file mode 100644
index 0000000000..fdfa0e9faa
--- /dev/null
+++ b/java/sca/modules/contribution-namespace/NOTICE
@@ -0,0 +1,6 @@
+${pom.name}
+Copyright (c) 2005 - 2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
diff --git a/java/sca/modules/contribution-namespace/pom.xml b/java/sca/modules/contribution-namespace/pom.xml
new file mode 100644
index 0000000000..de098cf031
--- /dev/null
+++ b/java/sca/modules/contribution-namespace/pom.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-modules</artifactId>
+ <version>1.4-EQUINOX-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>tuscany-contribution-namespace</artifactId>
+ <name>Apache Tuscany SCA Namespace Import/Export Model</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-contribution</artifactId>
+ <version>1.4-EQUINOX-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-core-spi</artifactId>
+ <version>1.4-EQUINOX-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.codehaus.woodstox</groupId>
+ <artifactId>wstx-asl</artifactId>
+ <version>3.2.4</version>
+ <scope>runtime</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>stax</groupId>
+ <artifactId>stax-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/DefaultNamespaceImportExportFactory.java b/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/DefaultNamespaceImportExportFactory.java
new file mode 100644
index 0000000000..a71fa61a54
--- /dev/null
+++ b/java/sca/modules/contribution-namespace/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/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceExport.java b/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceExport.java
new file mode 100644
index 0000000000..c68aee8521
--- /dev/null
+++ b/java/sca/modules/contribution-namespace/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/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImport.java b/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImport.java
new file mode 100644
index 0000000000..8af36d7da0
--- /dev/null
+++ b/java/sca/modules/contribution-namespace/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/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImportExportFactory.java b/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/NamespaceImportExportFactory.java
new file mode 100644
index 0000000000..cfbac8bb1f
--- /dev/null
+++ b/java/sca/modules/contribution-namespace/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/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportImpl.java b/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportImpl.java
new file mode 100644
index 0000000000..8991585d32
--- /dev/null
+++ b/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportImpl.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.namespace.NamespaceExport;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * The representation of an export for the contribution
+ *
+ * @version $Rev$ $Date$
+ */
+public class NamespaceExportImpl 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/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportModelResolver.java b/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportModelResolver.java
new file mode 100644
index 0000000000..5c5ae22f77
--- /dev/null
+++ b/java/sca/modules/contribution-namespace/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/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportProcessor.java b/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportProcessor.java
new file mode 100644
index 0000000000..6bf7c8f1d7
--- /dev/null
+++ b/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportProcessor.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.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.contribution.namespace.NamespaceExport;
+import org.apache.tuscany.sca.contribution.namespace.NamespaceImportExportFactory;
+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 Namespace export
+ *
+ * @version $Rev$ $Date$
+ */
+public class NamespaceExportProcessor implements StAXArtifactProcessor<NamespaceExport> {
+
+ private static final String SCA10_NS = "http://www.osoa.org/xmlns/sca/1.0";
+ private static final QName EXPORT = new QName(SCA10_NS, "export");
+ private static final String NAMESPACE = "namespace";
+
+ private final NamespaceImportExportFactory factory;
+ private final Monitor monitor;
+
+ public NamespaceExportProcessor(FactoryExtensionPoint modelFactories, Monitor monitor) {
+ this.factory = modelFactories.getFactory(NamespaceImportExportFactory.class);
+ 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, XMLStreamException {
+ NamespaceExport namespaceExport = this.factory.createNamespaceExport();
+ QName element = null;
+
+ 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);
+ }
+
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ if (EXPORT.equals(reader.getName())) {
+ return namespaceExport;
+ }
+ break;
+ }
+
+ // Read the next element
+ if (reader.hasNext()) {
+ reader.next();
+ }
+ }
+
+ 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());
+ }
+
+ 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/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportExportFactoryImpl.java b/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportExportFactoryImpl.java
new file mode 100644
index 0000000000..1146e593a9
--- /dev/null
+++ b/java/sca/modules/contribution-namespace/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/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportImpl.java b/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportImpl.java
new file mode 100644
index 0000000000..6d2a31f702
--- /dev/null
+++ b/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportImpl.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.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 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/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportProcessor.java b/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportProcessor.java
new file mode 100644
index 0000000000..e258dcf874
--- /dev/null
+++ b/java/sca/modules/contribution-namespace/src/main/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportProcessor.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.contribution.namespace.NamespaceImport;
+import org.apache.tuscany.sca.contribution.namespace.NamespaceImportExportFactory;
+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 Namespace import
+ *
+ * @version $Rev$ $Date$
+ */
+public class NamespaceImportProcessor implements StAXArtifactProcessor<NamespaceImport> {
+ private static final String SCA10_NS = "http://www.osoa.org/xmlns/sca/1.0";
+
+ private static final QName IMPORT = new QName(SCA10_NS, "import");
+
+ private static final String NAMESPACE = "namespace";
+ private static final String LOCATION = "location";
+
+ private final NamespaceImportExportFactory factory;
+ private final Monitor monitor;
+
+ public NamespaceImportProcessor(FactoryExtensionPoint modelFactories, Monitor monitor) {
+ this.factory = modelFactories.getFactory(NamespaceImportExportFactory.class);
+ 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 IMPORT;
+ }
+
+ public Class<NamespaceImport> getModelType() {
+ return NamespaceImport.class;
+ }
+
+ /**
+ * Process <import namespace="" location=""/>
+ */
+ public NamespaceImport read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException {
+ NamespaceImport namespaceImport = this.factory.createNamespaceImport();
+ QName element;
+
+ 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);
+ }
+ }
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ if (IMPORT.equals(reader.getName())) {
+ return namespaceImport;
+ }
+ break;
+ }
+
+ // Read the next element
+ if (reader.hasNext()) {
+ reader.next();
+ }
+ }
+
+ 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());
+ }
+
+ writer.writeEndElement();
+ }
+
+
+ public void resolve(NamespaceImport model, ModelResolver resolver) throws ContributionResolveException {
+ }
+}
diff --git a/java/sca/modules/contribution-namespace/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.namespace.NamespaceImportExportFactory b/java/sca/modules/contribution-namespace/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.namespace.NamespaceImportExportFactory
new file mode 100644
index 0000000000..095866fb6f
--- /dev/null
+++ b/java/sca/modules/contribution-namespace/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/java/sca/modules/contribution-namespace/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor b/java/sca/modules/contribution-namespace/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor
new file mode 100644
index 0000000000..86f199368b
--- /dev/null
+++ b/java/sca/modules/contribution-namespace/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor
@@ -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.namespace.impl.NamespaceImportProcessor;qname=http://www.osoa.org/xmlns/sca/1.0#import,model=org.apache.tuscany.sca.contribution.namespace.NamespaceImport
+org.apache.tuscany.sca.contribution.namespace.impl.NamespaceExportProcessor;qname=http://www.osoa.org/xmlns/sca/1.0#export,model=org.apache.tuscany.sca.contribution.namespace.NamespaceExport
diff --git a/java/sca/modules/contribution-namespace/src/main/resources/contribution-namespace-validation-messages.properties b/java/sca/modules/contribution-namespace/src/main/resources/contribution-namespace-validation-messages.properties
new file mode 100644
index 0000000000..c7ddba3c3d
--- /dev/null
+++ b/java/sca/modules/contribution-namespace/src/main/resources/contribution-namespace-validation-messages.properties
@@ -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.
+#
+#
+AttributeNameSpaceMissing = Attribute 'namespace' is missing
+
diff --git a/java/sca/modules/contribution-namespace/src/test/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportProcessorTestCase.java b/java/sca/modules/contribution-namespace/src/test/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportProcessorTestCase.java
new file mode 100644
index 0000000000..f4f6ed7879
--- /dev/null
+++ b/java/sca/modules/contribution-namespace/src/test/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceExportProcessorTestCase.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.namespace.impl;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.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://www.osoa.org/xmlns/sca/1.0\" xmlns:ns=\"http://ns\" namespace=\"http://foo\"/>";
+
+ private static final String INVALID_XML =
+ "<?xml version=\"1.0\" encoding=\"ASCII\"?>" + "<export xmlns=\"http://www.osoa.org/xmlns/sca/1.0\" 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());
+ }
+
+ /**
+ * 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/java/sca/modules/contribution-namespace/src/test/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportProcessorTestCase.java b/java/sca/modules/contribution-namespace/src/test/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportProcessorTestCase.java
new file mode 100644
index 0000000000..e3d96dc70f
--- /dev/null
+++ b/java/sca/modules/contribution-namespace/src/test/java/org/apache/tuscany/sca/contribution/namespace/impl/NamespaceImportProcessorTestCase.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.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://www.osoa.org/xmlns/sca/1.0\" xmlns:ns=\"http://ns\" namespace=\"http://foo\" location=\"sca://contributions/001\"/>";
+
+ private static final String INVALID_XML =
+ "<?xml version=\"1.0\" encoding=\"ASCII\"?>"
+ + "<import xmlns=\"http://www.osoa.org/xmlns/sca/1.0\" 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());
+ }
+
+ /**
+ * 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/java/sca/modules/contribution-osgi/LICENSE b/java/sca/modules/contribution-osgi/LICENSE
new file mode 100644
index 0000000000..8aa906c321
--- /dev/null
+++ b/java/sca/modules/contribution-osgi/LICENSE
@@ -0,0 +1,205 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+
diff --git a/java/sca/modules/contribution-osgi/NOTICE b/java/sca/modules/contribution-osgi/NOTICE
new file mode 100644
index 0000000000..fdfa0e9faa
--- /dev/null
+++ b/java/sca/modules/contribution-osgi/NOTICE
@@ -0,0 +1,6 @@
+${pom.name}
+Copyright (c) 2005 - 2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
diff --git a/java/sca/modules/contribution-osgi/pom.xml b/java/sca/modules/contribution-osgi/pom.xml
new file mode 100644
index 0000000000..342493e01b
--- /dev/null
+++ b/java/sca/modules/contribution-osgi/pom.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-modules</artifactId>
+ <version>1.4-EQUINOX-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>tuscany-contribution-osgi</artifactId>
+ <name>Apache Tuscany SCA Contribution Service OSGi </name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-contribution</artifactId>
+ <version>1.4-EQUINOX-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-osgi-runtime</artifactId>
+ <version>1.4-EQUINOX-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-contribution-java</artifactId>
+ <version>1.4-EQUINOX-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-core-spi</artifactId>
+ <version>1.4-EQUINOX-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.main</artifactId>
+ <version>1.0.4</version>
+ </dependency>
+
+
+
+ <dependency>
+ <groupId>org.codehaus.woodstox</groupId>
+ <artifactId>wstx-asl</artifactId>
+ <version>3.2.4</version>
+ <scope>runtime</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>stax</groupId>
+ <artifactId>stax-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/BundleReference.java b/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/BundleReference.java
new file mode 100644
index 0000000000..0bbb8b707a
--- /dev/null
+++ b/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/BundleReference.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.osgi;
+
+
+/**
+ * A weak reference to a class, which should be used to register classes
+ * with an ArtifactResolver and resolve these classes later.
+ *
+ * @version $Rev$ $Date$
+ */
+public class BundleReference {
+
+ /**
+ * The bundle.
+ */
+ private Object bundle;
+
+ /**
+ * The bundle name.
+ */
+ private String bundleName;
+
+ /**
+ * The bundle version.
+ */
+ private String bundleVersion;
+
+ /**
+ * The bundle name and version.
+ */
+ private String bundleUniqueName;
+
+ /**
+ * The bundle relative path.
+ */
+ private String bundleRelativePath;
+
+ /**
+ * Constructs a new BundleReference.
+ *
+ * @param bundle The bundle reference
+ * @param bundleName The bundle name
+ * @param bundleVersion The bundle version
+ * @param bundleRelativePath The relative path for the bundle
+ */
+ public BundleReference(Object bundle, String bundleName, String bundleVersion, String bundleRelativePath) {
+ this.bundle = bundle;
+ this.bundleName = bundleName;
+ this.bundleVersion = bundleVersion;
+ this.bundleRelativePath = bundleRelativePath;
+ this.bundleUniqueName = bundleName + "(" + (bundleVersion == null?"0.0.0":bundleVersion) + ")";
+ }
+
+ /**
+ * Constructs a new BundleReference.
+ *
+ * @param bundleName The bundle name
+ * @param bundleVersion The bundle version
+ */
+ public BundleReference(String bundleName, String bundleVersion) {
+ this.bundleName = bundleName;
+ this.bundleVersion = bundleVersion;
+ this.bundleUniqueName = bundleName + "(" + (bundleVersion == null?"0.0.0":bundleVersion) + ")";
+ }
+
+ /**
+ * Get the referenced bundle.
+ *
+ * @return The referenced bundle
+ */
+ public Object getBundle() {
+ return bundle;
+ }
+
+ /**
+ * Get the referenced bundle name.
+ *
+ * @return The bundle name
+ */
+ public String getBundleName() {
+ return bundleName;
+ }
+
+ /**
+ * Get the referenced bundle version.
+ *
+ * @return The bundle version
+ */
+ public String getBundleVersion() {
+ return bundleVersion;
+ }
+
+ /**
+ * Get the referenced bundle name and version.
+ *
+ * @return The bundle name
+ */
+ public String getBundleUniqueName() {
+ return bundleUniqueName;
+ }
+
+ /**
+ * Get the relative location of the bundle inside its contribution.
+ *
+ * @return The bundle path
+ */
+ public String getBundleRelativePath() {
+ return bundleRelativePath;
+ }
+
+
+
+ /**
+ * Returns true if the bundle reference is unresolved.
+ *
+ * @return Whether or not the bundle has been resolved
+ */
+ public boolean isUnresolved() {
+ return bundle == null;
+ }
+
+ @Override
+ public int hashCode() {
+ return bundleUniqueName.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ } else {
+ if (obj instanceof BundleReference) {
+ BundleReference ref = (BundleReference)obj;
+ return bundleName.equals(ref.bundleName) &&
+ (bundleVersion == null || ref.bundleVersion == null ||
+ bundleVersion.equals(ref.bundleVersion));
+ } else {
+ return false;
+ }
+ }
+ }
+
+}
diff --git a/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleContributionProcessor.java b/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleContributionProcessor.java
new file mode 100644
index 0000000000..5033d7eefc
--- /dev/null
+++ b/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleContributionProcessor.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.osgi.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+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.PackageType;
+import org.apache.tuscany.sca.contribution.processor.PackageProcessor;
+import org.apache.tuscany.sca.contribution.service.ContributionException;
+import org.apache.tuscany.sca.osgi.runtime.OSGiRuntime;
+import org.osgi.framework.Bundle;
+
+/**
+ * Bundle Contribution package processor.
+ *
+ * @version $Rev$ $Date$
+ */
+public class OSGiBundleContributionProcessor implements PackageProcessor {
+
+ public OSGiBundleContributionProcessor() {
+ }
+
+ public String getPackageType() {
+ return PackageType.BUNDLE;
+ }
+
+ public URL getArtifactURL(URL sourceURL, URI artifact) throws MalformedURLException {
+ Bundle bundle = null;
+ try {
+ bundle = OSGiRuntime.findInstalledBundle(sourceURL);
+ if (bundle != null) {
+ URL url = bundle.getResource(artifact.getPath());
+ if (url == null)
+ System.out.println("Could not load resource " + artifact);
+ return url;
+ }
+ } catch (Exception e) {
+ }
+ return null;
+ }
+
+ public List<URI> getJarArtifacts(URL packageSourceURL, InputStream inputStream) throws ContributionException,
+ IOException {
+ if (packageSourceURL == null) {
+ throw new IllegalArgumentException("Invalid null package source URL.");
+ }
+
+ if (inputStream == null) {
+ throw new IllegalArgumentException("Invalid null source inputstream.");
+ }
+
+ // Assume the root is a jar file
+ JarInputStream jar = new JarInputStream(inputStream);
+ try {
+ Set<String> names = new HashSet<String>();
+ while (true) {
+ JarEntry entry = jar.getNextJarEntry();
+ if (entry == null) {
+ // EOF
+ break;
+ }
+
+ // FIXME: Maybe we should externalize the filter as a property
+ String name = entry.getName();
+ if (!name.startsWith(".") && !entry.isDirectory()) {
+
+ // Trim trailing /
+ if (name.endsWith("/")) {
+ name = name.substring(0, name.length() - 1);
+ }
+
+ // Add the entry name
+ if (!names.contains(name) && name.length() > 0) {
+ names.add(name);
+
+ }
+ }
+ }
+
+ // Return list of URIs
+ List<URI> artifacts = new ArrayList<URI>();
+ for (String name: names) {
+ artifacts.add(URI.create(name));
+ }
+ return artifacts;
+
+ } finally {
+ jar.close();
+ }
+}
+
+ public List<URI> getArtifacts(URL packageSourceURL, InputStream inputStream) throws ContributionException,
+ IOException {
+
+ Bundle bundle = null;
+ try {
+ bundle = OSGiRuntime.findInstalledBundle(packageSourceURL);
+ } catch (Exception e) {
+ }
+
+ if (bundle == null) {
+ throw new IllegalArgumentException("Could not find OSGi bundle " + packageSourceURL);
+ }
+
+ if (packageSourceURL == null) {
+ throw new IllegalArgumentException("Invalid null package source URL.");
+ }
+
+ List<URI> artifacts = new ArrayList<URI>();
+
+ try {
+ Enumeration entries = bundle.findEntries("/", "*", true);
+ while (entries.hasMoreElements()) {
+ URL entry = (URL)entries.nextElement();
+ String entryName = entry.getPath();
+ if (entryName.startsWith("/"))
+ entryName = entryName.substring(1);
+ artifacts.add(new URI(entryName));
+
+ if (entryName.endsWith(".jar")) {
+
+ URL jarResource = bundle.getResource(entryName);
+ artifacts.addAll(getJarArtifacts(jarResource, jarResource.openStream()));
+ }
+
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ return artifacts;
+ }
+}
diff --git a/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleProcessor.java b/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleProcessor.java
new file mode 100644
index 0000000000..b3c2302f60
--- /dev/null
+++ b/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleProcessor.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.osgi.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.List;
+import java.util.jar.Attributes;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
+
+import org.apache.tuscany.sca.contribution.Artifact;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.osgi.BundleReference;
+import org.apache.tuscany.sca.osgi.runtime.OSGiRuntime;
+
+/**
+ * OSGi bundle processor
+ *
+ * @version $Rev$ $Date$
+ */
+public class OSGiBundleProcessor {
+
+ private boolean initializedOSGi;
+ private OSGiRuntime osgiRuntime;
+
+ public OSGiBundleProcessor() {
+ }
+
+ public Object installContributionBundle(Contribution contribution) {
+
+ JarInputStream jar = null;
+ Object bundle = null;
+
+ try {
+
+ URL contribURL = new URL(contribution.getLocation());
+ jar = new JarInputStream(contribURL.openStream());
+
+ Manifest manifest = jar.getManifest();
+ if (manifest != null && manifest.getMainAttributes()
+ .containsKey(new Attributes.Name("Bundle-SymbolicName"))) {
+
+ initialize();
+ if (osgiRuntime != null)
+ bundle = osgiRuntime.installBundle(contribURL.toString(), null);
+ }
+ } catch (Exception e) {
+ // If OSGi cannot process the jar, treat the bundle as a plain jar file.
+ } finally {
+
+ try {
+ if (jar != null)
+ jar.close();
+ } catch (IOException e) {
+ }
+ }
+
+ return bundle;
+ }
+
+ public BundleReference installNestedBundle(Contribution contribution,
+ String bundleSymbolicName,
+ String bundleVersion) {
+
+ BundleReference bundleReference = null;
+
+ initialize();
+ if (osgiRuntime == null)
+ return null;
+
+ List<Artifact> artifacts = contribution.getArtifacts();
+ for (Artifact a : artifacts) {
+ if (a.getURI().endsWith(".jar")) {
+
+ InputStream stream;
+ JarInputStream jar = null;
+ Object name;
+ Object version;
+ try {
+
+ URL artifactURL = new URL(a.getLocation());
+ stream = artifactURL.openStream();
+ jar = new JarInputStream(artifactURL.openStream());
+ Manifest manifest = jar.getManifest();
+ name = manifest.getMainAttributes().get(new Attributes.Name("Bundle-SymbolicName"));
+ version = manifest.getMainAttributes().get(new Attributes.Name("Bundle-Version"));
+
+ if (bundleSymbolicName.equals(name) && (bundleVersion == null || version == null || bundleVersion
+ .equals(version))) {
+
+ Object bundle = osgiRuntime.installBundle(a.getLocation(), stream);
+
+ bundleReference = new BundleReference(bundle, bundleSymbolicName, bundleVersion, a.getURI());
+
+ break;
+ }
+
+ } catch (Exception e) {
+
+ // If OSGi cannot process the jar, treat the bundle as a plain jar file.
+ } finally {
+ try {
+ if (jar != null)
+ jar.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+ return bundleReference;
+ }
+
+ private void initialize() {
+ try {
+ if (!initializedOSGi) {
+ initializedOSGi = true;
+ osgiRuntime = OSGiRuntime.getRuntime();
+ }
+ } catch (Exception e) {
+ }
+ }
+}
diff --git a/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleReferenceModelResolver.java b/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleReferenceModelResolver.java
new file mode 100644
index 0000000000..07e80f66f3
--- /dev/null
+++ b/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleReferenceModelResolver.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.osgi.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.Import;
+import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint;
+import org.apache.tuscany.sca.contribution.osgi.BundleReference;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.osgi.runtime.OSGiRuntime;
+import org.osgi.framework.Bundle;
+
+/**
+ * A Model Resolver for BundleReferences.
+ *
+ * @version $Rev$ $Date$
+ */
+public class OSGiBundleReferenceModelResolver implements ModelResolver {
+ private Contribution contribution;
+ private Map<String, BundleReference> map = new HashMap<String, BundleReference>();
+
+ OSGiRuntime osgiRuntime;
+ private OSGiBundleProcessor bundleProcessor;
+
+ public OSGiBundleReferenceModelResolver(Contribution contribution, ModelFactoryExtensionPoint modelFactories) {
+ this.contribution = contribution;
+ this.bundleProcessor = new OSGiBundleProcessor();
+ }
+
+ public void addModel(Object resolved) {
+ BundleReference bundleRef = (BundleReference)resolved;
+ map.put(bundleRef.getBundleUniqueName(), bundleRef);
+ }
+
+ public Object removeModel(Object resolved) {
+ return map.remove(((BundleReference)resolved).getBundleUniqueName());
+ }
+
+ /**
+ * Handle artifact resolution when the specific class reference is imported from another contribution
+ * @param unresolved
+ * @return
+ */
+ private BundleReference resolveImportedModel(BundleReference unresolved) {
+ BundleReference resolved = unresolved;
+
+ if( this.contribution != null) {
+ for (Import import_ : this.contribution.getImports()) {
+
+ resolved = import_.getModelResolver().resolveModel(BundleReference.class, unresolved);
+ if (resolved != unresolved)
+ break;
+ }
+
+ }
+ return resolved;
+ }
+
+
+ public <T> T resolveModel(Class<T> modelClass, T unresolved) {
+ Object resolved = map.get(unresolved);
+
+ if (resolved != null ){
+ return modelClass.cast(resolved);
+ }
+
+ try {
+ if (osgiRuntime == null)
+ osgiRuntime = OSGiRuntime.getRuntime();
+ } catch (Exception e) {
+ }
+ if (osgiRuntime == null)
+ return unresolved;
+
+ //Load a class on demand
+ Object bundle = null;
+ String bundleName = ((BundleReference)unresolved).getBundleName();
+ String bundleVersion = ((BundleReference)unresolved).getBundleVersion();
+
+ bundle = osgiRuntime.findBundle(bundleName, bundleVersion);
+ BundleReference bundleReference;
+
+ if (bundle == null)
+ bundleReference = bundleProcessor.installNestedBundle(contribution, bundleName, bundleVersion);
+ else {
+ bundleReference = new BundleReference(bundle,
+ ((BundleReference)unresolved).getBundleName(),
+ bundleVersion,
+ getBundleFileName(bundle)
+ );
+ }
+
+
+ if (bundleReference != null) {
+ //if we load the class
+
+ map.put(((BundleReference)unresolved).getBundleUniqueName(), bundleReference);
+
+ // Return the resolved BundleReference
+ return modelClass.cast(bundleReference);
+ } else {
+ //delegate resolution of the class
+ resolved = this.resolveImportedModel((BundleReference)unresolved);
+ return modelClass.cast(resolved);
+ }
+
+
+ }
+
+
+ private String getBundleFileName(Object bundle) {
+ if (bundle instanceof Bundle) {
+ String path = ((Bundle)bundle).getLocation();
+ if (path.endsWith("/"))
+ path = path.substring(0, path.length()-1);
+ if (path.startsWith(contribution.getLocation())) {
+ if (path.equals(contribution.getLocation())) {
+ int index = path.lastIndexOf('/');
+ if (index > 0 && index < path.length()-1)
+ path = path.substring(index+1);
+ } else {
+ path = path.substring(contribution.getLocation().length());
+ if (path.startsWith("/"))
+ path = path.substring(1);
+ }
+ } else if (path.lastIndexOf('/') >= 0)
+ path = path.substring(path.lastIndexOf('/')+1);
+ return path;
+ }
+ return null;
+
+ }
+
+}
diff --git a/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiClassReferenceModelResolver.java b/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiClassReferenceModelResolver.java
new file mode 100644
index 0000000000..528a287328
--- /dev/null
+++ b/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiClassReferenceModelResolver.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.osgi.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.Import;
+import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint;
+import org.apache.tuscany.sca.contribution.resolver.ClassReference;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.osgi.runtime.OSGiRuntime;
+import org.osgi.framework.Bundle;
+
+/**
+ * A Model Resolver for ClassReferences.
+ *
+ * @version $Rev$ $Date$
+ */
+public class OSGiClassReferenceModelResolver implements ModelResolver {
+ private Contribution contribution;
+ private Map<String, ClassReference> map = new HashMap<String, ClassReference>();
+ private Bundle bundle;
+ private boolean initialized;
+ private boolean useOSGi;
+
+ public OSGiClassReferenceModelResolver(Contribution contribution, ModelFactoryExtensionPoint modelFactories) {
+ this.contribution = contribution;
+ }
+
+ 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());
+ }
+
+ /**
+ * Handle artifact resolution when the specific class reference is imported from another contribution
+ * @param unresolved
+ * @return
+ */
+ private ClassReference resolveImportedModel(ClassReference unresolved) {
+ ClassReference resolved = unresolved;
+
+ if (this.contribution != null) {
+ for (Import import_ : this.contribution.getImports()) {
+
+ if (resolved == unresolved && bundle != null) {
+ resolved = import_.getModelResolver().resolveModel(ClassReference.class, unresolved);
+ if (resolved != unresolved)
+ break;
+ }
+ }
+
+ }
+ return resolved;
+ }
+
+ public <T> T resolveModel(Class<T> modelClass, T unresolved) {
+ Object resolved = map.get(unresolved);
+
+ if (resolved != null) {
+ return modelClass.cast(resolved);
+ }
+ initialize();
+ if (!useOSGi)
+ return unresolved;
+
+ //Load a class on demand
+ Class clazz = null;
+ if (bundle != null) {
+ try {
+ clazz = bundle.loadClass(((ClassReference)unresolved).getClassName());
+ } catch (Exception e) {
+ // we will later try to delegate to imported model resolvers
+ }
+ }
+
+ if (clazz != null) {
+ //if we load the class
+ // Store a new ClassReference wrapping the loaded class
+ ClassReference classReference = new ClassReference(clazz);
+ map.put(getPackageName(classReference), classReference);
+
+ // Return the resolved ClassReference
+ return modelClass.cast(classReference);
+ } else {
+ //delegate resolution of the class
+ resolved = this.resolveImportedModel((ClassReference)unresolved);
+ return modelClass.cast(resolved);
+ }
+
+ }
+
+ /***************
+ * Helper methods
+ ***************/
+
+ private String getPackageName(ClassReference clazz) {
+ int pos = clazz.getClassName().lastIndexOf(".");
+ return clazz.getClassName().substring(0, pos - 1);
+ }
+
+ private void initialize() {
+ if (initialized)
+ return;
+
+ initialized = true;
+ try {
+ bundle = OSGiRuntime.findInstalledBundle(contribution.getLocation());
+ useOSGi = bundle != null;
+ } catch (Throwable e) {
+ // Ignore errors, default to ClassReferenceModelResolver
+ }
+ }
+}
diff --git a/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiImportExportListener.java b/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiImportExportListener.java
new file mode 100644
index 0000000000..15ad0bd948
--- /dev/null
+++ b/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiImportExportListener.java
@@ -0,0 +1,215 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.osgi.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+
+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.JavaExport;
+import org.apache.tuscany.sca.contribution.java.JavaImport;
+import org.apache.tuscany.sca.contribution.service.ContributionListener;
+import org.apache.tuscany.sca.contribution.service.ContributionRepository;
+import org.apache.tuscany.sca.osgi.runtime.OSGiRuntime;
+
+/**
+ * Namespace Import/Export contribution listener
+ * The listener would process all import/export from a given contribution
+ * and initialize the model resolvers properly
+ *
+ * @version $Rev$ $Date$
+ */
+public class OSGiImportExportListener implements ContributionListener {
+
+ private OSGiBundleProcessor bundleProcessor;
+
+ public OSGiImportExportListener() {
+ bundleProcessor = new OSGiBundleProcessor();
+ }
+
+ /**
+ * Initialize the import/export model resolvers
+ * Export model resolvers are same as Contribution model resolver
+ * Import model resolvers are matched to a specific contribution if a location URI is specified,
+ * otherwise it try to resolve against all the other contributions
+ */
+ public void contributionAdded(ContributionRepository repository, Contribution contribution) {
+
+ OSGiRuntime osgiRuntime = null;
+ try {
+ if (bundleProcessor.installContributionBundle(contribution) == null) {
+ return;
+ } else {
+ osgiRuntime = OSGiRuntime.getRuntime();
+ }
+ } catch (Exception e) {
+ return;
+ }
+
+ HashSet<Contribution> bundlesToInstall = new HashSet<Contribution>();
+ // Initialize the contribution imports
+ for (Import import_ : contribution.getImports()) {
+ boolean initialized = false;
+
+ if (import_ instanceof JavaImport) {
+ JavaImport javaImport = (JavaImport)import_;
+ String packageName = javaImport.getPackage();
+
+ //Find a matching contribution
+ if (javaImport.getLocation() != null) {
+ Contribution targetContribution = repository.getContribution(javaImport.getLocation());
+ if (targetContribution != null) {
+
+ // Find a matching contribution export
+ for (Export export : targetContribution.getExports()) {
+ if (export instanceof JavaExport) {
+ JavaExport javaExport = (JavaExport)export;
+ if (packageName.equals(javaExport.getPackage())) {
+
+ if (osgiRuntime.findBundle(targetContribution.getLocation()) == null)
+ bundlesToInstall.add(targetContribution);
+
+ initialized = true;
+
+ }
+ }
+ if (initialized)
+ break;
+ }
+ }
+ }
+ }
+ if (!initialized) {
+ for (Contribution c : repository.getContributions()) {
+
+ // Go over all exports in the contribution
+ for (Export export : c.getExports()) {
+ // If the export matches our namespace, try to the resolve the model object
+ if (import_.match(export) && osgiRuntime.findBundle(c.getLocation()) == null) {
+ bundlesToInstall.add(c);
+ }
+ }
+ }
+ }
+ }
+ for (Contribution c : bundlesToInstall) {
+ try {
+ installDummyBundle(osgiRuntime, c);
+ } catch (Exception e) {
+ }
+ }
+
+ }
+
+ public void contributionRemoved(ContributionRepository repository, Contribution contribution) {
+
+ }
+
+ public void contributionUpdated(ContributionRepository repository,
+ Contribution oldContribution,
+ Contribution contribution) {
+
+ }
+
+ private void installDummyBundle(OSGiRuntime osgiRuntime, Contribution contribution) throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ String EOL = System.getProperty("line.separator");
+
+ String bundleName = contribution.getURI();
+ URL contribURL = new URL(contribution.getLocation());
+ String contribName = contribURL.getPath();
+ if (contribName.endsWith("/"))
+ contribName = contribName.substring(0, contribName.length()-1);
+ if (contribName.lastIndexOf("/") >= 0)
+ contribName = contribName.substring(contribName.lastIndexOf("/")+1);
+
+ StringBuffer exportPackageNames = new StringBuffer();
+ for (Export export : contribution.getExports()) {
+ if (export instanceof JavaExport) {
+ if (exportPackageNames.length() > 0)
+ exportPackageNames.append(",");
+ exportPackageNames.append(((JavaExport)export).getPackage());
+ }
+ }
+ StringBuffer importPackageNames = new StringBuffer();
+ for (Import import_ : contribution.getImports()) {
+ if (import_ instanceof JavaImport) {
+ if (importPackageNames.length() > 0)
+ importPackageNames.append(",");
+ importPackageNames.append(((JavaImport)import_).getPackage());
+ }
+ }
+
+ String manifestStr =
+ "Manifest-Version: 1.0" + EOL
+ + "Bundle-ManifestVersion: 2"
+ + EOL
+ + "Bundle-Name: "
+ + bundleName
+ + EOL
+ + "Bundle-SymbolicName: "
+ + bundleName
+ + EOL
+ + "Bundle-Version: "
+ + "1.0.0"
+ + EOL
+ + "Bundle-Localization: plugin"
+ + EOL;
+
+ StringBuilder manifestBuf = new StringBuilder();
+ manifestBuf.append(manifestStr);
+ manifestBuf.append("Export-Package: " + exportPackageNames + EOL);
+ manifestBuf.append("Import-Package: " + importPackageNames + EOL);
+ manifestBuf.append("Bundle-ClassPath: .," + contribName + EOL);
+
+ ByteArrayInputStream manifestStream = new ByteArrayInputStream(manifestBuf.toString().getBytes());
+ Manifest manifest = new Manifest();
+ manifest.read(manifestStream);
+
+ JarOutputStream jarOut = new JarOutputStream(out, manifest);
+
+ ZipEntry ze = new ZipEntry(contribName);
+ jarOut.putNextEntry(ze);
+ InputStream stream = contribURL.openStream();
+
+ byte[] bytes = new byte[stream.available()];
+ stream.read(bytes);
+ jarOut.write(bytes);
+ stream.close();
+
+ jarOut.close();
+ out.close();
+
+ ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+
+ osgiRuntime.installBundle("file://" + bundleName + ".jar", in);
+
+ }
+
+}
diff --git a/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiModelResolverImpl.java b/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiModelResolverImpl.java
new file mode 100644
index 0000000000..e624b1d3b5
--- /dev/null
+++ b/java/sca/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiModelResolverImpl.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.osgi.impl;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.tuscany.sca.contribution.osgi.BundleReference;
+import org.apache.tuscany.sca.contribution.resolver.ClassReference;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.osgi.framework.Bundle;
+
+/**
+ * An implementation of an artifact resolver for OSGi bundles.
+ *
+ * @version $Rev$ $Date$
+ */
+public class OSGiModelResolverImpl implements ModelResolver {
+ private static final long serialVersionUID = -7826976465762296634L;
+
+ private Map<Object, Object> map = new HashMap<Object, Object>();
+
+ private Hashtable<String, Bundle> bundles;
+ public OSGiModelResolverImpl(Hashtable<String, Bundle> bundles) {
+ this.bundles = bundles;
+ }
+
+
+ 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 if (unresolved instanceof ClassReference) {
+
+ // Load a class on demand
+ ClassReference classReference = (ClassReference)unresolved;
+ Class clazz = null;
+ for (Bundle bundle : bundles.values()) {
+ try {
+ clazz = bundle.loadClass(classReference.getClassName());
+ } catch (ClassNotFoundException e) {
+ continue;
+ }
+ break;
+ }
+ if (clazz == null) {
+
+ // Return the unresolved object
+ return unresolved;
+ }
+
+ // Store a new ClassReference wrapping the loaded class
+ resolved = new ClassReference(clazz);
+ map.put(resolved, resolved);
+
+ // Return the resolved ClassReference
+ return modelClass.cast(resolved);
+
+ } else if (unresolved instanceof BundleReference) {
+ for (String bundlePath: bundles.keySet()) {
+ Bundle bundle = bundles.get(bundlePath);
+ BundleReference bundleRef = (BundleReference)unresolved;
+ String bundleVersion = (String)bundle.getHeaders().get("Bundle-Version");
+ if (bundle.getSymbolicName().equals(bundleRef.getBundleName())&&
+ (bundleVersion == null || bundleRef.getBundleVersion() == null ||
+ bundleVersion.equals(bundleRef.getBundleVersion()))) {
+
+ resolved = new BundleReference(bundle,
+ bundle.getSymbolicName(),
+ bundleVersion,
+ bundlePath);
+ map.put(resolved, resolved);
+
+ // Return the resolved BundleReference
+ 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);
+ }
+
+ public Collection<Object> getModels() {
+ return map.values();
+ }
+
+}
diff --git a/java/sca/modules/contribution-osgi/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.PackageProcessor b/java/sca/modules/contribution-osgi/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.PackageProcessor
new file mode 100644
index 0000000000..632d135cb5
--- /dev/null
+++ b/java/sca/modules/contribution-osgi/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.PackageProcessor
@@ -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.osgi.impl.OSGiBundleContributionProcessor;type=application/osgi.bundle
diff --git a/java/sca/modules/contribution-osgi/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver b/java/sca/modules/contribution-osgi/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver
new file mode 100644
index 0000000000..02e8b411eb
--- /dev/null
+++ b/java/sca/modules/contribution-osgi/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver
@@ -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.osgi.impl.OSGiBundleReferenceModelResolver;model=org.apache.tuscany.sca.contribution.osgi.BundleReference
diff --git a/java/sca/modules/contribution-osgi/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.service.ContributionListener b/java/sca/modules/contribution-osgi/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.service.ContributionListener
new file mode 100644
index 0000000000..8dec190930
--- /dev/null
+++ b/java/sca/modules/contribution-osgi/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.service.ContributionListener
@@ -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.osgi.impl.OSGiImportExportListener
diff --git a/java/sca/modules/contribution-resource/META-INF/MANIFEST.MF b/java/sca/modules/contribution-resource/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..71371fa9fd
--- /dev/null
+++ b/java/sca/modules/contribution-resource/META-INF/MANIFEST.MF
@@ -0,0 +1,26 @@
+Manifest-Version: 1.0
+Export-Package: org.apache.tuscany.sca.contribution.resource;uses:="or
+ g.apache.tuscany.sca.contribution";version="1.4"
+Private-Package: org.apache.tuscany.sca.contribution.resource.impl;ver
+ sion="1.4"
+Tool: Bnd-0.0.255
+Bundle-Name: Apache Tuscany SCA Resource Import/Export Model
+Created-By: 1.6.0_07 (Sun Microsystems Inc.)
+Bundle-Vendor: The Apache Software Foundation
+Bundle-Version: 1.4
+Bnd-LastModified: 1225397365937
+Bundle-ManifestVersion: 2
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-Description: Apache Tuscany SCA Resource Import/Export Model
+Import-Package: javax.xml.namespace,
+ javax.xml.stream,
+ org.apache.tuscany.sca.assembly;version="1.4.0",
+ org.apache.tuscany.sca.contribution;version="1.4",
+ org.apache.tuscany.sca.contribution.processor;version="1.4",
+ org.apache.tuscany.sca.contribution.resolver;version="1.4",
+ org.apache.tuscany.sca.contribution.resource;version="1.4",
+ org.apache.tuscany.sca.core;version="1.4",
+ org.apache.tuscany.sca.monitor;version="1.4"
+Bundle-SymbolicName: org.apache.tuscany.sca.contribution.resource
+Bundle-DocURL: http://www.apache.org/
+
diff --git a/java/sca/modules/contribution-resource/pom.xml b/java/sca/modules/contribution-resource/pom.xml
new file mode 100644
index 0000000000..3f382c4de3
--- /dev/null
+++ b/java/sca/modules/contribution-resource/pom.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-modules</artifactId>
+ <version>1.4-EQUINOX-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>tuscany-contribution-resource</artifactId>
+ <name>Apache Tuscany SCA Resource Import/Export Model</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-contribution</artifactId>
+ <version>1.4-EQUINOX-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-core-spi</artifactId>
+ <version>1.4-EQUINOX-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.codehaus.woodstox</groupId>
+ <artifactId>wstx-asl</artifactId>
+ <version>3.2.4</version>
+ <scope>runtime</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>stax</groupId>
+ <artifactId>stax-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/ResourceExport.java b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/ResourceExport.java
new file mode 100644
index 0000000000..0bd30c19dd
--- /dev/null
+++ b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/ResourceExport.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.resource;
+
+import org.apache.tuscany.sca.contribution.Export;
+
+
+/**
+ * The representation of an resource export.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ResourceExport extends Export {
+
+ /**
+ * Get Resource URI that identifies the export.
+ *
+ * @return The exported resource URI
+ */
+ String getURI();
+
+ /**
+ * Set Resource URI that identifies the export.
+ *
+ * @param uri The exported resource URI
+ */
+ void setURI(String uri);
+
+}
diff --git a/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/ResourceImport.java b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/ResourceImport.java
new file mode 100644
index 0000000000..07eac9d843
--- /dev/null
+++ b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/ResourceImport.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.resource;
+
+import org.apache.tuscany.sca.contribution.Import;
+
+/**
+ * The representation of an resource import.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ResourceImport 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 URI that identifies the resource import
+ *
+ * @return The URI
+ */
+ String getURI();
+
+ /**
+ * Set URI that identifies the resource import
+ *
+ * @param uri The resource URI
+ */
+ void setURI(String uri);
+
+} \ No newline at end of file
diff --git a/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/ResourceImportExportFactory.java b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/ResourceImportExportFactory.java
new file mode 100644
index 0000000000..4119c344ce
--- /dev/null
+++ b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/ResourceImportExportFactory.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.resource;
+
+/**
+ * Base Resource import/export model factory
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ResourceImportExportFactory {
+
+ /**
+ * Create a resource import model object
+ *
+ * @return The new ResourceImport model object
+ */
+ ResourceImport createResourceImport();
+
+ /**
+ * Create a resource export model object
+ *
+ * @return The new ResourceExport model object
+ */
+ ResourceExport createResourceExport();
+}
diff --git a/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ArtifactModelResolver.java b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ArtifactModelResolver.java
new file mode 100644
index 0000000000..5c6bb5e245
--- /dev/null
+++ b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ArtifactModelResolver.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.resource.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.sca.contribution.Artifact;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.Import;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.resource.ResourceImport;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+
+/**
+ * A Model Resolver for contribution artifacts.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ArtifactModelResolver implements ModelResolver {
+ private Contribution contribution;
+ private Map<String, Artifact> map = new HashMap<String, Artifact>();
+
+ public ArtifactModelResolver(Contribution contribution, FactoryExtensionPoint modelFactories) {
+ this.contribution = contribution;
+ }
+
+ public void addModel(Object resolved) {
+ Artifact artifact = (Artifact)resolved;
+ map.put(artifact.getURI(), artifact);
+ }
+
+ public Object removeModel(Object resolved) {
+ return map.remove(((Artifact)resolved).getURI());
+ }
+
+ public <T> T resolveModel(Class<T> modelClass, T unresolved) {
+
+ // Get the artifact URI
+ String uri = ((Artifact)unresolved).getURI();
+ if (uri == null) {
+ return (T)unresolved;
+ }
+
+ // Lookup the artifact
+ Artifact resolved = (Artifact) map.get(uri);
+ if (resolved != null) {
+ return modelClass.cast(resolved);
+ }
+
+ // If not found, delegate the resolution to the imports (in this case based on the resource imports)
+ for (Import import_ : this.contribution.getImports()) {
+ if (import_ instanceof ResourceImport) {
+ ResourceImport resourceImport = (ResourceImport)import_;
+ //check the import location against the computed package name from the componentType URI
+ if (resourceImport.getURI().equals(uri)) {
+ // Delegate the resolution to the import resolver
+ resolved = resourceImport.getModelResolver().resolveModel(Artifact.class, (Artifact)unresolved);
+ if (!resolved.isUnresolved()) {
+ return modelClass.cast(resolved);
+ }
+ }
+ }
+ }
+
+ return (T)unresolved;
+ }
+
+}
diff --git a/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceExportImpl.java b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceExportImpl.java
new file mode 100644
index 0000000000..c2d525dfef
--- /dev/null
+++ b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceExportImpl.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.resource.impl;
+
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.resource.ResourceExport;
+
+/**
+ * The representation of an export for the contribution
+ *
+ * @version $Rev$ $Date$
+ */
+public class ResourceExportImpl implements ResourceExport {
+ /**
+ * The resource URI to be exported
+ */
+ private String uri;
+
+ private ModelResolver modelResolver;
+
+ protected ResourceExportImpl() {
+ super();
+ }
+
+ public String getURI() {
+ return uri;
+ }
+
+ public void setURI(String uri) {
+ this.uri = uri;
+ }
+
+ public ModelResolver getModelResolver() {
+ return modelResolver;
+ }
+
+ public void setModelResolver(ModelResolver modelResolver) {
+ this.modelResolver = modelResolver;
+ }
+
+}
diff --git a/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceExportModelResolver.java b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceExportModelResolver.java
new file mode 100644
index 0000000000..fd568e533d
--- /dev/null
+++ b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceExportModelResolver.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.resource.impl;
+
+import org.apache.tuscany.sca.contribution.Artifact;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.resource.ResourceExport;
+
+/**
+ * A model resolver for resource exports.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ResourceExportModelResolver implements ModelResolver {
+
+ private ResourceExport export;
+ private ModelResolver resolver;
+
+ public ResourceExportModelResolver(ResourceExport 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) {
+
+ // Filter based on the artifact URI
+ Artifact artifact = (Artifact)unresolved;
+ if (export.getURI().equals(artifact.getURI())) {
+
+ // The artifact URI matches the exported URI, delegate to the
+ // contribution's resolver
+ return resolver.resolveModel(modelClass, unresolved);
+ } else {
+
+ // The artifact URI is not exported, return the unresolved object
+ return unresolved;
+ }
+ }
+
+}
diff --git a/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceExportProcessor.java b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceExportProcessor.java
new file mode 100644
index 0000000000..f5f9fad167
--- /dev/null
+++ b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceExportProcessor.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.resource.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.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.contribution.resource.ResourceExport;
+import org.apache.tuscany.sca.contribution.resource.ResourceImportExportFactory;
+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 Resource export
+ *
+ * @version $Rev$ $Date$
+ */
+public class ResourceExportProcessor implements StAXArtifactProcessor<ResourceExport> {
+
+ private static final String SCA10_NS = "http://www.osoa.org/xmlns/sca/1.0";
+ private static final QName EXPORT_RESOURCE = new QName(SCA10_NS, "export.resource");
+ private static final String URI = "uri";
+
+ private final ResourceImportExportFactory factory;
+ private final Monitor monitor;
+
+ public ResourceExportProcessor(FactoryExtensionPoint modelFactories, Monitor monitor) {
+ this.factory = modelFactories.getFactory(ResourceImportExportFactory.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-resource-validation-messages", Severity.ERROR, model, message, (Object[])messageParameters);
+ monitor.problem(problem);
+ }
+ }
+
+ public QName getArtifactType() {
+ return EXPORT_RESOURCE;
+ }
+
+ public Class<ResourceExport> getModelType() {
+ return ResourceExport.class;
+ }
+
+ /**
+ * Process <export.resource uri=""/>
+ */
+ public ResourceExport read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException {
+ ResourceExport resourceExport = this.factory.createResourceExport();
+ QName element = null;
+
+ while (reader.hasNext()) {
+ int event = reader.getEventType();
+ switch (event) {
+ case START_ELEMENT:
+ element = reader.getName();
+
+ // Read <export.resource>
+ if (EXPORT_RESOURCE.equals(element)) {
+ String uri = reader.getAttributeValue(null, URI);
+ if (uri == null) {
+ error("AttributeURIMissing", reader);
+ //throw new ContributionReadException("Attribute 'uri' is missing");
+ } else
+ resourceExport.setURI(uri);
+ }
+
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ if (EXPORT_RESOURCE.equals(reader.getName())) {
+ return resourceExport;
+ }
+ break;
+ }
+
+ // Read the next element
+ if (reader.hasNext()) {
+ reader.next();
+ }
+ }
+
+ return resourceExport;
+ }
+
+ public void write(ResourceExport resourceExport, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException {
+
+ // Write <export.resource>
+ writer.writeStartElement(EXPORT_RESOURCE.getNamespaceURI(), EXPORT_RESOURCE.getLocalPart());
+
+ if (resourceExport.getURI() != null) {
+ writer.writeAttribute(URI, resourceExport.getURI());
+ }
+
+ writer.writeEndElement();
+ }
+
+ public void resolve(ResourceExport resourceExport, ModelResolver resolver) throws ContributionResolveException {
+
+ if (resourceExport.getURI() != null)
+ // Initialize the export's model resolver
+ resourceExport.setModelResolver(new ResourceExportModelResolver(resourceExport, resolver));
+ }
+}
diff --git a/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceImportExportFactoryImpl.java b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceImportExportFactoryImpl.java
new file mode 100644
index 0000000000..880f5f5786
--- /dev/null
+++ b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceImportExportFactoryImpl.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.resource.impl;
+
+import org.apache.tuscany.sca.contribution.resource.ResourceExport;
+import org.apache.tuscany.sca.contribution.resource.ResourceImport;
+import org.apache.tuscany.sca.contribution.resource.ResourceImportExportFactory;
+
+/**
+ * Resource Import/Export model factory implementation
+ *
+ * @version $Rev$ $Date$
+ */
+public class ResourceImportExportFactoryImpl implements ResourceImportExportFactory {
+
+ public ResourceImport createResourceImport() {
+ return new ResourceImportImpl();
+ }
+
+ public ResourceExport createResourceExport() {
+ return new ResourceExportImpl();
+ }
+
+}
diff --git a/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceImportImpl.java b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceImportImpl.java
new file mode 100644
index 0000000000..cd33f1290f
--- /dev/null
+++ b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceImportImpl.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.resource.impl;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.Export;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.resource.ResourceExport;
+import org.apache.tuscany.sca.contribution.resource.ResourceImport;
+
+/**
+ * The representation of an import for the contribution
+ *
+ * @version $Rev$ $Date$
+ */
+public class ResourceImportImpl implements ResourceImport {
+ /**
+ * The resource URI to be imported
+ */
+ private String uri;
+
+ private ModelResolver modelResolver;
+ private List<Contribution> exportContributions;
+
+ /**
+ * Optional location URI pointing to a Contribution that exports the resource
+ */
+ private String location;
+
+
+ protected ResourceImportImpl() {
+ super();
+ }
+
+ 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 ModelResolver getModelResolver() {
+ return modelResolver;
+ }
+
+ public void setModelResolver(ModelResolver modelResolver) {
+ this.modelResolver = modelResolver;
+ }
+
+ public List<Contribution> getExportContributions() {
+ return exportContributions;
+ }
+
+ public void setExportContributions(List<Contribution> contributions) {
+ this.exportContributions = contributions;
+ }
+
+ /**
+ * Match a ResourceImport to a given ResourceExport based on :
+ * location is not provided
+ * import and export resource URI match
+ */
+ public boolean match(Export export) {
+ if (export instanceof ResourceExport) {
+ if (this.getLocation() == null || this.getLocation().length() == 0) {
+ if (this.getURI().equals(((ResourceExport)export).getURI())) {
+ return true;
+ }
+ }
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(uri);
+ }
+}
diff --git a/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceImportProcessor.java b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceImportProcessor.java
new file mode 100644
index 0000000000..7fdb74e256
--- /dev/null
+++ b/java/sca/modules/contribution-resource/src/main/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceImportProcessor.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.resource.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.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.contribution.resource.ResourceImport;
+import org.apache.tuscany.sca.contribution.resource.ResourceImportExportFactory;
+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 ResourceImportProcessor implements StAXArtifactProcessor<ResourceImport> {
+ private static final String SCA10_NS = "http://www.osoa.org/xmlns/sca/1.0";
+
+ private static final QName IMPORT_RESOURCE = new QName(SCA10_NS, "import.resource");
+
+ private static final String URI = "uri";
+ private static final String LOCATION = "location";
+
+ private final ResourceImportExportFactory factory;
+ private final Monitor monitor;
+
+ public ResourceImportProcessor(FactoryExtensionPoint modelFactories, Monitor monitor) {
+ this.factory = modelFactories.getFactory(ResourceImportExportFactory.class);
+ 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-resource-validation-messages", Severity.ERROR, model, message, (Object[])messageParameters);
+ monitor.problem(problem);
+ }
+ }
+
+ public QName getArtifactType() {
+ return IMPORT_RESOURCE;
+ }
+
+ public Class<ResourceImport> getModelType() {
+ return ResourceImport.class;
+ }
+
+ /**
+ * Process <import.resource uri="" location=""/>
+ */
+ public ResourceImport read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException {
+ ResourceImport resourceImport = this.factory.createResourceImport();
+ QName element;
+
+ while (reader.hasNext()) {
+ int event = reader.getEventType();
+ switch (event) {
+ case START_ELEMENT:
+ element = reader.getName();
+
+ // Read <import>
+ if (IMPORT_RESOURCE.equals(element)) {
+ String uri = reader.getAttributeValue(null, URI);
+ if (uri == null) {
+ error("AttributeURIMissing", reader);
+ //throw new ContributionReadException("Attribute 'uri' is missing");
+ } else
+ resourceImport.setURI(uri);
+
+ String location = reader.getAttributeValue(null, LOCATION);
+ if (location != null) {
+ resourceImport.setLocation(location);
+ }
+ }
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ if (IMPORT_RESOURCE.equals(reader.getName())) {
+ return resourceImport;
+ }
+ break;
+ }
+
+ // Read the next element
+ if (reader.hasNext()) {
+ reader.next();
+ }
+ }
+
+ return resourceImport;
+ }
+
+ public void write(ResourceImport resourceImport, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException {
+
+ // Write <import>
+ writer.writeStartElement(IMPORT_RESOURCE.getNamespaceURI(), IMPORT_RESOURCE.getLocalPart());
+
+ if (resourceImport.getURI() != null) {
+ writer.writeAttribute(URI, resourceImport.getURI());
+ }
+ if (resourceImport.getLocation() != null) {
+ writer.writeAttribute(LOCATION, resourceImport.getLocation());
+ }
+
+ writer.writeEndElement();
+ }
+
+
+ public void resolve(ResourceImport model, ModelResolver resolver) throws ContributionResolveException {
+ }
+}
diff --git a/java/sca/modules/contribution-resource/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor b/java/sca/modules/contribution-resource/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor
new file mode 100644
index 0000000000..14eb81546d
--- /dev/null
+++ b/java/sca/modules/contribution-resource/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor
@@ -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.resource.impl.ResourceImportProcessor;qname=http://www.osoa.org/xmlns/sca/1.0#import.resource,model=org.apache.tuscany.sca.contribution.resource.ResourceImport
+org.apache.tuscany.sca.contribution.resource.impl.ResourceExportProcessor;qname=http://www.osoa.org/xmlns/sca/1.0#export.resource,model=org.apache.tuscany.sca.contribution.resource.ResourceExport
diff --git a/java/sca/modules/contribution-resource/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver b/java/sca/modules/contribution-resource/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver
new file mode 100644
index 0000000000..08d2b1c338
--- /dev/null
+++ b/java/sca/modules/contribution-resource/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver
@@ -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.resource.impl.ArtifactModelResolver;model=org.apache.tuscany.sca.contribution.Artifact \ No newline at end of file
diff --git a/java/sca/modules/contribution-resource/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resource.ResourceImportExportFactory b/java/sca/modules/contribution-resource/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resource.ResourceImportExportFactory
new file mode 100644
index 0000000000..d39a5065c2
--- /dev/null
+++ b/java/sca/modules/contribution-resource/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resource.ResourceImportExportFactory
@@ -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.resource.impl.ResourceImportExportFactoryImpl
diff --git a/java/sca/modules/contribution-resource/src/main/resources/contribution-resource-validation-messages.properties b/java/sca/modules/contribution-resource/src/main/resources/contribution-resource-validation-messages.properties
new file mode 100644
index 0000000000..58ee8153f8
--- /dev/null
+++ b/java/sca/modules/contribution-resource/src/main/resources/contribution-resource-validation-messages.properties
@@ -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.
+#
+#
+AttributeURIMissing = Attribute 'uri' is missing
+
diff --git a/java/sca/modules/contribution-resource/src/test/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceExportProcessorTestCase.java b/java/sca/modules/contribution-resource/src/test/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceExportProcessorTestCase.java
new file mode 100644
index 0000000000..52ec0b4cfc
--- /dev/null
+++ b/java/sca/modules/contribution-resource/src/test/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceExportProcessorTestCase.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.resource.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.processor.ExtensibleStAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint;
+import org.apache.tuscany.sca.contribution.resource.ResourceExport;
+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 ResourceExportProcessorTestCase {
+
+ private static final String VALID_XML =
+ "<?xml version=\"1.0\" encoding=\"ASCII\"?>" + "<export.resource xmlns=\"http://www.osoa.org/xmlns/sca/1.0\" xmlns:ns=\"http://ns\" uri=\"helloworld/HelloWorldService.componentType\"/>";
+
+ private static final String INVALID_XML =
+ "<?xml version=\"1.0\" encoding=\"ASCII\"?>" + "<export.resource xmlns=\"http://www.osoa.org/xmlns/sca/1.0\" 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, 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));
+ ResourceExport resourceExport = (ResourceExport)staxProcessor.read(reader);
+ assertEquals("helloworld/HelloWorldService.componentType", resourceExport.getURI());
+ }
+
+ /**
+ * 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("AttributeURIMissing", problem.getMessageId());
+ }
+}
diff --git a/java/sca/modules/contribution-resource/src/test/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceImportProcessorTestCase.java b/java/sca/modules/contribution-resource/src/test/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceImportProcessorTestCase.java
new file mode 100644
index 0000000000..1fc439f073
--- /dev/null
+++ b/java/sca/modules/contribution-resource/src/test/java/org/apache/tuscany/sca/contribution/resource/impl/ResourceImportProcessorTestCase.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.resource.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.processor.ExtensibleStAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
+import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint;
+import org.apache.tuscany.sca.contribution.resource.ResourceImport;
+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 ResourceImportProcessorTestCase {
+
+ private static final String VALID_XML =
+ "<?xml version=\"1.0\" encoding=\"ASCII\"?>" + "<import.resource xmlns=\"http://www.osoa.org/xmlns/sca/1.0\" xmlns:ns=\"http://ns\" uri=\"helloworld/HelloWorldService.componentType\" location=\"sca://contributions/001\"/>";
+
+ private static final String INVALID_XML =
+ "<?xml version=\"1.0\" encoding=\"ASCII\"?>" + "<import.resource xmlns=\"http://www.osoa.org/xmlns/sca/1.0\" 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));
+ ResourceImport namespaceImport = (ResourceImport)staxProcessor.read(reader);
+ assertEquals("helloworld/HelloWorldService.componentType", namespaceImport.getURI());
+ assertEquals("sca://contributions/001", namespaceImport.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("AttributeURIMissing", problem.getMessageId());
+ }
+}
diff --git a/java/sca/modules/contribution-xml/LICENSE b/java/sca/modules/contribution-xml/LICENSE
new file mode 100644
index 0000000000..8aa906c321
--- /dev/null
+++ b/java/sca/modules/contribution-xml/LICENSE
@@ -0,0 +1,205 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+
diff --git a/java/sca/modules/contribution-xml/META-INF/MANIFEST.MF b/java/sca/modules/contribution-xml/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..4f8d3ee0f8
--- /dev/null
+++ b/java/sca/modules/contribution-xml/META-INF/MANIFEST.MF
@@ -0,0 +1,34 @@
+Manifest-Version: 1.0
+Export-Package: org.apache.tuscany.sca.contribution.xml;uses:="org.apa
+ che.tuscany.sca.assembly,org.apache.tuscany.sca.core,org.apache.tusca
+ ny.sca.contribution,org.apache.tuscany.sca.monitor,javax.xml.namespac
+ e,javax.xml.stream,org.apache.tuscany.sca.contribution.resolver,org.a
+ pache.tuscany.sca.contribution.processor";version="1.4"
+Private-Package: org.apache.tuscany.sca.contribution.processor.xml;ver
+ sion="1.4"
+Tool: Bnd-0.0.255
+Bundle-Name: Apache Tuscany SCA XML Contribution Model
+Created-By: 1.6.0_07 (Sun Microsystems Inc.)
+Bundle-Vendor: The Apache Software Foundation
+Bundle-Version: 1.4
+Bnd-LastModified: 1225397199187
+Bundle-ManifestVersion: 2
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-Description: Apache Tuscany SCA XML Contribution Model
+Import-Package: javax.xml.namespace,
+ javax.xml.parsers,
+ javax.xml.stream,
+ org.apache.tuscany.sca.assembly;version="1.4",
+ org.apache.tuscany.sca.contribution;version="1.4",
+ org.apache.tuscany.sca.contribution.processor;version="1.4",
+ org.apache.tuscany.sca.contribution.resolver;version="1.4",
+ org.apache.tuscany.sca.contribution.xml;version="1.4",
+ org.apache.tuscany.sca.core;version="1.4",
+ org.apache.tuscany.sca.monitor;version="1.4",
+ org.apache.tuscany.sca.policy;version="1.4.0",
+
+ org.w3c.dom,
+ org.w3c.dom.traversal
+Bundle-SymbolicName: org.apache.tuscany.sca.contribution.xml
+Bundle-DocURL: http://www.apache.org/
+
diff --git a/java/sca/modules/contribution-xml/NOTICE b/java/sca/modules/contribution-xml/NOTICE
new file mode 100644
index 0000000000..fdfa0e9faa
--- /dev/null
+++ b/java/sca/modules/contribution-xml/NOTICE
@@ -0,0 +1,6 @@
+${pom.name}
+Copyright (c) 2005 - 2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
diff --git a/java/sca/modules/contribution-xml/pom.xml b/java/sca/modules/contribution-xml/pom.xml
new file mode 100644
index 0000000000..eaeacd65e3
--- /dev/null
+++ b/java/sca/modules/contribution-xml/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-modules</artifactId>
+ <version>1.4-EQUINOX-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>tuscany-contribution-xml</artifactId>
+ <name>Apache Tuscany SCA XML Contribution Model</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-contribution</artifactId>
+ <version>1.4-EQUINOX-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.codehaus.woodstox</groupId>
+ <artifactId>wstx-asl</artifactId>
+ <version>3.2.4</version>
+ <scope>runtime</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>stax</groupId>
+ <artifactId>stax-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyAttributeProcessor.java b/java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyAttributeProcessor.java
new file mode 100644
index 0000000000..503a9c96d2
--- /dev/null
+++ b/java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyAttributeProcessor.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.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.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<String> {
+ private static final QName ANY_ATTRIBUTE = new QName("http://www.w3.org/2001/XMLSchema", "anyAttribute");
+
+ public AnyAttributeProcessor(FactoryExtensionPoint modelFactories, Monitor monitor) {
+
+ }
+
+ public QName getArtifactType() {
+ return ANY_ATTRIBUTE;
+ }
+
+ public Class<String> getModelType() {
+ return String.class;
+ }
+
+ public String read(QName attributeName, XMLStreamReader reader) throws ContributionReadException, XMLStreamException {
+ return reader.getAttributeValue(attributeName.getNamespaceURI(), attributeName.getLocalPart());
+ }
+
+ public void write(String value, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException {
+ writer.setPrefix(ANY_ATTRIBUTE.getPrefix(), ANY_ATTRIBUTE.getNamespaceURI());
+ writer.writeAttribute(ANY_ATTRIBUTE.getLocalPart(), value);
+ }
+
+
+ public void resolve(String arg0, ModelResolver arg1) throws ContributionResolveException {
+
+ }
+}
diff --git a/java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyElementProcessor.java b/java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyElementProcessor.java
new file mode 100644
index 0000000000..38da7740cd
--- /dev/null
+++ b/java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/processor/xml/AnyElementProcessor.java
@@ -0,0 +1,309 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+
+import java.util.ArrayList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.processor.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.processor.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;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.traversal.DocumentTraversal;
+import org.w3c.dom.traversal.NodeFilter;
+import org.w3c.dom.traversal.NodeIterator;
+import org.w3c.dom.traversal.TreeWalker;
+
+public class AnyElementProcessor implements StAXArtifactProcessor<Object> {
+ private static final QName ANY_ELEMENT = new QName("http://www.w3.org/2001/XMLSchema", "anyElement");
+
+ private static final Logger logger = Logger.getLogger(AnyElementProcessor.class.getName());
+ private DocumentBuilderFactory documentBuilderFactory;
+ private Document document;
+ private Monitor monitor;
+
+ public AnyElementProcessor(FactoryExtensionPoint modelFactories, Monitor monitor) {
+ documentBuilderFactory = modelFactories.getFactory(DocumentBuilderFactory.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 the DOM
+ * @param reader
+ * @param name
+ * @return
+ * @throws XMLStreamException
+ */
+ public Object read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException {
+
+ int event = reader.getEventType();
+ int level = 0;
+ ArrayList<String> elementList = new ArrayList<String>();
+ document = createDocument();
+
+ QName name = reader.getName();
+
+ while(reader.hasNext()){
+ switch(event){
+ case START_ELEMENT:
+ elementList.add(reader.getName().getLocalPart());
+ if(level == 0){
+ generateDOM(reader,null);
+ level++;
+ }
+ else{
+ generateDOM(reader,elementList.get(elementList.size()-2).toString());
+ }
+
+ break;
+ case END_ELEMENT:
+ elementList.remove(reader.getName().getLocalPart());
+ }
+ if(reader.hasNext()){
+ event = reader.next();
+ }
+
+ if(event == START_ELEMENT || event == END_ELEMENT){
+ if(reader.getName().equals(name)){
+ break;
+ }
+ }
+ }
+ return document;
+ }
+
+ /**
+ * Writes unknown portions back to the writer
+ * @param model
+ * @param writer
+ */
+ public void write(Object model, XMLStreamWriter writer) {
+
+ if( ! (model instanceof Document)) {
+ return;
+ }
+
+ Document doc = (Document)model;
+ try{
+ DocumentTraversal traversal = (DocumentTraversal)doc;
+ TreeWalker walker = traversal.createTreeWalker(doc.getDocumentElement(),NodeFilter.SHOW_ALL, null, true);
+ writeDOM(walker,writer);
+ }
+ catch(Exception e){
+ if (logger.isLoggable(Level.SEVERE)) {
+ logger.log(Level.SEVERE, "Document not created ");
+ }
+ error("Document not created",document,e);
+ }
+ }
+
+ public void resolve(Object arg0, ModelResolver arg1) throws ContributionResolveException {
+
+ }
+
+ /**
+ * Method to generate the DOM
+ * @param reader
+ * @param parent
+ * @throws Exception
+ */
+ //private void generateDOM(String elementText, String parent) {
+ private void generateDOM(XMLStreamReader reader, String parent) {
+ try{
+ String elePrefix = reader.getPrefix();
+ String eleQName = reader.getLocalName();
+ if (elePrefix != null && elePrefix.length() != 0) {
+ eleQName = elePrefix + ":" + eleQName;
+ }
+
+ Element element = document.createElementNS(reader.getNamespaceURI(), eleQName);
+
+ int attributeCount = reader.getAttributeCount();
+ for(int i = 0;i < attributeCount;i++){
+ String ns = reader.getAttributeNamespace(i);
+ String prefix = reader.getAttributePrefix(i);
+ String qname = reader.getAttributeLocalName(i);
+ String value = reader.getAttributeValue(i);
+ if (prefix != null && prefix.length() != 0) {
+ qname = prefix + ":" + qname;
+ }
+ element.setAttributeNS(ns,qname,value);
+ }
+ if(parent == null){
+ if(document != null){
+ document.appendChild(element);
+ }
+ else{
+ if (logger.isLoggable(Level.SEVERE)) {
+ logger.log(Level.SEVERE, "Document not created ");
+ }
+ error("Document not created",document,element);
+ }
+ }
+ else{
+ Node parentNode = getParentNode(document,parent);
+ if(parentNode != null){
+ parentNode.appendChild(element);
+ }
+ else{
+ if (logger.isLoggable(Level.SEVERE)) {
+ logger.log(Level.SEVERE, "Parent node not found");
+ }
+ error("Parent node not found",document,parentNode.getNodeName());
+ }
+ }
+ }
+ catch(Exception e){
+ e.printStackTrace();
+ if (logger.isLoggable(Level.SEVERE)) {
+ logger.log(Level.SEVERE, "Document not created ");
+ }
+ error("Document not created",document,e);
+ }
+ }
+
+ /**
+ * Method to create an empty document
+ * @return
+ */
+ private Document createDocument() {
+ try {
+ document = documentBuilderFactory.newDocumentBuilder().newDocument();
+ return document;
+ } catch (ParserConfigurationException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * Method to traverse the DOM structure and write the elements
+ * @param walker
+ * @param writer
+ * @throws XMLStreamException
+ */
+ private void writeDOM(TreeWalker walker,XMLStreamWriter writer) throws XMLStreamException {
+
+ Node parent = walker.getCurrentNode();
+
+ writer.writeStartElement(parent.getPrefix(), parent.getLocalName(), parent.getNamespaceURI());
+
+ NamedNodeMap attributes = parent.getAttributes();
+
+ for(int i = 0;i<attributes.getLength();i++){
+ writer.writeAttribute(attributes.item(i).getPrefix(), attributes.item(i).getNamespaceURI(), attributes.item(i).getLocalName(), attributes.item(i).getNodeValue());
+ }
+
+ for (Node n = walker.firstChild();n != null;n = walker.nextSibling()) {
+ writeDOM(walker,writer);
+ }
+ writer.writeEndElement();
+
+ walker.setCurrentNode(parent);
+ }
+
+ /**
+ * Method to get the Parent node out of the DOM structure
+ * @param doc
+ * @param parent
+ * @return
+ */
+ private Node getParentNode(Node doc,String parent) {
+ Node parentNode = null;
+ try{
+ DocumentTraversal traversal = (DocumentTraversal)doc;
+
+ CharSequence prefixChar = ":";
+ NodeIterator iterator = traversal.createNodeIterator(document.getDocumentElement(), NodeFilter.SHOW_ELEMENT, null, true);
+ for (Node n = iterator.nextNode(); n != null; n = iterator.nextNode()) {
+ String nodeName = n.getNodeName();
+ String[] str = null;
+ if(n.getNodeName().contains(prefixChar)){
+ str = nodeName.split(":");
+ nodeName = str[str.length-1];
+ }
+ if(parent.equalsIgnoreCase(nodeName)){
+ parentNode = n;
+ }
+ }
+ return parentNode;
+ }
+ catch(Exception e){
+ e.printStackTrace();
+ }
+ return parentNode;
+ }
+
+ /**
+ * Marshals exceptions into the monitor
+ *
+ * @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);
+ }
+ }
+
+ /**
+ * 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);
+ }
+ }
+
+}
diff --git a/java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionGeneratedMetadataDocumentProcessor.java b/java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionGeneratedMetadataDocumentProcessor.java
new file mode 100644
index 0000000000..ff7bf7068a
--- /dev/null
+++ b/java/sca/modules/contribution-xml/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 "sca-contribution-generated.xml";
+ }
+}
diff --git a/java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataDocumentProcessor.java b/java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataDocumentProcessor.java
new file mode 100644
index 0000000000..c293649135
--- /dev/null
+++ b/java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataDocumentProcessor.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.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.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(XMLInputFactory.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 "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/java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataProcessor.java b/java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataProcessor.java
new file mode 100644
index 0000000000..02c5d48eb3
--- /dev/null
+++ b/java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataProcessor.java
@@ -0,0 +1,216 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.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.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 SCA10_NS = "http://www.osoa.org/xmlns/sca/1.0";
+
+ private static final QName CONTRIBUTION_QNAME = new QName(SCA10_NS, "contribution");
+ private static final QName DEPLOYABLE_QNAME = new QName(SCA10_NS, "deployable");
+
+ private final AssemblyFactory assemblyFactory;
+ private final ContributionFactory contributionFactory;
+
+ private final StAXArtifactProcessor<Object> extensionProcessor;
+ private Monitor monitor;
+
+ public ContributionMetadataProcessor(AssemblyFactory assemblyFactory,
+ ContributionFactory contributionFactory,
+ StAXArtifactProcessor<Object> extensionProcessor,
+ Monitor monitor) {
+ this.assemblyFactory = assemblyFactory;
+ this.contributionFactory = contributionFactory;
+ this.extensionProcessor = extensionProcessor;
+ 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);
+ }
+ }
+
+ public ContributionMetadataProcessor(FactoryExtensionPoint modelFactories,
+ StAXArtifactProcessor<Object> extensionProcessor,
+ Monitor monitor) {
+ this.assemblyFactory = modelFactories.getFactory(AssemblyFactory.class);
+ this.contributionFactory = modelFactories.getFactory(ContributionFactory.class);
+ this.extensionProcessor = extensionProcessor;
+ this.monitor = monitor;
+ }
+
+
+ public QName getArtifactType() {
+ return CONTRIBUTION_QNAME;
+ }
+
+ public Class<ContributionMetadata> getModelType() {
+ return ContributionMetadata.class;
+ }
+
+ public ContributionMetadata read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException {
+ ContributionMetadata contribution = null;
+ QName name = null;
+
+ 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);
+
+ } 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);
+ }
+ }
+ }
+ break;
+
+ case XMLStreamConstants.END_ELEMENT:
+ if (CONTRIBUTION_QNAME.equals(reader.getName())) {
+ return contribution;
+ }
+ break;
+ }
+
+ //Read the next element
+ if (reader.hasNext()) {
+ reader.next();
+ }
+ }
+
+ return contribution;
+ }
+
+ public void write(ContributionMetadata contribution, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException {
+
+ // Write <contribution>
+ writeStartDocument(writer, CONTRIBUTION_QNAME.getNamespaceURI(), CONTRIBUTION_QNAME.getLocalPart());
+
+ // 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);
+ }
+ }
+
+ contribution.setUnresolved(false);
+ }
+}
diff --git a/java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionModelResolver.java b/java/sca/modules/contribution-xml/src/main/java/org/apache/tuscany/sca/contribution/xml/ContributionModelResolver.java
new file mode 100644
index 0000000000..ddc768b61c
--- /dev/null
+++ b/java/sca/modules/contribution-xml/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/java/sca/modules/contribution-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor b/java/sca/modules/contribution-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor
new file mode 100644
index 0000000000..b69ea1e135
--- /dev/null
+++ b/java/sca/modules/contribution-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Implementation class for the artifact processor extension
+org.apache.tuscany.sca.contribution.xml.ContributionMetadataProcessor;qname=http://www.osoa.org/xmlns/sca/1.0#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
diff --git a/java/sca/modules/contribution-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor b/java/sca/modules/contribution-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor
new file mode 100644
index 0000000000..23adab56b9
--- /dev/null
+++ b/java/sca/modules/contribution-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor
@@ -0,0 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Implementation class for the artifact processor extension
+org.apache.tuscany.sca.contribution.xml.ContributionMetadataDocumentProcessor;type=sca-contribution.xml,model=org.apache.tuscany.sca.contribution.ContributionMetadata
+org.apache.tuscany.sca.contribution.xml.ContributionGeneratedMetadataDocumentProcessor;type=sca-contribution-generated.xml
diff --git a/java/sca/modules/contribution-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver b/java/sca/modules/contribution-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver
new file mode 100644
index 0000000000..68030bf6e6
--- /dev/null
+++ b/java/sca/modules/contribution-xml/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolver
@@ -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.xml.ContributionModelResolver;model=org.apache.tuscany.sca.contribution.Contribution
diff --git a/java/sca/modules/contribution-xml/src/main/resources/contribution-xml-validation-messages.properties b/java/sca/modules/contribution-xml/src/main/resources/contribution-xml-validation-messages.properties
new file mode 100644
index 0000000000..3e1a0187fe
--- /dev/null
+++ b/java/sca/modules/contribution-xml/src/main/resources/contribution-xml-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.
+#
+#
+XMLStreamException = XMLStreamException occured due to:
+IOException = IOException occured due to:
+AttributeCompositeMissing = Attribute 'composite' is missing \ No newline at end of file
diff --git a/java/sca/modules/contribution-xml/src/test/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataProcessorTestCase.java b/java/sca/modules/contribution-xml/src/test/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataProcessorTestCase.java
new file mode 100644
index 0000000000..ddb660a139
--- /dev/null
+++ b/java/sca/modules/contribution-xml/src/test/java/org/apache/tuscany/sca/contribution/xml/ContributionMetadataProcessorTestCase.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.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://www.osoa.org/xmlns/sca/1.0\" xmlns:ns=\"http://ns\">"
+ + "<deployable composite=\"ns:Composite1\"/>"
+ + "<deployable composite=\"ns:Composite2\"/>"
+ + "</contribution>";
+
+ private static final String INVALID_XML =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<contribution xmlns=\"http://www.osoa.org/xmlns/sca/1.0\" 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());
+ }
+
+ @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/java/sca/modules/contribution/LICENSE b/java/sca/modules/contribution/LICENSE
new file mode 100644
index 0000000000..8aa906c321
--- /dev/null
+++ b/java/sca/modules/contribution/LICENSE
@@ -0,0 +1,205 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+
diff --git a/java/sca/modules/contribution/META-INF/MANIFEST.MF b/java/sca/modules/contribution/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..d0a5651923
--- /dev/null
+++ b/java/sca/modules/contribution/META-INF/MANIFEST.MF
@@ -0,0 +1,46 @@
+Manifest-Version: 1.0
+Export-Package: org.apache.tuscany.sca.contribution.scanner;uses:="org
+ .apache.tuscany.sca.contribution.processor,org.apache.tuscany.sca.ext
+ ensibility";version="1.4",org.apache.tuscany.sca.contribution.resolve
+ r;uses:="org.apache.tuscany.sca.assembly,org.apache.tuscany.sca.core,
+ org.apache.tuscany.sca.contribution,org.apache.tuscany.sca.extensibil
+ ity";version="1.4",org.apache.tuscany.sca.contribution.processor;uses
+ :="org.apache.tuscany.sca.assembly,org.apache.tuscany.sca.core,org.ap
+ ache.tuscany.sca.policy,org.apache.tuscany.sca.monitor,org.apache.tus
+ cany.sca.extensibility,org.xml.sax,javax.xml.namespace,javax.xml.stre
+ am,javax.xml.stream.util,javax.xml.transform,org.apache.tuscany.sca.c
+ ontribution.resolver,javax.xml.transform.stream,javax.xml.validation,
+ org.xml.sax.helpers";version="1.4",org.apache.tuscany.sca.contributio
+ n;uses:="org.apache.tuscany.sca.assembly,org.apache.tuscany.sca.contr
+ ibution.resolver";version="1.4"
+Private-Package: org.apache.tuscany.sca.contribution.impl;version="1.4
+ "
+Tool: Bnd-0.0.255
+Bundle-Name: Apache Tuscany SCA Contribution Model
+Created-By: 1.6.0_07 (Sun Microsystems Inc.)
+Bundle-Vendor: The Apache Software Foundation
+Bundle-Version: 1.4
+Bnd-LastModified: 1225397102546
+Bundle-ManifestVersion: 2
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-Description: Apache Tuscany SCA Contribution Model
+Import-Package: javax.xml.namespace,
+ javax.xml.stream,
+ javax.xml.stream.util,
+ javax.xml.transform,
+ javax.xml.transform.stream,
+ javax.xml.validation,
+ org.apache.tuscany.sca.assembly;version="1.4",
+ org.apache.tuscany.sca.contribution;version="1.4",
+ org.apache.tuscany.sca.contribution.processor;version="1.4",
+ org.apache.tuscany.sca.contribution.resolver;version="1.4",
+ org.apache.tuscany.sca.contribution.scanner;version="1.4",
+ org.apache.tuscany.sca.core;version="1.4",
+ org.apache.tuscany.sca.extensibility;version="1.4",
+ org.apache.tuscany.sca.monitor;version="1.4",
+ org.apache.tuscany.sca.policy;version="1.4",
+ org.xml.sax,
+ org.xml.sax.helpers
+Bundle-SymbolicName: org.apache.tuscany.sca.contribution
+Bundle-DocURL: http://www.apache.org/
+
diff --git a/java/sca/modules/contribution/NOTICE b/java/sca/modules/contribution/NOTICE
new file mode 100644
index 0000000000..fdfa0e9faa
--- /dev/null
+++ b/java/sca/modules/contribution/NOTICE
@@ -0,0 +1,6 @@
+${pom.name}
+Copyright (c) 2005 - 2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
diff --git a/java/sca/modules/contribution/pom.xml b/java/sca/modules/contribution/pom.xml
new file mode 100644
index 0000000000..e2cea9df57
--- /dev/null
+++ b/java/sca/modules/contribution/pom.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-modules</artifactId>
+ <version>1.4-EQUINOX-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>tuscany-contribution</artifactId>
+ <name>Apache Tuscany SCA Contribution Model</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-assembly</artifactId>
+ <version>1.4-EQUINOX-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-extensibility</artifactId>
+ <version>1.4-EQUINOX-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.xml.stream</groupId>
+ <artifactId>stax-api</artifactId>
+ <version>1.0-2</version>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java
new file mode 100644
index 0000000000..7400501d85
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+import org.apache.tuscany.sca.assembly.Base;
+
+
+/**
+ * Represents an artifact in an SCA contribution.
+ *
+ * @version $Rev$ $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
+ */
+ Object getModel();
+
+ /**
+ * Sets the in-memory model representing the artifact.
+ *
+ * @param model The model object
+ */
+ void setModel(Object model);
+
+ /**
+ * Returns the contents of the artifact cached here.
+ * @return the contents of the artifact
+ */
+ byte[] getContents();
+
+ /**
+ * Sets the contents of the artifact.
+ * @param contents the contents of the artifact
+ */
+ void setContents(byte[] contents);
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Constants.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Constants.java
new file mode 100644
index 0000000000..4cf20125b9
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Constants.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;
+
+/**
+ * Constants used in SCA contribution.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface Constants {
+ String SCA10_NS = "http://www.osoa.org/xmlns/sca/1.0";
+ String SCA10_TUSCANY_NS = "http://tuscany.apache.org/xmlns/sca/1.0";
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.java
new file mode 100644
index 0000000000..81b0b08b9d
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java
new file mode 100644
index 0000000000..80dece4496
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * The representation of an SCA contribution.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface Contribution extends Artifact {
+
+ /**
+ * Default location of contribution metadata in an SCA contribution.
+ */
+ String SCA_CONTRIBUTION_META = "META-INF/sca-contribution.xml";
+
+ /**
+ * Default location of a generated contribution metadata in an SCA contribution.
+ */
+ String SCA_CONTRIBUTION_GENERATED_META = "META-INF/sca-contribution-generated.xml";
+
+ /**
+ * Default location of deployable composites in an SCA contribution.
+ */
+ String SCA_CONTRIBUTION_DEPLOYABLES = "META-INF/sca-deployables/";
+
+
+ /**
+ * Returns a list of exports based on the contribution metadata.
+ *
+ * @return The list of exports in this contribution
+ */
+ List<Export> getExports();
+
+ /**
+ * Returns a list of imports based on the contribution metadata.
+ *
+ * @return The list of imports in this contribution
+ */
+ List<Import> getImports();
+
+ /**
+ * Returns the list of deployable composites in the contribution.
+ *
+ * @return The list of deployable composites
+ */
+ List<Composite> getDeployables();
+
+ /**
+ * Returns the list of artifacts in the contribution.
+ *
+ * @return The list of artifacts in the contribution
+ */
+ List<Artifact> getArtifacts();
+
+ /**
+ * Returns the model resolver for the models representing the artifacts
+ * visible in the scope of this contribution.
+ *
+ * @return The model resolver
+ */
+ ModelResolver getModelResolver();
+
+ /**
+ * Sets the model resolver for the models representing the artifacts
+ * visible in the scope of this contribution.
+ *
+ * @param modelResolver The model resolver
+ */
+ void setModelResolver(ModelResolver modelResolver);
+
+ /**
+ * Returns the 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);
+
+} \ No newline at end of file
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java
new file mode 100644
index 0000000000..67c9a05a0b
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.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 a deployedArtifact model object
+ *
+ * @return The new deployedArtifact model object
+ */
+ @Deprecated
+ DeployedArtifact createDeployedArtifact();
+
+ /**
+ * Create an artifact model object
+ *
+ * @return The new artifact model object
+ */
+ Artifact createArtifact();
+
+ /**
+ * 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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionMetadata.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionMetadata.java
new file mode 100644
index 0000000000..4043fb9eda
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionMetadata.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;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Base;
+import org.apache.tuscany.sca.assembly.Composite;
+
+/**
+ * The representation of SCA contribution metadata.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ContributionMetadata extends Base {
+
+ /**
+ * 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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultContributionFactory.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultContributionFactory.java
new file mode 100644
index 0000000000..98954c288a
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultExport.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultExport.java
new file mode 100644
index 0000000000..b2eddb8336
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultImport.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultImport.java
new file mode 100644
index 0000000000..20798dcd17
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DeployedArtifact.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DeployedArtifact.java
new file mode 100644
index 0000000000..ffe190132c
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DeployedArtifact.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+/**
+ * Representation of a deployed artifact
+ *
+ * @version $Rev$ $Date$
+ */
+@Deprecated
+public interface DeployedArtifact extends Artifact {
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java
new file mode 100644
index 0000000000..bfa16b1ce3
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * The representation of an export.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface Export {
+
+ /**
+ * Returns the model resolver for the models representing artifacts
+ * made available by this export.
+ *
+ * @return The model resolver
+ */
+ ModelResolver getModelResolver();
+
+ /**
+ * Sets the model resolver for the models representing artifacts
+ * made available by this export.
+ *
+ * @param modelResolver
+ */
+ void setModelResolver(ModelResolver modelResolver);
+
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java
new file mode 100644
index 0000000000..35076f55a7
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+
+/**
+ * The representation of an import.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface Import {
+
+ /**
+ * Returns the model resolver for the models representing artifacts
+ * made available by this import.
+ *
+ * @return The model resolver
+ */
+ ModelResolver getModelResolver();
+
+ /**
+ * Sets the model resolver for the models representing artifacts
+ * made available by this import.
+ *
+ * @param modelResolver The model resolver
+ */
+ void setModelResolver(ModelResolver modelResolver);
+
+ /**
+ * Verify that a specific export actually exports what is being imported.
+ *
+ * @param export The Exported being verified
+ * @return true/false
+ */
+ boolean match(Export export);
+
+} \ No newline at end of file
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/PackageType.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/PackageType.java
new file mode 100644
index 0000000000..c0dd5431d7
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/PackageType.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+/**
+ * Constants for the main supported contribution package types.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface PackageType {
+
+ /**
+ * Java compressed contribution package
+ */
+ String JAR = "application/x-compressed";
+
+ /**
+ * Filesystem folder contribution package
+ */
+ String FOLDER = "application/vnd.tuscany.folder";
+
+
+ String BUNDLE = "application/osgi.bundle";
+
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ArtifactImpl.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ArtifactImpl.java
new file mode 100644
index 0000000000..881987f622
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ArtifactImpl.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.impl;
+
+import org.apache.tuscany.sca.contribution.Artifact;
+
+
+/**
+ * The model representing an artifact in a contribution.
+ *
+ * @version $Rev$ $Date$
+ */
+class ArtifactImpl implements Artifact {
+ private String uri;
+ private String location;
+ private Object model;
+ private boolean unresolved;
+ private byte[] contents;
+
+ ArtifactImpl() {
+ }
+
+ public String getLocation() {
+ return location;
+ }
+
+ public void setLocation(String location) {
+ this.location = location;
+ }
+
+ public String getURI() {
+ return uri;
+ }
+
+ public void setURI(String uri) {
+ this.uri = uri;
+ }
+
+ public Object getModel() {
+ return model;
+ }
+
+ public void setModel(Object model) {
+ this.model = model;
+ }
+
+ public byte[] getContents() {
+ return contents;
+ }
+
+ public void setContents(byte[] contents) {
+ this.contents = contents;
+ }
+
+ public boolean isUnresolved() {
+ return unresolved;
+ }
+
+ public void setUnresolved(boolean unresolved) {
+ this.unresolved = unresolved;
+ }
+
+ @Override
+ public int hashCode() {
+ return uri.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ } else {
+ if (obj instanceof Artifact) {
+ return uri.equals(((Artifact)obj).getURI());
+ } else {
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Artifact:" + uri + "\n" +
+ "at: " + location;
+ }
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionFactoryImpl.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionFactoryImpl.java
new file mode 100644
index 0000000000..c678c2eaef
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionFactoryImpl.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.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;
+import org.apache.tuscany.sca.contribution.DeployedArtifact;
+
+
+/**
+ * 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();
+ }
+
+ @Deprecated
+ public DeployedArtifact createDeployedArtifact() {
+ class DeployedArtifactImpl extends ArtifactImpl implements DeployedArtifact {
+ }
+ return new DeployedArtifactImpl();
+ }
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionImpl.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionImpl.java
new file mode 100644
index 0000000000..0b41016caa
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionImpl.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.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.contribution.Artifact;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.Export;
+import org.apache.tuscany.sca.contribution.Import;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * The representation of a deployed contribution
+ *
+ * @version $Rev$ $Date$
+ */
+class ContributionImpl implements Contribution {
+ private String uri;
+ private String location;
+ private Object model;
+ private byte[] contents;
+ private boolean unresolved;
+ private List<Export> exports = new ArrayList<Export>();
+ private List<Import> imports = new ArrayList<Import>();
+ private List<Composite> deployables = new ArrayList<Composite>();
+ private List<Artifact> artifacts = new ArrayList<Artifact>();
+ private List<Contribution> dependencies = new ArrayList<Contribution>();
+ private ModelResolver modelResolver;
+
+ // FIXME remove this dependency on Java ClassLoaders
+ private ClassLoader classLoader;
+
+ ContributionImpl() {
+ }
+
+ public String getLocation() {
+ return this.location;
+ }
+
+ public void setLocation(String location) {
+ this.location = location;
+ }
+
+ //FIXME Remove dependency on Java ClassLoaders
+ public ClassLoader getClassLoader() {
+ return classLoader;
+ }
+
+ //FIXME Remove dependency on Java ClassLoaders
+ public void setClassLoader(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+
+ public String getURI() {
+ return this.uri;
+ }
+
+ public void setURI(String uri) {
+ this.uri = uri;
+ }
+
+ public Object getModel() {
+ return model;
+ }
+
+ public void setModel(Object model) {
+ this.model = model;
+ }
+
+ public byte[] getContents() {
+ return contents;
+ }
+
+ public void setContents(byte[] contents) {
+ this.contents = contents;
+ }
+
+ public boolean isUnresolved() {
+ return unresolved;
+ }
+
+ public void setUnresolved(boolean unresolved) {
+ this.unresolved = unresolved;
+ }
+
+ public ModelResolver getModelResolver() {
+ return modelResolver;
+ }
+
+ public void setModelResolver(ModelResolver modelResolver) {
+ this.modelResolver = modelResolver;
+ }
+
+ public List<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;
+ }
+
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionMetadataImpl.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionMetadataImpl.java
new file mode 100644
index 0000000000..75b12b1260
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/ContributionMetadataImpl.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Composite;
+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 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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultExportImpl.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultExportImpl.java
new file mode 100644
index 0000000000..e67395337a
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultExportImpl.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.impl;
+
+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 implements DefaultExport {
+ private ModelResolver modelResolver;
+
+ protected DefaultExportImpl() {
+ super();
+ }
+
+ public ModelResolver getModelResolver() {
+ return modelResolver;
+ }
+
+ public void setModelResolver(ModelResolver modelResolver) {
+ this.modelResolver = modelResolver;
+ }
+
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultImportImpl.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultImportImpl.java
new file mode 100644
index 0000000000..17c09f2cbc
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/impl/DefaultImportImpl.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.impl;
+
+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 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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java
new file mode 100644
index 0000000000..5be0b188f4
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessorExtensionPoint.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..029df61f0f
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessorExtensionPoint.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+/**
+ * An extension point for artifact processors.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ArtifactProcessorExtensionPoint<P extends ArtifactProcessor> {
+
+ /**
+ * Add an artifact processor.
+ *
+ * @param artifactProcessor The artifact processor to add
+ */
+ void addArtifactProcessor(P artifactProcessor);
+
+ /**
+ * Remove an artifact processor.
+ *
+ * @param artifactProcessor The artifact processor to remove
+ */
+ void removeArtifactProcessor(P artifactProcessor);
+
+ /**
+ * Returns the processor associated with the given artifact type.
+ *
+ * @param artifactType An artifact type
+ * @return The processor associated with the given artifact type
+ */
+ P getProcessor(Object artifactType);
+
+ /**
+ * Returns the processor associated with the given model type.
+ *
+ * @param modelType A model type
+ * @return The processor associated with the given model type
+ */
+ P getProcessor(Class<?> modelType);
+
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java
new file mode 100644
index 0000000000..f23797a831
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java
@@ -0,0 +1,539 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import static javax.xml.stream.XMLStreamConstants.END_ELEMENT;
+import static javax.xml.stream.XMLStreamConstants.START_ELEMENT;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+
+/**
+ * A base class with utility methods for the other artifact processors in this module.
+ *
+ * @version $Rev$ $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);
+ }
+ }
+
+ /**
+ * Represents an XML attribute that needs to be written to a document.
+ */
+ public static class XAttr {
+
+ private static final String SCA10_NS = "http://www.osoa.org/xmlns/sca/1.0";
+
+ private String uri = SCA10_NS;
+ private String name;
+ private Object value;
+
+ public XAttr(String uri, String name, String value) {
+ this.uri = uri;
+ this.name = name;
+ this.value = value;
+ }
+
+ public XAttr(String name, String value) {
+ this(null, name, value);
+ }
+
+ public XAttr(String uri, String name, List<?> values) {
+ this.uri = uri;
+ this.name = name;
+ this.value = values;
+ }
+
+ public XAttr(String name, List<?> values) {
+ this(null, name, values);
+ }
+
+ public XAttr(String uri, String name, Boolean value) {
+ this.uri = uri;
+ this.name = name;
+ this.value = value;
+ }
+
+ public XAttr(String name, Boolean value) {
+ this(null, name, value);
+ }
+
+ public XAttr(String uri, String name, 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(SCA10_NS)) {
+ writer.writeAttribute(uri, name, str);
+ } else {
+ writer.writeAttribute(name,str);
+ }
+ }
+
+ /**
+ * Registers a prefix for the namespace of a QName or list of QNames
+ * @param writer
+ * @throws XMLStreamException
+ */
+ public void writePrefix(XMLStreamWriter writer) throws XMLStreamException {
+ if (value instanceof QName) {
+
+ // Write prefix for a single QName value
+ writeQNamePrefix(writer, (QName)value);
+
+ } else if (value instanceof List) {
+
+ // Write prefixes for a list of values
+ for (Object v: (List<?>)value) {
+ if (v instanceof QName) {
+ // Write prefix for a QName value
+ writeQNamePrefix(writer, (QName)v);
+
+ } else if (v instanceof XAttr) {
+ // Write prefix for an XAttr value
+ ((XAttr)v).writePrefix(writer);
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionException.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionException.java
new file mode 100644
index 0000000000..3b99eba586
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionReadException.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionReadException.java
new file mode 100644
index 0000000000..6fd7d0c91e
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionResolveException.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionResolveException.java
new file mode 100644
index 0000000000..fe1a09d398
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionRuntimeException.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionRuntimeException.java
new file mode 100644
index 0000000000..0039dd9f8b
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionWriteException.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ContributionWriteException.java
new file mode 100644
index 0000000000..286c9dc791
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..3c67a8c550
--- /dev/null
+++ b/java/sca/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> {
+ protected final Map<Object, P> processorsByArtifactType = new HashMap<Object, P>();
+ protected final Map<Class<?>, P> processorsByModelType = new HashMap<Class<?>, P>();
+
+ /**
+ * Constructs a new loader registry.
+ */
+ DefaultArtifactProcessorExtensionPoint() {
+ }
+
+ /**
+ * Returns the processor associated with the given artifact type.
+ *
+ * @param artifactType An artifact type
+ * @return The processor associated with the given artifact type
+ */
+ public P getProcessor(Object artifactType) {
+ return processorsByArtifactType.get(artifactType);
+ }
+
+ /**
+ * Returns the processor associated with the given model type.
+ *
+ * @param modelType A model type
+ * @return The processor associated with the given model type
+ */
+ public P getProcessor(Class<?> modelType) {
+ Class<?>[] classes = modelType.getInterfaces();
+ for (Class<?> c : classes) {
+ P processor = processorsByModelType.get(c);
+ if (processor != null) {
+ return processor;
+ }
+ }
+ return processorsByModelType.get(modelType);
+ }
+
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..d268c5b011
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java
@@ -0,0 +1,384 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.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.assembly.AssemblyFactory;
+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;
+import org.apache.tuscany.sca.policy.PolicyFactory;
+
+/**
+ * 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 StAXArtifactProcessor getProcessor(Class<?> modelType) {
+ loadArtifactProcessors();
+ return super.getProcessor(modelType);
+ }
+
+ @Override
+ public StAXArtifactProcessor getProcessor(Object artifactType) {
+ loadArtifactProcessors();
+ return super.getProcessor(artifactType);
+ }
+
+ /**
+ * Returns a QName object from a QName expressed as {ns}name
+ * or ns#name.
+ *
+ * @param qname
+ * @return
+ */
+ private static QName getQName(String qname) {
+ if (qname == null) {
+ return null;
+ }
+ qname = qname.trim();
+ if (qname.startsWith("{")) {
+ int h = qname.indexOf('}');
+ if (h != -1) {
+ return new QName(qname.substring(1, h), qname.substring(h + 1));
+ }
+ } else {
+ int h = qname.indexOf('#');
+ if (h != -1) {
+ return new QName(qname.substring(0, h), qname.substring(h + 1));
+ }
+ }
+ throw new IllegalArgumentException("Invalid qname: "+qname);
+ }
+
+ /**
+ * Lazily load artifact processors registered in the extension point.
+ */
+ private void loadArtifactProcessors() {
+ if (loaded)
+ return;
+
+ // Get the processor service declarations
+ Set<ServiceDeclaration> processorDeclarations;
+ try {
+ processorDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(StAXArtifactProcessor.class.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);
+ AssemblyFactory assemblyFactory = modelFactories.getFactory(AssemblyFactory.class);
+ PolicyFactory policyFactory = modelFactories.getFactory(PolicyFactory.class);
+ try {
+ Class<StAXArtifactProcessor> processorClass =
+ (Class<StAXArtifactProcessor>)processorDeclaration.loadClass();
+ Object modelFactory;
+ if (factoryName != null) {
+ Class<?> factoryClass = (Class<?>)processorDeclaration.loadClass(factoryName);
+ modelFactory = modelFactories.getFactory(factoryClass);
+ } else {
+ modelFactory = null;
+ }
+ Constructor<StAXArtifactProcessor> constructor =
+ processorClass.getConstructor(AssemblyFactory.class,
+ PolicyFactory.class,
+ QName.class,
+ Class.class,
+ Object.class,
+ Monitor.class);
+ processor =
+ constructor.newInstance(assemblyFactory,
+ policyFactory,
+ 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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXAttributeProcessorExtensionPoint.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXAttributeProcessorExtensionPoint.java
new file mode 100644
index 0000000000..bd38a609a6
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXAttributeProcessorExtensionPoint.java
@@ -0,0 +1,323 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.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 StAXAttributeProcessor getProcessor(Class<?> modelType) {
+ loadArtifactProcessors();
+ return 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 void loadArtifactProcessors() {
+ if (loaded)
+ return;
+
+ // Get the processor service declarations
+ Set<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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..402d4aa151
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.net.URI;
+import java.net.URL;
+import java.util.Map;
+import java.util.Set;
+
+import 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) {
+ processorsByArtifactType.put((Object)artifactProcessor.getArtifactType(), artifactProcessor);
+ }
+ if (artifactProcessor.getModelType() != null) {
+ processorsByModelType.put(artifactProcessor.getModelType(), artifactProcessor);
+ }
+ }
+
+ public void removeArtifactProcessor(URLArtifactProcessor artifactProcessor) {
+ if (artifactProcessor.getArtifactType() != null) {
+ processorsByArtifactType.remove((Object)artifactProcessor.getArtifactType());
+ }
+ if (artifactProcessor.getModelType() != null) {
+ processorsByModelType.remove(artifactProcessor.getModelType());
+ }
+ }
+
+ @Override
+ public URLArtifactProcessor getProcessor(Class<?> modelType) {
+ loadProcessors();
+ return super.getProcessor(modelType);
+ }
+
+ @Override
+ public URLArtifactProcessor getProcessor(Object artifactType) {
+ loadProcessors();
+ return super.getProcessor(artifactType);
+ }
+
+ /**
+ * Lazily load artifact processors registered in the extension point.
+ */
+ private void loadProcessors() {
+ if (loaded)
+ return;
+
+ // Get the processor service declarations
+ Set<ServiceDeclaration> processorDeclarations;
+ try {
+ processorDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(URLArtifactProcessor.class.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 URLArtifactProcessor {
+
+ 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 (Exception e) {
+ IllegalStateException ie = new IllegalStateException(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);
+ }
+
+ }
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java
new file mode 100644
index 0000000000..9258a837d8
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java
@@ -0,0 +1,325 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.List;
+
+import javax.xml.XMLConstants;
+import javax.xml.stream.EventFilter;
+import javax.xml.stream.StreamFilter;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLReporter;
+import javax.xml.stream.XMLResolver;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.util.XMLEventAllocator;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+
+import org.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.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * Default implementation of an XMLInputFactory that creates validating
+ * XMLStreamReaders.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultValidatingXMLInputFactory extends ValidatingXMLInputFactory {
+
+ private XMLInputFactory inputFactory;
+ 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);
+ XMLInputFactory factory = factoryExtensionPoint.getFactory(XMLInputFactory.class);
+ this.inputFactory = factory;
+ 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, Exception ex) {
+ if (monitor != null) {
+ Problem problem = monitor.createProblem(this.getClass().getName(), "contribution-validation-messages", Severity.ERROR, 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);
+ // 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) {
+ error("PrivilegedActionException", schemaFactory, (SAXException)e.getException());
+ throw (SAXException)e.getException();
+ }
+
+ } catch (Error e) {
+ // FIXME Log this, some old JDKs don't support XMLSchema validation
+ //e.printStackTrace();
+ } catch (SAXParseException e) {
+ IllegalStateException ie = new IllegalStateException(e);
+ error("IllegalStateException", schemas, ie);
+ throw ie;
+ } catch (Exception e) {
+ //FIXME Log this, some old JDKs don't support XMLSchema validation
+ e.printStackTrace();
+ }
+ }
+
+ @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);
+ }
+
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidationSchemaExtensionPoint.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidationSchemaExtensionPoint.java
new file mode 100644
index 0000000000..a6631f498e
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidationSchemaExtensionPoint.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;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.tuscany.sca.extensibility.ServiceDeclaration;
+import org.apache.tuscany.sca.extensibility.ServiceDiscovery;
+
+/**
+ * Default implementation of an extension point for XML schemas.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultValidationSchemaExtensionPoint implements ValidationSchemaExtensionPoint {
+
+ private List<String> schemas = new ArrayList<String>();
+ private boolean loaded;
+
+ public void addSchema(String uri) {
+ schemas.add(uri);
+ }
+
+ public void removeSchema(String uri) {
+ schemas.remove(uri);
+ }
+
+ /**
+ * Load schema declarations from META-INF/services/
+ * org.apache.tuscany.sca.contribution.processor.ValidationSchema files
+ */
+ private void loadSchemas() {
+ if (loaded)
+ return;
+
+ // Get the schema declarations
+ Set<ServiceDeclaration> schemaDeclarations;
+ try {
+ schemaDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations("org.apache.tuscany.sca.contribution.processor.ValidationSchema");
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+
+ // 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.xsd")){
+ tuscanyScaXsd = url.toString();
+ } else {
+ schemas.add(url.toString());
+ }
+ }
+
+ if (tuscanyScaXsd != null){
+ schemas.add(0, tuscanyScaXsd);
+ }
+
+ loaded = true;
+ }
+
+ public List<String> getSchemas() {
+ loadSchemas();
+ return schemas;
+ }
+
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java
new file mode 100644
index 0000000000..947fdb330d
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java
@@ -0,0 +1,266 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.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.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("http://www.w3.org/2001/XMLSchema", "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);
+
+ return null;
+
+ //FIXME Re-enable feature after complete merge is done
+ /*
+ 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());
+ }
+ warning("NoStaxProcessor", processors, model.getClass());
+
+ //FIXME Re-enable feature after complete merge is done
+ /*
+ 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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXAttributeProcessor.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXAttributeProcessor.java
new file mode 100644
index 0000000000..48e80a073a
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXAttributeProcessor.java
@@ -0,0 +1,243 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.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 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 UNKNOWN_ATTRIBUTE = new QName(Constants.SCA10_TUSCANY_NS, "unknown");
+
+ 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();
+ 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(UNKNOWN_ATTRIBUTE);
+ if (processor == null) {
+ Location location = source.getLocation();
+ if (logger.isLoggable(Level.WARNING)) {
+ logger.warning("Could not find Default Attribute processor !");
+ }
+ warning("DefaultAttributeProcessorNotAvailable", processors, UNKNOWN_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 (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(UNKNOWN_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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java
new file mode 100644
index 0000000000..cc31d2e073
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.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;
+
+ // Delegate to the processor associated with file extension
+ String fileName = getFileName(sourceURL);
+
+ //try to retrieve a processor for the specific filename
+ processor = (URLArtifactProcessor<Object>)processors.getProcessor(fileName);
+
+ if (processor == null) {
+ //try to find my file type (extension)
+ String extension = sourceURL.getPath();
+
+ int extensionStart = extension.lastIndexOf('.');
+ //handle files without extension (e.g NOTICE)
+ if (extensionStart > 0) {
+ extension = extension.substring(extensionStart);
+ processor = (URLArtifactProcessor<Object>)processors.getProcessor(extension);
+ }
+ }
+
+ if (processor == null) {
+ return null;
+ }
+ return processor.read(contributionURL, sourceURI, sourceURL);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void resolve(Object model, ModelResolver resolver) throws ContributionResolveException {
+
+ // Delegate to the processor associated with the model type
+ if (model != null) {
+ URLArtifactProcessor processor = processors.getProcessor(model.getClass());
+ if (processor != null) {
+ processor.resolve(model, resolver);
+ }
+ }
+ }
+
+ public <M> M read(URL contributionURL, URI artifactURI, URL artifactUrl, Class<M> type)
+ throws ContributionReadException {
+ Object mo = read(contributionURL, artifactURI, artifactUrl);
+ if (type.isInstance(mo)) {
+ return type.cast(mo);
+ } else {
+ UnrecognizedElementException e = new UnrecognizedElementException(null);
+ e.setResourceURI(artifactURI.toString());
+ 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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java
new file mode 100644
index 0000000000..1bf9b4d494
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..9700e2bc60
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+/**
+ * An extension point for StAX artifact processors.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface StAXArtifactProcessorExtensionPoint extends
+ ArtifactProcessorExtensionPoint<StAXArtifactProcessor> {
+
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessor.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessor.java
new file mode 100644
index 0000000000..b25bf0d669
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessorExtensionPoint.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessorExtensionPoint.java
new file mode 100644
index 0000000000..ebad243c1c
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXAttributeProcessorExtensionPoint.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+/**
+ * An extension point for StAX artifact processors.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface StAXAttributeProcessorExtensionPoint extends
+ ArtifactProcessorExtensionPoint<StAXAttributeProcessor> {
+
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java
new file mode 100644
index 0000000000..c44ca0c66a
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..7714586951
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+/**
+ * An extension point for URL artifact processors.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface URLArtifactProcessorExtensionPoint extends
+ ArtifactProcessorExtensionPoint<URLArtifactProcessor> {
+
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnrecognizedElementException.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnrecognizedElementException.java
new file mode 100644
index 0000000000..4c6f0b7282
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedContentTypeException.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedContentTypeException.java
new file mode 100644
index 0000000000..8a166e42f0
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedPackageTypeException.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/UnsupportedPackageTypeException.java
new file mode 100644
index 0000000000..ce94cef6a0
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLInputFactory.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLInputFactory.java
new file mode 100644
index 0000000000..c0eef5a7a8
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java
new file mode 100644
index 0000000000..ee8fbba5a5
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java
@@ -0,0 +1,387 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.util.logging.Logger;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.util.StreamReaderDelegate;
+import javax.xml.validation.Schema;
+import javax.xml.validation.ValidatorHandler;
+
+import org.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 StreamReaderDelegate 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: " + 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(), 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(), 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(), exception.getSystemId(),
+ exception.getLineNumber(), exception.getColumnNumber(), exception.getMessage());
+ }
+ });
+ }
+
+ /**
+ * 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();
+ return event;
+ case XMLStreamConstants.PROCESSING_INSTRUCTION:
+ handler.processingInstruction(super.getPITarget(), super.getPIData());
+ break;
+ case XMLStreamConstants.CHARACTERS:
+ case XMLStreamConstants.CDATA:
+ case XMLStreamConstants.SPACE:
+ case XMLStreamConstants.ENTITY_REFERENCE:
+ handler.characters(super.getTextCharacters(), super.getTextStart(), super.getTextLength());
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ handleEndElement();
+ level--;
+ return event;
+ case XMLStreamConstants.END_DOCUMENT:
+ handler.endDocument();
+ return event;
+ }
+ } catch (SAXException e) {
+ 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;
+ }
+ }
+ }
+
+ /**
+ * 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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidationSchemaExtensionPoint.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidationSchemaExtensionPoint.java
new file mode 100644
index 0000000000..cc3bb59a5b
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidationSchemaExtensionPoint.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.util.List;
+
+
+/**
+ * An extension point for XML schemas used for validation.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ValidationSchemaExtensionPoint {
+
+ /**
+ * Add a schema.
+ *
+ * @param uri the URI of the schema
+ */
+ void addSchema(String uri);
+
+ /**
+ * Remove a schema.
+ *
+ * @param uri the URI of the schema
+ */
+ void removeSchema(String uri);
+
+ /**
+ * Returns the list of schemas registered in the extension point.
+ * @return the list of schemas
+ */
+ List<String> getSchemas();
+
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java
new file mode 100644
index 0000000000..f3555ee71e
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultDelegatingModelResolver.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultDelegatingModelResolver.java
new file mode 100644
index 0000000000..13c622adf0
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java
new file mode 100644
index 0000000000..c6facd2b02
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportModelResolver.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportModelResolver.java
new file mode 100644
index 0000000000..9ae57c41d0
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolver.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolver.java
new file mode 100644
index 0000000000..bf175813f3
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolver.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.resolver;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * A default implementation of a model resolver based on a map.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultModelResolver implements ModelResolver {
+
+ private Map<Object, Object> map = new HashMap<Object, Object>();
+
+ public DefaultModelResolver() {
+ }
+
+ public <T> T resolveModel(Class<T> modelClass, T unresolved) {
+ Object resolved = map.get(unresolved);
+ if (resolved != null) {
+
+ // Return the resolved object
+ return modelClass.cast(resolved);
+
+ } else {
+
+ // Return the unresolved object
+ return unresolved;
+ }
+ }
+
+ public void addModel(Object resolved) {
+ map.put(resolved, resolved);
+ }
+
+ public Object removeModel(Object resolved) {
+ return map.remove(resolved);
+ }
+
+ // 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 getModels() {
+ return map;
+ }
+
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.java
new file mode 100644
index 0000000000..878a2efdab
--- /dev/null
+++ b/java/sca/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.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tuscany.sca.extensibility.ServiceDeclaration;
+import org.apache.tuscany.sca.extensibility.ServiceDiscovery;
+
+
+/**
+ * The default implementation of a model resolver extension point.
+ *
+ * @version $Rev$ $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 void loadModelResolvers() {
+ if (loadedResolvers != null)
+ return;
+ loadedResolvers = new HashMap<String, ServiceDeclaration>();
+
+ // Get the model resolver service declarations
+ Set<ServiceDeclaration> modelResolverDeclarations;
+ try {
+ modelResolverDeclarations = ServiceDiscovery.getInstance().getServiceDeclarations(ModelResolver.class.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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java
new file mode 100644
index 0000000000..b48742bcae
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.java
new file mode 100644
index 0000000000..2831bebbc4
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java
new file mode 100644
index 0000000000..4a25059792
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResolverExtension.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResolverExtension.java
new file mode 100644
index 0000000000..74f0f2d71d
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResourceReference.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ResourceReference.java
new file mode 100644
index 0000000000..2394f4510b
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java
new file mode 100644
index 0000000000..4e71e1ac30
--- /dev/null
+++ b/java/sca/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.processor.ContributionException;
+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 contributionURL Contribution URL
+ * @return List of artifact URIs
+ * @throws ContributionException
+ * @throws IOException
+ */
+ List<String> getArtifacts(URL contributionURL) throws ContributionReadException;
+
+ /**
+ * Return the URL for an artifact in the contribution.
+ *
+ * This is needed for archives such as jar files that have specific URL schemes
+ * for the artifacts they contain.
+ *
+ * @param contributionURL Contribution URL
+ * @param artifact The relative URI for the artifact
+ * @return The artifact URL
+ */
+ URL getArtifactURL(URL contributionURL, String artifact) throws ContributionReadException;
+
+}
diff --git a/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java
new file mode 100644
index 0000000000..1ca9def4ea
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java
new file mode 100644
index 0000000000..cf3c77d5eb
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.scanner;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.tuscany.sca.contribution.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 void loadScanners() {
+ if (loaded)
+ return;
+
+ // Get the scanner service declarations
+ Set<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(URL contributionSourceURL, String artifact) throws ContributionReadException {
+ return getScanner().getArtifactURL(contributionSourceURL, artifact);
+ }
+
+ public List<String> getArtifacts(URL contributionSourceURL) throws ContributionReadException {
+ return getScanner().getArtifacts(contributionSourceURL);
+ }
+
+ public String getContributionType() {
+ return contributionType;
+ }
+
+ private ContributionScanner getScanner() {
+ if (scanner == null) {
+ try {
+ Class<ContributionScanner> scannerClass = (Class<ContributionScanner>)scannerDeclaration.loadClass();
+ Constructor<ContributionScanner> constructor = scannerClass.getConstructor();
+ scanner = constructor.newInstance();
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ return scanner;
+ }
+ }
+}
diff --git a/java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ContributionFactory b/java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.ContributionFactory
new file mode 100644
index 0000000000..bcc346d9f8
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ContributionPostProcessorExtensionPoint b/java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ContributionPostProcessorExtensionPoint
new file mode 100644
index 0000000000..9e6433ba6c
--- /dev/null
+++ b/java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ContributionPostProcessorExtensionPoint
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+org.apache.tuscany.sca.contribution.processor.DefaultContributionPostProcessorExtensionPoint
diff --git a/java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint b/java/sca/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/java/sca/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/java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.StAXAttributeProcessorExtensionPoint b/java/sca/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/java/sca/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/java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.URLArtifactProcessorExtensionPoint b/java/sca/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/java/sca/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/java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidatingXMLInputFactory b/java/sca/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/java/sca/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/java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchemaExtensionPoint b/java/sca/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/java/sca/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/java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.resolver.ModelResolverExtensionPoint b/java/sca/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/java/sca/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/java/sca/modules/contribution/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.scanner.ContributionScannerExtensionPoint b/java/sca/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/java/sca/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/java/sca/modules/contribution/src/main/resources/contribution-validation-messages.properties b/java/sca/modules/contribution/src/main/resources/contribution-validation-messages.properties
new file mode 100644
index 0000000000..4f9f85048e
--- /dev/null
+++ b/java/sca/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 :
+AttributeCannotBeProcessed = Attribute {0} cannot be processed. ({1})
+
diff --git a/java/sca/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/processor/URLartifactProcessorExtensionPointTestCase.java b/java/sca/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/processor/URLartifactProcessorExtensionPointTestCase.java
new file mode 100644
index 0000000000..14b6b956da
--- /dev/null
+++ b/java/sca/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/processor/URLartifactProcessorExtensionPointTestCase.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import static junit.framework.Assert.assertNotNull;
+
+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(".m1"));
+ }
+
+ @Test
+ public final void testFileNameProcessor() {
+ assertNotNull(artifactProcessors.getProcessor("file.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/java/sca/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverTestCase.java b/java/sca/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverTestCase.java
new file mode 100644
index 0000000000..f5b04f503c
--- /dev/null
+++ b/java/sca/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 junit.framework.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/java/sca/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolverTestCase.java b/java/sca/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolverTestCase.java
new file mode 100644
index 0000000000..e4082b3b85
--- /dev/null
+++ b/java/sca/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 junit.framework.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/java/sca/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/TestModelResolver.java b/java/sca/modules/contribution/src/test/java/org/apache/tuscany/sca/contribution/resolver/TestModelResolver.java
new file mode 100644
index 0000000000..cd586d3b2c
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/test/resources/deployables/sample-calculator.jar b/java/sca/modules/contribution/src/test/resources/deployables/sample-calculator.jar
new file mode 100644
index 0000000000..0ca3a1b781
--- /dev/null
+++ b/java/sca/modules/contribution/src/test/resources/deployables/sample-calculator.jar
Binary files differ
diff --git a/java/sca/modules/contribution/src/test/resources/repository/sample-calculator.jar b/java/sca/modules/contribution/src/test/resources/repository/sample-calculator.jar
new file mode 100644
index 0000000000..9c46c679d2
--- /dev/null
+++ b/java/sca/modules/contribution/src/test/resources/repository/sample-calculator.jar
Binary files differ
diff --git a/java/sca/modules/contribution/src/test/resources/test.composite b/java/sca/modules/contribution/src/test/resources/test.composite
new file mode 100644
index 0000000000..1e09549194
--- /dev/null
+++ b/java/sca/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/java/sca/modules/contribution/src/test/resources/test.ext b/java/sca/modules/contribution/src/test/resources/test.ext
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/java/sca/modules/contribution/src/test/resources/test.ext