summaryrefslogtreecommitdiffstats
path: root/branches/sca-java-1.0/modules/contribution/src/main/java
diff options
context:
space:
mode:
authordims <dims@13f79535-47bb-0310-9956-ffa450edef68>2008-06-17 00:23:01 +0000
committerdims <dims@13f79535-47bb-0310-9956-ffa450edef68>2008-06-17 00:23:01 +0000
commitbdd0a41aed7edf21ec2a65cfa17a86af2ef8c48a (patch)
tree38a92061c0793434c4be189f1d70c3458b6bc41d /branches/sca-java-1.0/modules/contribution/src/main/java
Move Tuscany from Incubator to top level.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@668359 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'branches/sca-java-1.0/modules/contribution/src/main/java')
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java57
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.java56
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java91
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java42
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultModelFactoryExtensionPoint.java134
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DeployedArtifact.java43
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java47
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java54
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ModelFactoryExtensionPoint.java54
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java48
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessorExtensionPoint.java58
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java486
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.java66
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultPackageProcessorExtensionPoint.java130
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java215
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java165
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensiblePackageProcessor.java79
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java173
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java121
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessor.java67
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessorExtensionPoint.java50
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java61
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java29
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java51
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java29
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java319
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java103
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java84
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.java113
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java152
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.java66
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java52
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/AbstractContributionException.java124
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionException.java53
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListener.java58
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListenerExtensionPoint.java44
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionReadException.java94
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRepository.java128
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionResolveException.java41
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRuntimeException.java44
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionService.java142
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionWireException.java42
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionWriteException.java61
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/DefaultContributionListenerExtensionPoint.java86
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ExtensibleContributionListener.java77
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/TypeDescriber.java38
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnrecognizedElementException.java48
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedContentTypeException.java49
-rw-r--r--branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/util/ServiceConfigurationUtil.java98
49 files changed, 4522 insertions, 0 deletions
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java
new file mode 100644
index 0000000000..1b4a61234b
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Artifact.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+
+/**
+ * Base Artifact interface to accomodate common properties between Contribution and Deployed Artifact
+ *
+ * @version $Rev$ $Date$
+ */
+public interface Artifact {
+ /**
+ * Get the URI that unique identifies the artifact
+ *
+ * @return The artifact uri
+ */
+ String getURI();
+
+ /**
+ * Set the URI that unique identifies the artifact
+ *
+ * @param uri The artifact uri
+ */
+ void setURI(String uri);
+
+ /**
+ * Get the URL location for the artifact
+ *
+ * @return The artifact location
+ */
+ String getLocation();
+
+ /**
+ * Set the URL location for the artifact
+ *
+ * @param location The artifact location
+ */
+ void setLocation(String location);
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.java
new file mode 100644
index 0000000000..51e5b586be
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContentType.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;
+
+/**
+ * Identifies internal content types for contribution package and artifacts
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ContentType {
+ /**
+ * Java compressed contribution package
+ */
+ String JAR = "application/x-compressed";
+ /**
+ * Filesystem folder contribution package
+ */
+ String FOLDER = "application/vnd.tuscany.folder";
+ /**
+ * Contribution metadata file
+ */
+ String CONTRIBUTION_METADATA = "application/vnd.tuscany.contribution.metadata";
+ /**
+ * SCA Composite description file
+ */
+ String COMPOSITE = "application/vnd.tuscany.composite";
+ /**
+ * WSDL file
+ */
+ String WSDL = "application/vnd.tuscany.wsdl";
+ /**
+ * Java source/binary file
+ */
+ String JAVA = "application/java-vm";
+ /**
+ * Unkown contentType
+ */
+ String UNKNOWN = "content/unknown";
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.java
new file mode 100644
index 0000000000..e31805bf9a
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Contribution.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;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * The representation of a deployed contribution
+ *
+ * @version $Rev$ $Date$
+ */
+public interface Contribution extends Artifact {
+ /**
+ * Default location of contribution metadata in a contribution package
+ */
+ String SCA_CONTRIBUTION_META = "META-INF/sca-contribution.xml";
+ /**
+ * default location of a generated contribution metadata in a contribution package
+ */
+ String SCA_CONTRIBUTION_GENERATED_META = "META-INF/sca-contribution-generated.xml";
+ /**
+ * Default location of deployables in a contribution
+ */
+ String SCA_CONTRIBUTION_DEPLOYABLES = "META-INF/sca-deployables/";
+
+
+ /**
+ * Get a list of exports based on the Contribution metadata sidefile
+ *
+ * @return The list of exported artifacts from this contribution
+ */
+ List<Export> getExports();
+
+ /**
+ * Get a list of imports based on the Contribution metadata sidefile
+ *
+ * @return The list of imported artifacts on this contribution
+ */
+ List<Import> getImports();
+
+ /**
+ * Get a list of deployables for the contribution based on the contribution metadata sidefile
+ *
+ * @return The list of deployable composites
+ */
+ List<Composite> getDeployables();
+
+ /**
+ * Get a list of artifacts from the contribution
+ *
+ * @return The list of deployed artifacts for the contribution
+ */
+ List<DeployedArtifact> 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);
+
+} \ No newline at end of file
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.java
new file mode 100644
index 0000000000..e21ae3999b
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ContributionFactory.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;
+
+
+/**
+ * Contribution model object factory
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ContributionFactory {
+ /**
+ * Create a contribution model object
+ *
+ * @return The new contribution model object
+ */
+ Contribution createContribution();
+
+ /**
+ * Create a deployedArtifact model object
+ *
+ * @return The new deployedArtifact model object
+ */
+ DeployedArtifact createDeployedArtifact();
+} \ No newline at end of file
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultModelFactoryExtensionPoint.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultModelFactoryExtensionPoint.java
new file mode 100644
index 0000000000..ac3cd010d1
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DefaultModelFactoryExtensionPoint.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;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.tuscany.sca.contribution.util.ServiceConfigurationUtil;
+
+
+/**
+ * Default implementation of a model factory extension point.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultModelFactoryExtensionPoint implements ModelFactoryExtensionPoint {
+
+ private HashMap<Class<?>, Object> factories = new HashMap<Class<?>, Object>();
+
+ public DefaultModelFactoryExtensionPoint() {
+ }
+
+ /**
+ * Add a model factory extension.
+ *
+ * @param factory The factory to add
+ */
+ public void addFactory(Object factory) {
+ Class[] interfaces = factory.getClass().getInterfaces();
+ if (interfaces.length == 0) {
+ Class<?> sc = factory.getClass().getSuperclass();
+ if (sc != Object.class) {
+ factories.put(sc, factory);
+ }
+ } else {
+ for (int i = 0; i<interfaces.length; i++) {
+ factories.put(interfaces[i], factory);
+ }
+ }
+ }
+
+ /**
+ * Remove a model factory extension.
+ *
+ * @param factory The factory to remove
+ */
+ public void removeFactory(Object factory) {
+ Class[] interfaces = factory.getClass().getInterfaces();
+ if (interfaces.length == 0) {
+ Class<?> sc = factory.getClass().getSuperclass();
+ if (sc != Object.class) {
+ factories.remove(sc);
+ }
+ } else {
+ for (int i = 0; i<interfaces.length; i++) {
+ factories.remove(interfaces[i]);
+ }
+ }
+ }
+
+ /**
+ * Get a factory implementing the given interface.
+ * @param factoryInterface The lookup key (factory interface)
+ * @return The factory
+ */
+ public <T> T getFactory(Class<T> factoryInterface) {
+ Object factory = factories.get(factoryInterface);
+ if (factory == null) {
+
+ if (factoryInterface.isInterface()) {
+
+ // Dynamically load a factory class declared under META-INF/services
+ ClassLoader classLoader = factoryInterface.getClassLoader();
+ if (classLoader == null)
+ classLoader = ClassLoader.getSystemClassLoader();
+ try {
+ List<String> classNames = ServiceConfigurationUtil.getServiceClassNames(classLoader, factoryInterface.getName());
+ if (!classNames.isEmpty()) {
+ Class<?> factoryClass = Class.forName(classNames.iterator().next(), true, classLoader);
+
+ try {
+ // Default empty constructor
+ Constructor<?> constructor = factoryClass.getConstructor();
+ factory = constructor.newInstance();
+ } catch (NoSuchMethodException e) {
+
+ // Constructor taking the model factory extension point
+ Constructor<?> constructor = factoryClass.getConstructor(ModelFactoryExtensionPoint.class);
+ factory = constructor.newInstance(this);
+ }
+
+ // Cache the loaded factory
+ addFactory(factory);
+ }
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e);
+ }
+ } else {
+
+ // Call the newInstance static method on the factory abstract class
+ try {
+ Method newInstanceMethod = factoryInterface.getMethod("newInstance");
+ factory = newInstanceMethod.invoke(null);
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e);
+ }
+
+ // Cache the factory
+ addFactory(factory);
+ }
+ }
+ return factoryInterface.cast(factory);
+ }
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DeployedArtifact.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DeployedArtifact.java
new file mode 100644
index 0000000000..4b0fb1cc08
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/DeployedArtifact.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;
+
+/**
+ * Representation of a deployed artifact
+ *
+ * @version $Rev$ $Date$
+ */
+public interface DeployedArtifact extends Artifact {
+
+ /**
+ * Get the assembly model associated with this artifact
+ *
+ * @return The assembly model
+ */
+ Object getModel();
+
+ /**
+ * Set the assembly model associated with this artifact
+ *
+ * @param modelObject The assembly model
+ */
+ void setModel(Object modelObject);
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Export.java
new file mode 100644
index 0000000000..bfa16b1ce3
--- /dev/null
+++ b/branches/sca-java-1.0/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/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.java
new file mode 100644
index 0000000000..4a4b63805b
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/Import.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;
+
+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 is a specific export is provider of what is being imported
+ * @param export The Exported being verified
+ * @return true/false
+ */
+ boolean match(Export export);
+} \ No newline at end of file
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ModelFactoryExtensionPoint.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ModelFactoryExtensionPoint.java
new file mode 100644
index 0000000000..0ada4ebec3
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/ModelFactoryExtensionPoint.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution;
+
+/**
+ * An extension point for model factories. Model factories are provided to
+ * abstract the classes that represent artifacts in the assembly model away
+ * from their creation mechanism. When the runtime needs to extend the model
+ * as it reads in contributed artifacts it looks up the factory for the
+ * artifact required in this registry
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ModelFactoryExtensionPoint {
+
+ /**
+ * Add a model factory extension.
+ *
+ * @param factory The factory to add
+ */
+ void addFactory(Object factory);
+
+ /**
+ * Remove a model factory extension.
+ *
+ * @param factory The factory to remove
+ */
+ void removeFactory(Object factory);
+
+ /**
+ * Get a factory implementing the given interface.
+ * @param factoryInterface the lookup key (factory interface)
+ * @return The factory
+ */
+ <T> T getFactory(Class<T> factoryInterface);
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java
new file mode 100644
index 0000000000..014c187733
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessor.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.service.ContributionResolveException;
+
+/**
+ * Interface for extensions that can process contributions.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ArtifactProcessor<M> {
+
+ /**
+ * Resolve references from this model to other models. For example references
+ * from a composite to another one, or references from a composite to a WSDL
+ * model.
+ *
+ * @param model The model to resolve
+ * @param resolver The resolver to use to resolve referenced models
+ */
+ void resolve(M model, ModelResolver resolver) throws ContributionResolveException;
+
+ /**
+ * Returns the type of model handled by this artifact processor.
+ *
+ * @return The type of model handled by this artifact processor
+ */
+ Class<M> getModelType();
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessorExtensionPoint.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..029df61f0f
--- /dev/null
+++ b/branches/sca-java-1.0/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/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java
new file mode 100644
index 0000000000..ed41b9ae6e
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/BaseStAXArtifactProcessor.java
@@ -0,0 +1,486 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, 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 void writeElementPrefix(XMLStreamWriter writer, String uri) throws XMLStreamException {
+ if (uri == null) {
+ return;
+ }
+ String 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);
+ }
+
+ }
+
+ /**
+ * Start an element.
+ * @param uri
+ * @param name
+ * @param attrs
+ * @throws XMLStreamException
+ */
+ protected void writeStart(XMLStreamWriter writer, String uri, String name, XAttr... attrs) throws XMLStreamException {
+ writeElementPrefix(writer, uri);
+ writeAttributePrefixes(writer, attrs);
+ writer.writeStartElement(uri, name);
+ writeAttributes(writer, 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);
+ }
+
+ /**
+ * End a document.
+ * @param writer
+ * @throws XMLStreamException
+ */
+ protected void writeEndDocument(XMLStreamWriter writer) throws XMLStreamException {
+ writer.writeEndDocument();
+ }
+
+ /**
+ * Write attributes to the current element.
+ * @param writer
+ * @param attrs
+ * @throws XMLStreamException
+ */
+ protected void writeAttributes(XMLStreamWriter writer, XAttr... attrs) throws XMLStreamException {
+ for (XAttr attr : attrs) {
+ if (attr != null)
+ attr.write(writer);
+ }
+ }
+
+ /**
+ * Write attribute prefixes to the current element.
+ * @param writer
+ * @param attrs
+ * @throws XMLStreamException
+ */
+ protected void writeAttributePrefixes(XMLStreamWriter writer, XAttr... attrs) throws XMLStreamException {
+ for (XAttr attr : attrs) {
+ if (attr != null)
+ attr.writePrefix(writer);
+ }
+ }
+
+ /**
+ * Represents an XML attribute that needs to be written to a document.
+ */
+ public static class XAttr {
+
+ private static final String SCA10_NS = "http://www.osoa.org/xmlns/sca/1.0";
+
+ private String uri = SCA10_NS;
+ private String name;
+ private Object value;
+
+ public XAttr(String uri, String name, String value) {
+ this.uri = uri;
+ this.name = name;
+ this.value = value;
+ }
+
+ public XAttr(String name, String value) {
+ this(null, name, value);
+ }
+
+ public XAttr(String uri, String name, List values) {
+ this.uri = uri;
+ this.name = name;
+ this.value = values;
+ }
+
+ public XAttr(String name, List values) {
+ this(null, name, values);
+ }
+
+ public XAttr(String uri, String name, Boolean value) {
+ this.uri = uri;
+ this.name = name;
+ this.value = value;
+ }
+
+ public XAttr(String name, Boolean value) {
+ this(null, name, value);
+ }
+
+ public XAttr(String uri, String name, QName value) {
+ this.uri = uri;
+ this.name = name;
+ this.value = value;
+ }
+
+ public XAttr(String name, QName value) {
+ this(null, name, value);
+ }
+
+ /**
+ * Writes a string from a qname and registers a prefix for its namespace.
+ * @param reader
+ * @param value
+ * @return
+ */
+ private String writeQNameValue(XMLStreamWriter writer, QName qname) throws XMLStreamException {
+ if (qname != null) {
+ String prefix = qname.getPrefix();
+ String uri = qname.getNamespaceURI();
+ prefix = writer.getPrefix(uri);
+ if (prefix != null && prefix.length() > 0) {
+
+ // Use the prefix already bound to the given uri
+ return prefix + ":" + qname.getLocalPart();
+ } else {
+
+ // Find an available prefix and bind it to the given uri
+ NamespaceContext nsc = writer.getNamespaceContext();
+ for (int i=1; ; i++) {
+ prefix = "ns" + i;
+ if (nsc.getNamespaceURI(prefix) == null) {
+ break;
+ }
+ }
+ writer.setPrefix(prefix, uri);
+ writer.writeNamespace(prefix, uri);
+ return prefix + ":" + qname.getLocalPart();
+ }
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Registers a prefix for the namespace of a QName.
+ * @param reader
+ * @param value
+ * @return
+ */
+ private void writeQNamePrefix(XMLStreamWriter writer, QName qname) throws XMLStreamException {
+ if (qname != null) {
+ String prefix = qname.getPrefix();
+ String uri = qname.getNamespaceURI();
+ prefix = writer.getPrefix(uri);
+ if (prefix != null) {
+ return;
+ } else {
+
+ // Find an available prefix and bind it to the given uri
+ NamespaceContext nsc = writer.getNamespaceContext();
+ for (int i=1; ; i++) {
+ prefix = "ns" + i;
+ if (nsc.getNamespaceURI(prefix) == null) {
+ break;
+ }
+ }
+ writer.setPrefix(prefix, uri);
+ }
+ }
+ }
+
+ /**
+ * Write to document
+ * @param writer
+ * @throws XMLStreamException
+ */
+ public void write(XMLStreamWriter writer) throws XMLStreamException {
+ String str;
+ if (value instanceof QName) {
+
+ // Write a QName
+ str = writeQNameValue(writer, (QName)value);
+
+ } else if (value instanceof List) {
+
+ // Write a list of values
+ List values = (List)value;
+ if (values.isEmpty()) {
+ return;
+ }
+ StringBuffer buffer = new StringBuffer();
+ for (Object v: values) {
+ if (v == null) {
+ // Skip null values
+ continue;
+ }
+
+ if (v instanceof XAttr) {
+ // Write an XAttr value
+ ((XAttr)v).write(writer);
+ continue;
+ }
+
+ if (buffer.length() != 0) {
+ buffer.append(' ');
+ }
+ if (v instanceof QName) {
+ // Write a qname value
+ buffer.append(writeQNameValue(writer, (QName)v));
+ } else {
+ // Write value as a string
+ buffer.append(String.valueOf(v));
+ }
+ }
+ str = buffer.toString();
+
+ } else {
+
+ // Write a string
+ if (value == null) {
+ return;
+ }
+ str = String.valueOf(value);
+ }
+ if (str.length() == 0) {
+ return;
+ }
+
+ // Write the attribute
+ if (uri != null && !uri.equals(SCA10_NS)) {
+ writer.writeAttribute(uri, name, str);
+ } else {
+ writer.writeAttribute(name,str);
+ }
+ }
+
+ /**
+ * Registers a prefix for the namespace of a QName or list of QNames
+ * @param writer
+ * @throws XMLStreamException
+ */
+ public void writePrefix(XMLStreamWriter writer) throws XMLStreamException {
+ if (value instanceof QName) {
+
+ // Write prefix for a single QName value
+ writeQNamePrefix(writer, (QName)value);
+
+ } else if (value instanceof List) {
+
+ // Write prefixes for a list of values
+ for (Object v: (List)value) {
+ if (v instanceof QName) {
+ // Write prefix for a QName value
+ writeQNamePrefix(writer, (QName)v);
+
+ } else if (v instanceof XAttr) {
+ // Write prefix for an XAttr value
+ ((XAttr)v).writePrefix(writer);
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..1c2faf9503
--- /dev/null
+++ b/branches/sca-java-1.0/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 registry.
+ *
+ * @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.
+ */
+ public 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/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultPackageProcessorExtensionPoint.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultPackageProcessorExtensionPoint.java
new file mode 100644
index 0000000000..5a794498d9
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultPackageProcessorExtensionPoint.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.processor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tuscany.sca.contribution.service.ContributionException;
+import org.apache.tuscany.sca.contribution.util.ServiceConfigurationUtil;
+
+/**
+ * Default implementation of ContributionProcessorRegistry
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultPackageProcessorExtensionPoint implements PackageProcessorExtensionPoint {
+
+ private Map<String, PackageProcessor> processors = new HashMap<String, PackageProcessor>();
+ private boolean loaded;
+
+ public DefaultPackageProcessorExtensionPoint() {
+ }
+
+ public void addPackageProcessor(PackageProcessor processor) {
+ processors.put(processor.getPackageType(), processor);
+ }
+
+ public void removePackageProcessor(PackageProcessor processor) {
+ processors.remove(processor.getPackageType());
+ }
+
+ public PackageProcessor getPackageProcessor(String contentType) {
+ loadProcessors();
+ return processors.get(contentType);
+ }
+
+ private void loadProcessors() {
+ if (loaded)
+ return;
+
+ // Get the processor service declarations
+ ClassLoader classLoader = PackageProcessor.class.getClassLoader();
+ List<String> processorDeclarations;
+ try {
+ processorDeclarations = ServiceConfigurationUtil.getServiceClassNames(classLoader, PackageProcessor.class.getName());
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+
+ for (String processorDeclaration: processorDeclarations) {
+ Map<String, String> attributes = ServiceConfigurationUtil.parseServiceDeclaration(processorDeclaration);
+ String className = attributes.get("class");
+
+ // Load a URL artifact processor
+ String packageType = attributes.get("type");
+
+ // Create a processor wrapper and register it
+ PackageProcessor processor = new LazyPackageProcessor(packageType, className);
+ addPackageProcessor(processor);
+ }
+
+ loaded = true;
+ }
+
+ /**
+ * A facade for package processors.
+ */
+ private static class LazyPackageProcessor implements PackageProcessor {
+
+ private String className;
+ private String packageType;
+ private PackageProcessor processor;
+
+ private LazyPackageProcessor(String packageType, String className) {
+ this.className = className;
+ this.packageType = packageType;
+ }
+
+ public URL getArtifactURL(URL packageSourceURL, URI artifact) throws MalformedURLException {
+ return getProcessor().getArtifactURL(packageSourceURL, artifact);
+ }
+
+ public List<URI> getArtifacts(URL packageSourceURL, InputStream inputStream) throws ContributionException, IOException {
+ return getProcessor().getArtifacts(packageSourceURL, inputStream);
+ }
+
+ public String getPackageType() {
+ return packageType;
+ }
+
+ @SuppressWarnings("unchecked")
+ private PackageProcessor getProcessor() {
+ if (processor == null) {
+ try {
+ ClassLoader classLoader = PackageProcessor.class.getClassLoader();
+ Class<PackageProcessor> processorClass = (Class<PackageProcessor>)Class.forName(className, true, classLoader);
+ Constructor<PackageProcessor> constructor = processorClass.getConstructor();
+ processor = constructor.newInstance();
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ return processor;
+ }
+ }
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..9ebf49554c
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultStAXArtifactProcessorExtensionPoint.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.processor;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.service.ContributionReadException;
+import org.apache.tuscany.sca.contribution.service.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.service.ContributionWriteException;
+import org.apache.tuscany.sca.contribution.util.ServiceConfigurationUtil;
+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 ModelFactoryExtensionPoint modelFactories;
+ private boolean loaded;
+
+ /**
+ * Constructs a new extension point.
+ */
+ public DefaultStAXArtifactProcessorExtensionPoint(ModelFactoryExtensionPoint modelFactories) {
+ this.modelFactories = modelFactories;
+ }
+
+ public void addArtifactProcessor(StAXArtifactProcessor artifactProcessor) {
+ processorsByArtifactType.put((Object)artifactProcessor.getArtifactType(), artifactProcessor);
+ processorsByModelType.put(artifactProcessor.getModelType(), artifactProcessor);
+ }
+
+ public void removeArtifactProcessor(StAXArtifactProcessor artifactProcessor) {
+ processorsByArtifactType.remove((Object)artifactProcessor.getArtifactType());
+ processorsByModelType.remove(artifactProcessor.getModelType());
+ }
+
+ @Override
+ public StAXArtifactProcessor getProcessor(Class<?> modelType) {
+ loadArtifactProcessors();
+ return super.getProcessor(modelType);
+ }
+
+ @Override
+ public StAXArtifactProcessor getProcessor(Object artifactType) {
+ loadArtifactProcessors();
+ return super.getProcessor(artifactType);
+ }
+
+ private void loadArtifactProcessors() {
+ if (loaded)
+ return;
+
+ // Get the processor service declarations
+ ClassLoader classLoader = StAXArtifactProcessor.class.getClassLoader();
+ List<String> processorDeclarations;
+ try {
+ processorDeclarations = ServiceConfigurationUtil.getServiceClassNames(classLoader, StAXArtifactProcessor.class.getName());
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+
+ for (String processorDeclaration: processorDeclarations) {
+ Map<String, String> attributes = ServiceConfigurationUtil.parseServiceDeclaration(processorDeclaration);
+ String className = attributes.get("class");
+
+ // Load a StAX artifact processor
+
+ // Get the model qname
+ QName artifactType = null;
+ String qname = attributes.get("qname");
+ if (qname != null) {
+ int h = qname.indexOf('#');
+ artifactType = new QName(qname.substring(0, h), qname.substring(h+1));
+ }
+
+ // Get the model class name
+ String modelTypeName = attributes.get("model");
+
+ // Get the model factory class name
+ String factoryName = attributes.get("factory");
+
+ // Create a processor wrapper and register it
+ StAXArtifactProcessor processor = new LazyStAXArtifactProcessor(modelFactories, artifactType, modelTypeName, factoryName, className);
+ addArtifactProcessor(processor);
+ }
+
+ loaded = true;
+ }
+
+ /**
+ * A wrapper around an Artifact processor class allowing lazy loading and
+ * initialization of artifact processors.
+ */
+ private static class LazyStAXArtifactProcessor implements StAXArtifactProcessor {
+
+ private ModelFactoryExtensionPoint modelFactories;
+ private QName artifactType;
+ private String modelTypeName;
+ private String factoryName;
+ private String className;
+ private StAXArtifactProcessor processor;
+ private Class modelType;
+
+ LazyStAXArtifactProcessor(ModelFactoryExtensionPoint modelFactories, QName artifactType, String modelTypeName, String factoryName, String className) {
+ this.modelFactories = modelFactories;
+ this.artifactType = artifactType;
+ this.modelTypeName = modelTypeName;
+ this.factoryName = factoryName;
+ this.className = className;
+ }
+
+ public QName getArtifactType() {
+ return artifactType;
+ }
+
+ @SuppressWarnings("unchecked")
+ private StAXArtifactProcessor getProcessor() {
+ if (processor == null) {
+
+ if (className.equals("org.apache.tuscany.sca.assembly.xml.DefaultBeanModelProcessor")) {
+
+ // Specific initialization for the DefaultBeanModelProcessor
+ AssemblyFactory assemblyFactory = modelFactories.getFactory(AssemblyFactory.class);
+ PolicyFactory policyFactory = modelFactories.getFactory(PolicyFactory.class);
+ try {
+ ClassLoader classLoader = URLArtifactProcessor.class.getClassLoader();
+ Class<StAXArtifactProcessor> processorClass = (Class<StAXArtifactProcessor>)Class.forName(className, true, classLoader);
+ Object modelFactory;
+ if (factoryName != null) {
+ Class<?> factoryClass = (Class<?>)Class.forName(factoryName, true, classLoader);
+ modelFactory = modelFactories.getFactory(factoryClass);
+ } else {
+ modelFactory = null;
+ }
+ Constructor<StAXArtifactProcessor> constructor = processorClass.getConstructor(AssemblyFactory.class, PolicyFactory.class, QName.class, Class.class, Object.class);
+ processor = constructor.newInstance(assemblyFactory, policyFactory, artifactType, getModelType(), modelFactory);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ } else {
+
+ // Load and instanciate the processor class
+ try {
+ ClassLoader classLoader = URLArtifactProcessor.class.getClassLoader();
+ Class<StAXArtifactProcessor> processorClass = (Class<StAXArtifactProcessor>)Class.forName(className, true, classLoader);
+ Constructor<StAXArtifactProcessor> constructor = processorClass.getConstructor(ModelFactoryExtensionPoint.class);
+ processor = constructor.newInstance(modelFactories);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+ return processor;
+ }
+
+ public Object read(XMLStreamReader inputSource) throws ContributionReadException, XMLStreamException {
+ return getProcessor().read(inputSource);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void write(Object model, XMLStreamWriter outputSource) throws ContributionWriteException, XMLStreamException {
+ getProcessor().write(model, outputSource);
+ }
+
+ public Class getModelType() {
+ if (modelType == null) {
+ try {
+ ClassLoader classLoader = URLArtifactProcessor.class.getClassLoader();
+ modelType = Class.forName(modelTypeName, true, classLoader);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ return modelType;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void resolve(Object model, ModelResolver resolver) throws ContributionResolveException {
+ getProcessor().resolve(model, resolver);
+ }
+
+ }
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..acc611c101
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultURLArtifactProcessorExtensionPoint.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.net.URI;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.service.ContributionReadException;
+import org.apache.tuscany.sca.contribution.service.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.util.ServiceConfigurationUtil;
+
+/**
+ * The default implementation of a StAX artifact processor registry.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultURLArtifactProcessorExtensionPoint
+ extends DefaultArtifactProcessorExtensionPoint<URLArtifactProcessor>
+ implements URLArtifactProcessorExtensionPoint {
+
+ private ModelFactoryExtensionPoint modelFactories;
+ private boolean loaded;
+
+ /**
+ * Constructs a new extension point.
+ */
+ public DefaultURLArtifactProcessorExtensionPoint(ModelFactoryExtensionPoint modelFactories) {
+ this.modelFactories = modelFactories;
+ }
+
+ public void addArtifactProcessor(URLArtifactProcessor artifactProcessor) {
+ processorsByArtifactType.put((Object)artifactProcessor.getArtifactType(), artifactProcessor);
+ processorsByModelType.put(artifactProcessor.getModelType(), artifactProcessor);
+ }
+
+ public void removeArtifactProcessor(URLArtifactProcessor artifactProcessor) {
+ processorsByArtifactType.remove((Object)artifactProcessor.getArtifactType());
+ processorsByModelType.remove(artifactProcessor.getModelType());
+ }
+
+ @Override
+ public URLArtifactProcessor getProcessor(Class<?> modelType) {
+ loadProcessors();
+ return super.getProcessor(modelType);
+ }
+
+ @Override
+ public URLArtifactProcessor getProcessor(Object artifactType) {
+ loadProcessors();
+ return super.getProcessor(artifactType);
+ }
+
+ private void loadProcessors() {
+ if (loaded)
+ return;
+
+ // Get the processor service declarations
+ ClassLoader classLoader = URLArtifactProcessor.class.getClassLoader();
+ List<String> processorDeclarations;
+ try {
+ processorDeclarations = ServiceConfigurationUtil.getServiceClassNames(classLoader, URLArtifactProcessor.class.getName());
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+
+ for (String processorDeclaration: processorDeclarations) {
+ Map<String, String> attributes = ServiceConfigurationUtil.parseServiceDeclaration(processorDeclaration);
+ String className = attributes.get("class");
+
+ // Load a URL artifact processor
+ String artifactType = attributes.get("type");
+ String modelTypeName = attributes.get("model");
+
+ // Create a processor wrapper and register it
+ URLArtifactProcessor processor = new LazyURLArtifactProcessor(modelFactories, artifactType, modelTypeName, className);
+ addArtifactProcessor(processor);
+ }
+
+ loaded = true;
+ }
+
+ /**
+ * A wrapper around an Artifact processor class allowing lazy loading and
+ * initialization of artifact processors.
+ */
+ private static class LazyURLArtifactProcessor implements URLArtifactProcessor {
+
+ private ModelFactoryExtensionPoint modelFactories;
+ private String artifactType;
+ private String modelTypeName;
+ private String className;
+ private URLArtifactProcessor processor;
+ private Class modelType;
+
+ LazyURLArtifactProcessor(ModelFactoryExtensionPoint modelFactories, String artifactType, String modelTypeName, String className) {
+ this.modelFactories = modelFactories;
+ this.artifactType = artifactType;
+ this.modelTypeName = modelTypeName;
+ this.className = className;
+ }
+
+ public String getArtifactType() {
+ return artifactType;
+ }
+
+ @SuppressWarnings("unchecked")
+ private URLArtifactProcessor getProcessor() {
+ if (processor == null) {
+ try {
+ ClassLoader classLoader = URLArtifactProcessor.class.getClassLoader();
+ Class<URLArtifactProcessor> processorClass = (Class<URLArtifactProcessor>)Class.forName(className, true, classLoader);
+ Constructor<URLArtifactProcessor> constructor = processorClass.getConstructor(ModelFactoryExtensionPoint.class);
+ processor = constructor.newInstance(modelFactories);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ return processor;
+ }
+
+ public Object read(URL contributionURL, URI artifactURI, URL artifactURL) throws ContributionReadException {
+ return getProcessor().read(contributionURL, artifactURI, artifactURL);
+ }
+
+ public Class getModelType() {
+ if (modelType == null) {
+ try {
+ ClassLoader classLoader = URLArtifactProcessor.class.getClassLoader();
+ modelType = Class.forName(modelTypeName, true, classLoader);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ return modelType;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void resolve(Object model, ModelResolver resolver) throws ContributionResolveException {
+ getProcessor().resolve(model, resolver);
+ }
+
+ }
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensiblePackageProcessor.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensiblePackageProcessor.java
new file mode 100644
index 0000000000..fb6e1b29ce
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensiblePackageProcessor.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.util.List;
+
+import org.apache.tuscany.sca.contribution.service.ContributionException;
+import org.apache.tuscany.sca.contribution.service.TypeDescriber;
+import org.apache.tuscany.sca.contribution.service.UnsupportedContentTypeException;
+
+/**
+ * Default implementation of PackageProcessor.
+ *
+ * This implementation has a packageProcessorExtensionPoint
+ * and it delegates to the proper package processor based on content type
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExtensiblePackageProcessor implements PackageProcessor {
+
+ private PackageProcessorExtensionPoint processors;
+
+ /**
+ * Helper method to describe contentType for each artifact
+ */
+ private TypeDescriber packageTypeDescriber;
+
+ public ExtensiblePackageProcessor(PackageProcessorExtensionPoint processors, TypeDescriber packageTypeDescriber) {
+ this.processors = processors;
+ this.packageTypeDescriber = packageTypeDescriber;
+ }
+
+ public List<URI> getArtifacts(URL packageSourceURL, InputStream inputStream)
+ throws ContributionException, IOException {
+ String contentType = this.packageTypeDescriber.getType(packageSourceURL, null);
+ if (contentType == null) {
+ throw new UnsupportedContentTypeException("Unsupported contribution package", packageSourceURL.toString());
+ }
+
+ PackageProcessor packageProcessor = this.processors.getPackageProcessor(contentType);
+ if (packageProcessor == null) {
+ throw new UnsupportedContentTypeException(contentType, packageSourceURL.getPath());
+ }
+
+ return packageProcessor.getArtifacts(packageSourceURL, inputStream);
+ }
+
+ public URL getArtifactURL(URL packageSourceURL, URI artifact) throws MalformedURLException {
+ String contentType = this.packageTypeDescriber.getType(packageSourceURL, null);
+ PackageProcessor packageProcessor = this.processors.getPackageProcessor(contentType);
+ return packageProcessor.getArtifactURL(packageSourceURL, artifact);
+ }
+
+ public String getPackageType() {
+ return null;
+ }
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java
new file mode 100644
index 0000000000..8034a45d79
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleStAXArtifactProcessor.java
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.service.ContributionReadException;
+import org.apache.tuscany.sca.contribution.service.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.service.ContributionWriteException;
+import org.apache.tuscany.sca.contribution.service.UnrecognizedElementException;
+
+/**
+ * The default implementation of a StAX artifact processor registry.
+ *
+ * This implementation has a StAXArtifactProcessorExtensionPoint and
+ * it delegates to the proper StAXArtifactProcessor by element QName
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExtensibleStAXArtifactProcessor
+ implements StAXArtifactProcessor<Object> {
+
+ private XMLInputFactory inputFactory;
+ private XMLOutputFactory outputFactory;
+ private StAXArtifactProcessorExtensionPoint processors;
+
+ /**
+ * Constructs a new loader registry.
+ * @param inputFactory
+ * @param outputFactory
+ */
+ public ExtensibleStAXArtifactProcessor(StAXArtifactProcessorExtensionPoint processors, XMLInputFactory inputFactory, XMLOutputFactory outputFactory) {
+ super();
+ this.processors = processors;
+ this.inputFactory = inputFactory;
+ this.outputFactory = outputFactory;
+ this.outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", Boolean.TRUE);
+ }
+
+ public Object read(XMLStreamReader source) throws ContributionReadException, XMLStreamException {
+
+ // Delegate to the processor associated with the element qname
+ QName name = source.getName();
+ StAXArtifactProcessor<?> processor = (StAXArtifactProcessor<?>)processors.getProcessor(name);
+ if (processor == null) {
+ 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);
+ }
+ }
+ }
+
+ @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 input stream.
+ * @param is The artifact inputstream
+ * @param type Model type
+ * @return The model
+ * @throws ContributionReadException
+ */
+ public <MO> MO read(InputStream is, Class<MO> type) throws ContributionReadException {
+ try {
+ XMLStreamReader reader;
+ try {
+ reader = inputFactory.createXMLStreamReader(is);
+ try {
+ reader.nextTag();
+ QName name = reader.getName();
+ Object mo = read(reader);
+ if (type.isInstance(mo)) {
+ return type.cast(mo);
+ } else {
+ UnrecognizedElementException e = new UnrecognizedElementException(name);
+ throw e;
+ }
+ } catch (ContributionReadException e) {
+ Location location = reader.getLocation();
+ e.setLine(location.getLineNumber());
+ e.setColumn(location.getColumnNumber());
+ throw e;
+ } finally {
+ try {
+ reader.close();
+ } catch (XMLStreamException e) {
+ // ignore
+ }
+ }
+ } finally {
+ try {
+ is.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ } catch (XMLStreamException e) {
+ ContributionReadException ce = new ContributionReadException(e);
+ throw ce;
+ }
+ }
+
+ /**
+ * Write a model to an ouput stream.
+ * @param model
+ * @param os
+ * @throws ContributionWriteException
+ */
+ public void write(Object model, OutputStream os) throws ContributionWriteException {
+ try {
+ XMLStreamWriter writer = outputFactory.createXMLStreamWriter(os);
+ write(model, writer);
+ writer.flush();
+ writer.close();
+ } catch (XMLStreamException e) {
+ throw new ContributionWriteException(e);
+ }
+ }
+
+ public QName getArtifactType() {
+ return null;
+ }
+
+ public Class<Object> getModelType() {
+ return null;
+ }
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java
new file mode 100644
index 0000000000..3c7c886d80
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ExtensibleURLArtifactProcessor.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.net.URI;
+import java.net.URL;
+
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.service.ContributionReadException;
+import org.apache.tuscany.sca.contribution.service.ContributionResolveException;
+import org.apache.tuscany.sca.contribution.service.UnrecognizedElementException;
+
+/**
+ * The default implementation of a URL artifact processor.
+ *
+ * This implementation has a URLArtifactProcessorExtensionPoint and
+ * it delegate to the proper URLArtifactProcessor by either fileName or fileExtention
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExtensibleURLArtifactProcessor
+ implements URLArtifactProcessor<Object> {
+
+ private URLArtifactProcessorExtensionPoint processors;
+
+ /**
+ * Constructs a new URL artifact processor.
+ *
+ * @param processors
+ */
+ public ExtensibleURLArtifactProcessor(URLArtifactProcessorExtensionPoint processors) {
+ this.processors = processors;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object read(URL contributionURL, URI sourceURI, URL sourceURL) throws ContributionReadException {
+ URLArtifactProcessor<Object> processor = null;
+
+ // Delegate to the processor associated with file extension
+ String fileName = getFileName(sourceURL);
+
+ //try to retrieve a processor for the specific filename
+ processor = (URLArtifactProcessor<Object>)processors.getProcessor(fileName);
+
+ if (processor == null) {
+ //try to find my file type (extension)
+ String extension = sourceURL.getPath();
+
+ int extensionStart = extension.lastIndexOf('.');
+ //handle files without extension (e.g NOTICE)
+ if (extensionStart > 0) {
+ extension = extension.substring(extensionStart);
+ processor = (URLArtifactProcessor<Object>)processors.getProcessor(extension);
+ }
+ }
+
+ if (processor == null) {
+ return null;
+ }
+ return processor.read(contributionURL, sourceURI, sourceURL);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void resolve(Object model, ModelResolver resolver) throws ContributionResolveException {
+
+ // Delegate to the processor associated with the model type
+ if (model != null) {
+ URLArtifactProcessor processor = processors.getProcessor(model.getClass());
+ if (processor != null) {
+ processor.resolve(model, resolver);
+ }
+ }
+ }
+
+ public <MO> MO read(URL contributionURL, URI artifactURI, URL artifactUrl, Class<MO> type)
+ throws ContributionReadException {
+ Object mo = read(contributionURL, artifactURI, artifactUrl);
+ if (type.isInstance(mo)) {
+ return type.cast(mo);
+ } else {
+ UnrecognizedElementException e = new UnrecognizedElementException(null);
+ e.setResourceURI(artifactURI.toString());
+ throw e;
+ }
+ }
+
+ public String getArtifactType() {
+ return null;
+ }
+
+ public Class<Object> getModelType() {
+ return null;
+ }
+
+ /**
+ * Utility functions
+ */
+
+ private String getFileName(URL url){
+ String fileName = url.getPath();
+ int pos = fileName.lastIndexOf("/");
+
+ return fileName.substring(pos +1);
+ }
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessor.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessor.java
new file mode 100644
index 0000000000..28b268301f
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessor.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.processor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.util.List;
+
+import org.apache.tuscany.sca.contribution.service.ContributionException;
+
+/**
+ * Contribution package processors
+ * These processors understand the internal format of the contribution and how to process the artifacts
+ *
+ * @version $Rev$ $Date$
+ */
+public interface PackageProcessor {
+
+ /**
+ * Returns the type of package supported by this package processor.
+ *
+ * @return the package type
+ */
+ String getPackageType();
+
+ /**
+ * Retrieve a list of artifacts for the specific package type
+ *
+ * @param packageSourceURL Contribution package location URL
+ * @param inputStream Optional content of the package
+ * @return List of artifact URIs
+ * @throws ContributionException
+ * @throws IOException
+ */
+ List<URI> getArtifacts(URL packageSourceURL, InputStream inputStream) throws ContributionException, IOException;
+
+ /**
+ * Return the URL for an artifact in the package.
+ * This is needed in the case of special archives such as jar files that have special
+ * URL structure for internal artifacts
+ *
+ * @param packageSourceURL Contribution package location URL
+ * @param artifact The relative URI for the artifact
+ * @return The artifact URL
+ */
+ URL getArtifactURL(URL packageSourceURL, URI artifact) throws MalformedURLException;
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessorExtensionPoint.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessorExtensionPoint.java
new file mode 100644
index 0000000000..27499b5847
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/PackageProcessorExtensionPoint.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.processor;
+
+/**
+ * An extension point for package processors
+ *
+ * @version $Rev$ $Date$
+ */
+public interface PackageProcessorExtensionPoint {
+
+ /**
+ * Register a PackageProcessor using the package type as the key
+ *
+ * @param processor The package processor
+ */
+ void addPackageProcessor(PackageProcessor processor);
+
+ /**
+ * Unregister a PackageProcessor
+ *
+ * @param processor The package processor
+ */
+ void removePackageProcessor(PackageProcessor processor);
+
+ /**
+ * Returns the PackageProcessor for the given package type.
+ *
+ * @param packageType The package type
+ * @return The package processor
+ */
+ PackageProcessor getPackageProcessor(String packageType);
+
+} \ No newline at end of file
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java
new file mode 100644
index 0000000000..fcf9347564
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessor.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.sca.contribution.service.ContributionReadException;
+import org.apache.tuscany.sca.contribution.service.ContributionWriteException;
+
+/**
+ * An artifact processor that can read models from a StAX XMLStreamReader.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface StAXArtifactProcessor<M> extends ArtifactProcessor<M> {
+
+ /**
+ * Reads a model from an XMLStreamReader.
+ *
+ * @param reader The XMLStreamReader
+ * @return A model representation of the input.
+ */
+ M read(XMLStreamReader reader) throws ContributionReadException, XMLStreamException;
+
+ /**
+ * Writes a model to an XMLStreamWriter.
+ *
+ * @param model A model representing the source
+ * @param writer The XML stream writer
+ * @throws ContributionWriteException
+ * @throws XMLStreamException
+ */
+ void write(M model, XMLStreamWriter writer) throws ContributionWriteException, XMLStreamException;
+
+ /**
+ * Returns the type of artifact handled by this artifact processor.
+ *
+ * @return The type of artifact handled by this artifact processor
+ */
+ QName getArtifactType();
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/StAXArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..fb272d05bc
--- /dev/null
+++ b/branches/sca-java-1.0/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;
+
+/**
+ * A registry for StAX artifact processors.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface StAXArtifactProcessorExtensionPoint extends
+ ArtifactProcessorExtensionPoint<StAXArtifactProcessor> {
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java
new file mode 100644
index 0000000000..eb6201c856
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessor.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.net.URI;
+import java.net.URL;
+
+import org.apache.tuscany.sca.contribution.service.ContributionReadException;
+
+/**
+ * An artifact processor that can read models from an InputStream.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface URLArtifactProcessor<M> extends ArtifactProcessor<M> {
+
+ /**
+ * Reads a model from a URL.
+ *
+ * @param contributionURL Contribution location URL
+ * @param artifactURI Artifact URI
+ * @param artifactURL Artifact location URL
+ * @return A model representation of the input.
+ */
+ M read(URL contributionURL, URI artifactURI, URL artifactURL) throws ContributionReadException;
+
+ /**
+ * Returns the type of artifact handled by this artifact processor.
+ *
+ * @return The type of artifact handled by this artifact processor
+ */
+ String getArtifactType();
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/URLArtifactProcessorExtensionPoint.java
new file mode 100644
index 0000000000..0b02c12830
--- /dev/null
+++ b/branches/sca-java-1.0/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;
+
+/**
+ * A registry for Document artifact processors.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface URLArtifactProcessorExtensionPoint extends
+ ArtifactProcessorExtensionPoint<URLArtifactProcessor> {
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java
new file mode 100644
index 0000000000..bd1687fafd
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/ValidatingXMLStreamReader.java
@@ -0,0 +1,319 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.processor;
+
+import java.util.logging.Logger;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.util.StreamReaderDelegate;
+import javax.xml.validation.Schema;
+import javax.xml.validation.ValidatorHandler;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+ *
+ * A validating XMLStreamReader that reports XMLSchema validation errors.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ValidatingXMLStreamReader extends StreamReaderDelegate implements XMLStreamReader {
+ private static final Logger logger = Logger.getLogger(ValidatingXMLStreamReader.class.getName());
+
+ private int level;
+ private ValidatorHandler handler;
+
+ public ValidatingXMLStreamReader(XMLStreamReader reader, Schema schema) throws XMLStreamException {
+ super(reader);
+ if (schema == null) {
+ return;
+ }
+
+ handler = schema.newValidatorHandler();
+ handler.setDocumentLocator(new LocatorAdaptor());
+ try {
+ handler.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
+ } catch (SAXException e) {
+ throw new XMLStreamException(e);
+ }
+
+ // These validation errors are just warnings for us as we want to support
+ // running from an XML document with XSD validation errors, as long as we can
+ // get the metadata we need from the document
+ handler.setErrorHandler(new ErrorHandler() {
+ private String getMessage(SAXParseException e) {
+ return "XMLSchema validation problem in: " + e.getSystemId() + ", line: " + e.getLineNumber() + ", column: " + e.getColumnNumber() + "\n" + e.getMessage();
+ }
+
+ public void error(SAXParseException exception) throws SAXException {
+ logger.warning(getMessage(exception));
+ }
+
+ public void fatalError(SAXParseException exception) throws SAXException {
+ logger.warning(getMessage(exception));
+ }
+
+ public void warning(SAXParseException exception) throws SAXException {
+ logger.warning(getMessage(exception));
+ }
+ });
+ }
+
+ @Override
+ public int next() throws XMLStreamException {
+ if (handler == null) {
+ return super.next();
+ }
+
+ int event = super.next();
+ try {
+ switch (event) {
+ case XMLStreamConstants.START_DOCUMENT:
+ level++;
+ handler.startDocument();
+ break;
+ case XMLStreamConstants.START_ELEMENT:
+ level++;
+ handleStartElement();
+ break;
+ case XMLStreamConstants.PROCESSING_INSTRUCTION:
+ handler.processingInstruction(super.getPITarget(), super.getPIData());
+ break;
+ case XMLStreamConstants.CHARACTERS:
+ case XMLStreamConstants.CDATA:
+ case XMLStreamConstants.SPACE:
+ case XMLStreamConstants.ENTITY_REFERENCE:
+ handler.characters(super.getTextCharacters(), super.getTextStart(), super.getTextLength());
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ handleEndElement();
+ level--;
+ break;
+ case XMLStreamConstants.END_DOCUMENT:
+ handler.endDocument();
+ break;
+ }
+ } catch (SAXException e) {
+ throw new XMLStreamException(e.getMessage(), e);
+ }
+ return event;
+ }
+
+ @Override
+ public int nextTag() throws XMLStreamException {
+ if (handler == null) {
+ return super.nextTag();
+ }
+
+ for (;;) {
+ int event = super.getEventType();
+ try {
+ switch (event) {
+ case XMLStreamConstants.START_DOCUMENT:
+ level++;
+ handler.startDocument();
+ break;
+ case XMLStreamConstants.START_ELEMENT:
+ level++;
+ handleStartElement();
+ return event;
+ case XMLStreamConstants.PROCESSING_INSTRUCTION:
+ handler.processingInstruction(super.getPITarget(), super.getPIData());
+ break;
+ case XMLStreamConstants.CHARACTERS:
+ case XMLStreamConstants.CDATA:
+ case XMLStreamConstants.SPACE:
+ case XMLStreamConstants.ENTITY_REFERENCE:
+ handler.characters(super.getTextCharacters(), super.getTextStart(), super.getTextLength());
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ handleEndElement();
+ level--;
+ return event;
+ case XMLStreamConstants.END_DOCUMENT:
+ handler.endDocument();
+ return event;
+ }
+ } catch (SAXException e) {
+ throw new XMLStreamException(e);
+ }
+ super.next();
+ }
+ }
+
+ @Override
+ public String getElementText() throws XMLStreamException {
+ if (handler == null) {
+ return super.getElementText();
+ }
+
+ if (getEventType() != XMLStreamConstants.START_ELEMENT) {
+ return super.getElementText();
+ }
+ StringBuffer text = new StringBuffer();
+
+ for (;;) {
+ int event = next();
+ switch (event) {
+ case XMLStreamConstants.END_ELEMENT:
+ return text.toString();
+
+ case XMLStreamConstants.COMMENT:
+ case XMLStreamConstants.PROCESSING_INSTRUCTION:
+ continue;
+
+ case CHARACTERS:
+ case CDATA:
+ case SPACE:
+ case ENTITY_REFERENCE:
+ text.append(getText());
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ 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);
+ }
+
+ 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;
+ }
+
+ /**
+ * Adaptor for mapping Locator information.
+ */
+ private final class LocatorAdaptor implements Locator {
+
+ private LocatorAdaptor() {
+ }
+
+ public int getColumnNumber() {
+ Location location = getLocation();
+ return location == null ? 0 : location.getColumnNumber();
+ }
+
+ public int getLineNumber() {
+ Location location = getLocation();
+ return location == null ? 0 : location.getLineNumber();
+ }
+
+ public String getPublicId() {
+ Location location = getLocation();
+ return location == null ? "" : location.getPublicId();
+ }
+
+ public String getSystemId() {
+ Location location = getLocation();
+ return location == null ? "" : location.getSystemId();
+ }
+ }
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.java
new file mode 100644
index 0000000000..6715341ca9
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ClassReference.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.lang.ref.WeakReference;
+
+/**
+ * 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 ClassReference {
+
+ private WeakReference<Class> clazz;
+ private String className;
+
+ /**
+ * Constructs a new ClassReference.
+ *
+ * @param clazz The class reference
+ */
+ public ClassReference(Class clazz) {
+ this.clazz = new WeakReference<Class>(clazz);
+ this.className = clazz.getName();
+ }
+
+ /**
+ * Constructs a new ClassReference.
+ *
+ * @param className The class name
+ */
+ public ClassReference(String className) {
+ this.className = className;
+ }
+
+ /**
+ * Get the referenced class.
+ *
+ * @return The referenced class
+ */
+ public Class getJavaClass() {
+ if (clazz != null) {
+ return clazz.get();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Get the referenced class name.
+ *
+ * @return The class name
+ */
+ public String getClassName() {
+ return className;
+ }
+
+ /**
+ * Returns true if the class reference is unresolved.
+ *
+ * @return Wether or not the class has been resolved
+ */
+ public boolean isUnresolved() {
+ return clazz == null;
+ }
+
+ @Override
+ public int hashCode() {
+ return className.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ } else {
+ if (obj instanceof ClassReference) {
+ return className.equals(((ClassReference)obj).className);
+ } else {
+ return false;
+ }
+ }
+ }
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java
new file mode 100644
index 0000000000..ce6305814a
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultImportAllModelResolver.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.resolver;
+
+import java.util.List;
+
+import org.apache.tuscany.sca.assembly.Base;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.Export;
+import org.apache.tuscany.sca.contribution.Import;
+
+/**
+ * A model resolver implementation that considers Exports in any available contribution
+ *
+ * @version $Rev: 560435 $ $Date: 2007-07-27 18:26:55 -0700 (Fri, 27 Jul 2007) $
+ */
+public class DefaultImportAllModelResolver implements ModelResolver {
+
+ private Import import_;
+ private List<Contribution> contributions;
+
+ public DefaultImportAllModelResolver(Import import_, List<Contribution> contributions) {
+ this.import_ = import_;
+ this.contributions = contributions;
+ }
+
+ public void addModel(Object resolved) {
+ throw new IllegalStateException();
+ }
+
+ public Object removeModel(Object resolved) {
+ throw new IllegalStateException();
+ }
+
+ public <T> T resolveModel(Class<T> modelClass, T unresolved) {
+
+ //TODO optimize and cache results of the resolution later
+
+ // Go over all available contributions
+ for (Contribution contribution : contributions) {
+
+ // Go over all exports in the contribution
+ for (Export export : contribution.getExports()) {
+ // If the export matches our namespace, try to the 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);
+ }
+ }
+ else if (resolved instanceof org.apache.tuscany.sca.assembly.Base) {
+ if (!((org.apache.tuscany.sca.assembly.Base)resolved).isUnresolved()) {
+ return modelClass.cast(resolved);
+ }
+ }
+ }
+ }
+ }
+
+ // Model object was not resolved
+ return unresolved;
+ }
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.java
new file mode 100644
index 0000000000..bde0f24341
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/DefaultModelResolverExtensionPoint.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.resolver;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tuscany.sca.contribution.util.ServiceConfigurationUtil;
+
+/**
+ * The default implementation of a model resolver Class registry.
+ *
+ * @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, String> loadedResolvers;
+
+ /**
+ * Constructs a new model resolver registry.
+ */
+ public DefaultModelResolverExtensionPoint() {
+ }
+
+ public void addResolver(Class<?> modelType, Class<? extends ModelResolver> resolver) {
+ resolvers.put(modelType, resolver);
+ }
+
+ public void removeResolver(Class<?> modelType) {
+ resolvers.remove(modelType);
+ }
+
+ 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) {
+ String className = loadedResolvers.get(c.getName());
+ if (className != null) {
+ try {
+ return (Class<? extends ModelResolver>)Class.forName(className, true, modelType.getClassLoader());
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ } else {
+ return resolver;
+ }
+ }
+
+ Class<? extends ModelResolver > resolver = resolvers.get(modelType);
+ if (resolver == null) {
+ String className = loadedResolvers.get(modelType.getName());
+ if (className != null) {
+ try {
+ return (Class<? extends ModelResolver>)Class.forName(className, true, modelType.getClassLoader());
+ } 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, String>();
+
+ // Get the model resolver service declarations
+ ClassLoader classLoader = ModelResolver.class.getClassLoader();
+ List<String> modelResolverDeclarations;
+ try {
+ modelResolverDeclarations = ServiceConfigurationUtil.getServiceClassNames(classLoader, ModelResolver.class.getName());
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+
+ // Load model resolvers
+ for (String dataBindingDeclaration: modelResolverDeclarations) {
+ Map<String, String> attributes = ServiceConfigurationUtil.parseServiceDeclaration(dataBindingDeclaration);
+ String className = attributes.get("class");
+ String model = attributes.get("model");
+
+ loadedResolvers.put(model, className);
+ }
+ }
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java
new file mode 100644
index 0000000000..e6899e3174
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ExtensibleModelResolver.java
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.resolver;
+
+import java.lang.reflect.Constructor;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.ModelFactoryExtensionPoint;
+
+/**
+ * An implementation of an extensible model resolver which delegates to the
+ * proper resolver extension based on the class of the model to resolve.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ExtensibleModelResolver implements ModelResolver {
+ private final ModelResolverExtensionPoint resolvers;
+ private final ModelFactoryExtensionPoint factories;
+ private final Contribution contribution;
+ private final Map<Class<?>, ModelResolver> resolverInstances = new HashMap<Class<?>, ModelResolver>();
+ private Map<Object, Object> map = new HashMap<Object, Object>();
+ private ModelResolver domainResolver = null;
+
+ /**
+ * Constructs an extensible model resolver
+ *
+ * @param resolvers
+ * @param contribution
+ */
+ public ExtensibleModelResolver(Contribution contribution,
+ ModelResolverExtensionPoint resolvers,
+ ModelFactoryExtensionPoint factories) {
+ this.contribution = contribution;
+ this.resolvers = resolvers;
+ this.factories = factories;
+ }
+
+ /**
+ * Returns the proper resolver instance based on the interfaces of the model
+ * If one is not available on the registry, instantiate on demand
+ *
+ * @param modelType
+ * @return
+ */
+ private ModelResolver getModelResolverInstance(Class<?> modelType) {
+
+ // Look up a model resolver instance for the model class or
+ // each implemented interface
+ Class<?>[] interfaces = modelType.getInterfaces();
+ Class<?>[] classes = new Class<?>[interfaces.length + 1];
+ classes[0] = modelType;
+ if (interfaces.length != 0) {
+ System.arraycopy(interfaces, 0, classes, 1, interfaces.length);
+ }
+ for (Class<?> c : classes) {
+
+ // Look up an existing model resolver instance
+ ModelResolver resolverInstance = resolverInstances.get(c);
+ if (resolverInstance != null) {
+ return resolverInstance;
+ }
+
+ // We don't have an instance, lookup a model resolver class
+ // and instantiate it
+ Class<? extends ModelResolver> resolverClass = resolvers.getResolver(c);
+ if (resolverClass != null) {
+ try {
+ Constructor<? extends ModelResolver> constructor =
+ resolverClass
+ .getConstructor(new Class[] {Contribution.class, ModelFactoryExtensionPoint.class});
+ if (constructor != null) {
+
+ // Construct the model resolver instance and cache it
+ resolverInstance = constructor.newInstance(contribution, factories);
+ resolverInstances.put(c, resolverInstance);
+ return resolverInstance;
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public void addModel(Object resolved) {
+ ModelResolver resolver = getModelResolverInstance(resolved.getClass());
+ if (resolver != null) {
+ resolver.addModel(resolved);
+ } else {
+ map.put(resolved, resolved);
+ }
+ }
+
+ public Object removeModel(Object resolved) {
+ ModelResolver resolver = getModelResolverInstance(resolved.getClass());
+ if (resolver != null) {
+ return resolver.removeModel(resolved);
+ } else {
+ return map.remove(resolved);
+ }
+ }
+
+ public <T> T resolveModel(Class<T> modelClass, T unresolved) {
+ ModelResolver resolver = getModelResolverInstance(unresolved.getClass());
+ if (resolver != null) {
+ return resolver.resolveModel(modelClass, unresolved);
+ } else {
+ if (domainResolver != null) {
+ Object resolved = domainResolver.resolveModel(modelClass, unresolved);
+ if (resolved != null && resolved != unresolved) {
+ return modelClass.cast(resolved);
+ }
+ }
+ Object resolved = map.get(unresolved);
+ if (resolved != null) {
+ // Return the resolved object
+ return modelClass.cast(resolved);
+ }
+ }
+
+ return unresolved;
+ }
+
+ public ModelResolver getDomainResolver() {
+ return domainResolver;
+ }
+
+ public void setDomainResolver(ModelResolver domainResolver) {
+ this.domainResolver = domainResolver;
+ }
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.java
new file mode 100644
index 0000000000..850f79fdea
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolver.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;
+
+/**
+ * SCA Assemblies reference many 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 URIs that do not point to a specific entity. Resolution of these
+ * references to concrete artifacts is necessary as part of the operation of the
+ * SCA domain.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ModelResolver {
+
+ /**
+ * Resolve the model representing an artifact.
+ *
+ * @param modelClass the type of artifact
+ * @param unresolved the unresolved model
+ * @return the resolved model
+ */
+ <T> T resolveModel(Class<T> modelClass, T unresolved);
+
+ /**
+ * Add a resolved model.
+ *
+ * @param resolved The model
+ */
+ void addModel(Object resolved);
+
+ /**
+ * Remove a resolved model.
+ *
+ * @param resolved
+ * @return The removed model, or null if the model was not removed
+ */
+ Object removeModel(Object resolved);
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/resolver/ModelResolverExtensionPoint.java
new file mode 100644
index 0000000000..0b14b7f3c3
--- /dev/null
+++ b/branches/sca-java-1.0/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 Artifact Type as the key
+ *
+ * @param modelType The model artifact type
+ * @param resolver The model resolver Class
+ */
+ void addResolver(Class<?> modelType, Class <? extends ModelResolver> resolver);
+
+ /**
+ * Remove the Model Resolver Class for a specific Artifact Type
+ *
+ * @param modelType The model artifact type
+ */
+ void removeResolver(Class<?> modelType);
+
+ /**
+ * Retrieve a Model Resolver Class for a specific Artifact Type
+ *
+ * @param modelType The model artifact type
+ * @return The model resolver Class
+ */
+ Class <? extends ModelResolver> getResolver(Class<?> modelType);
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/AbstractContributionException.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/AbstractContributionException.java
new file mode 100644
index 0000000000..e5b18b4738
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/AbstractContributionException.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.service;
+
+import java.io.PrintWriter;
+
+/**
+ * The root checked exception for the Contribution Service.
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractContributionException extends Exception {
+ private static final long serialVersionUID = -7847121698339635268L;
+ private final String identifier;
+
+ /**
+ * Override constructor from Exception.
+ *
+ * @see Exception
+ */
+ public AbstractContributionException() {
+ super();
+ this.identifier = null;
+ }
+
+ /**
+ * Override constructor from Exception.
+ *
+ * @param message passed to Exception
+ * @see Exception
+ */
+ public AbstractContributionException(String message) {
+ super(message);
+ this.identifier = null;
+ }
+
+ /**
+ * Override constructor from Exception.
+ *
+ * @param message passed to Exception
+ * @param identifier additional error information referred to in the error message
+ * @see Exception
+ */
+ public AbstractContributionException(String message, String identifier) {
+ super(message);
+ this.identifier = identifier;
+ }
+
+ /**
+ * Override constructor from Exception.
+ *
+ * @param message passed to Exception
+ * @param cause passed to Exception
+ * @see Exception
+ */
+ public AbstractContributionException(String message, Throwable cause) {
+ super(message, cause);
+ this.identifier = null;
+ }
+
+ /**
+ * Override constructor from Exception.
+ *
+ * @param message passed to Exception
+ * @param identifier additional error information referred to in the error message
+ * @param cause passed to Exception
+ * @see Exception
+ */
+ public AbstractContributionException(String message, String identifier, Throwable cause) {
+ super(message, cause);
+ this.identifier = identifier;
+ }
+
+ /**
+ * Override constructor from Exception.
+ *
+ * @param cause passed to Exception
+ * @see Exception
+ */
+ public AbstractContributionException(Throwable cause) {
+ super(cause);
+ this.identifier = null;
+ }
+
+ /**
+ * Returns a string representing additional error information referred to in the error message.
+ *
+ * @return additional error information
+ */
+ public String getIdentifier() {
+ return identifier;
+ }
+
+ public PrintWriter appendBaseMessage(PrintWriter writer) {
+ if (identifier == null) {
+ if (super.getMessage() == null) {
+ return writer;
+ }
+ return writer.append(super.getMessage());
+ }
+ if (super.getMessage() != null) {
+ writer.append(super.getMessage());
+ }
+ writer.append(" [").append(identifier).append(']');
+ return writer;
+ }
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionException.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionException.java
new file mode 100644
index 0000000000..484200286b
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionException.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.service;
+
+/**
+ * Base class for exceptions raised by contribution services.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ContributionException extends AbstractContributionException {
+
+ private static final long serialVersionUID = 4432880414927652578L;
+
+ protected ContributionException() {
+ super();
+ }
+
+ protected ContributionException(String message) {
+ super(message);
+ }
+
+ protected ContributionException(String message, String identifier) {
+ super(message, identifier);
+ }
+
+ protected ContributionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ protected ContributionException(String message, String identifier, Throwable cause) {
+ super(message, identifier, cause);
+ }
+
+ public ContributionException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListener.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListener.java
new file mode 100644
index 0000000000..5158eaf85c
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListener.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.service;
+
+import java.util.EventListener;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+
+/**
+ * A listener interface used to listen to contribution repository events.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ContributionListener extends EventListener {
+
+ /**
+ * Notifies the listener that a contribution has been added.
+ *
+ * @param repository The contribution repository
+ * @param contribution The new contribution
+ */
+ void contributionAdded(ContributionRepository repository, Contribution contribution);
+
+ /**
+ * Notifies the listener that a contribution has been removed.
+ *
+ * @param repository The contribution repository
+ * @param contribution The removed contribution.
+ */
+ void contributionRemoved(ContributionRepository repository, Contribution contribution);
+
+ /**
+ * Notifies the listener that a contribution has been updated.
+ *
+ * @param repository The contribution repository
+ * @param oldContribution The old contribution
+ * @param contribution The new contribution
+ */
+ void contributionUpdated(ContributionRepository repository, Contribution oldContribution, Contribution contribution);
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListenerExtensionPoint.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListenerExtensionPoint.java
new file mode 100644
index 0000000000..ce2b4b13c3
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionListenerExtensionPoint.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.service;
+
+import java.util.List;
+
+public interface ContributionListenerExtensionPoint {
+
+ /**
+ * Adds a contribution repository listener extension.
+ * @param listener The listener to add
+ */
+ void addContributionListener(ContributionListener listener);
+
+ /**
+ * Removes a contribution repository listener extension.
+ * @param listener The listener to remove
+ */
+ void removeContributionListener(ContributionListener listener);
+
+ /**
+ * Returns the contribution repository listeners.
+ * @return
+ */
+ List<ContributionListener> getContributionListeners();
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionReadException.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionReadException.java
new file mode 100644
index 0000000000..33399dcc2f
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionReadException.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.service;
+
+/**
+ * Denotes an exception while reading artifacts inside an SCA contribution.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ContributionReadException extends ContributionException {
+ public static final int UNDEFINED = -1;
+ private static final long serialVersionUID = -7459051598906813461L;
+ private String resourceURI;
+ private int line = UNDEFINED;
+ private int column = UNDEFINED;
+
+ public ContributionReadException(String message) {
+ super(message);
+ }
+
+ public ContributionReadException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ContributionReadException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Returns the location of the resource that was being read.
+ *
+ * @return the location of the resource that was being read
+ */
+ public String getResourceURI() {
+ return resourceURI;
+ }
+
+ /**
+ * Sets the location of the resource that was being read.
+ *
+ * @param resourceURI the location of the resource that was being read
+ */
+ public void setResourceURI(String resourceURI) {
+ this.resourceURI = resourceURI;
+ }
+
+ /**
+ * Returns the line inside the resource that was being read.
+ * @return the line inside the resource that was being read
+ */
+ public int getLine() {
+ return line;
+ }
+
+ /**
+ * Sets the line inside the resource that was being read.
+ * @param line the line inside the resource that was being read
+ */
+ public void setLine(int line) {
+ this.line = line;
+ }
+
+ /**
+ * Returns the column inside the resource that was being read.
+ * @return the column inside the resource that was being read
+ */
+ public int getColumn() {
+ return column;
+ }
+
+ /**
+ * Sets the column inside the resource that was being read.
+ * @param column the column inside the resource that was being read
+ */
+ public void setColumn(int column) {
+ this.column = column;
+ }
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRepository.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRepository.java
new file mode 100644
index 0000000000..838359be5f
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRepository.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.service;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+import java.util.List;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+
+/**
+ * Contribution repository
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ContributionRepository {
+
+ /**
+ * Get the URI of the SCA domain
+ *
+ * @return The domain URI
+ */
+ URI getDomain();
+
+ /**
+ * Copies a contribution to the repository.
+ *
+ * @param contribution A URl pointing to the contribution being copied to
+ * the repository
+ * @param sourceURL url of the source. this would be used to calculate the right
+ * filename to be stored on the repository when a inputStream is being
+ * provided
+ * @param contributionStream InputStream with the content of the
+ * distribution
+ * @return A URL pointing to the content of the contribution in the
+ * repository
+ * @throws IOException
+ */
+ URL store(String contribution, URL sourceURL, InputStream contributionStream) throws IOException;
+ /**
+ * Copy a contribution from the source URL to the repository
+ *
+ * @param contribution A URl pointing to the contribution being copied to
+ * the repository
+ * @param sourceURL url of the source. this would be used to calculate the right
+ * filename to be stored on the repository when a inputStream is being
+ * provided
+ * @return A URL pointing to the content of the contribution in the
+ * repository
+ * @throws IOException
+ */
+ URL store(String contribution, URL sourceURL) throws IOException;
+
+ /**
+ * Look up the contribution by URI
+ *
+ * @param contribution The URI of the contribution
+ * @return A URL pointing to the content of the contribution in the
+ * repository, it will be null if the contribution cannot be found
+ * in the repository
+ */
+ URL find(String contribution);
+
+ /**
+ * Remove a contribution from the repository
+ *
+ * @param contribution The URI of the contribution to be removed
+ */
+ void remove(String contribution);
+
+ /**
+ * Get list of URIs for all the contributions in the repository
+ *
+ * @return A list of contribution URIs
+ */
+ List<String> list();
+
+ /**
+ * Returns the contributions available in the repository.
+ * @return The list of contributions.
+ */
+ List<Contribution> getContributions();
+
+ /**
+ * Adds a contribution to the repository.
+ * @param contribution The new contribution.
+ */
+ void addContribution(Contribution contribution);
+
+ /**
+ * Removes a contribution from the repository.
+ * @param contribution The contribution to remove
+ */
+ void removeContribution(Contribution contribution);
+
+ /**
+ * Updates a contribution in the repository
+ * @param contribution The contribution to update
+ */
+ void updateContribution(Contribution contribution);
+
+ /**
+ * Returns the contribution with the given URI.
+ * @param uri the URI of the contribution
+ * @return The contribution
+ */
+ Contribution getContribution(String uri);
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionResolveException.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionResolveException.java
new file mode 100644
index 0000000000..ecb774ac0c
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionResolveException.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.service;
+
+/**
+ * Denotes a problem while resolving models inside an SCA contribution.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ContributionResolveException extends ContributionException {
+ private static final long serialVersionUID = -7459051598906813461L;
+
+ public ContributionResolveException(String message) {
+ super(message);
+ }
+
+ public ContributionResolveException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ContributionResolveException(Throwable cause) {
+ super(cause);
+ }
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRuntimeException.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRuntimeException.java
new file mode 100644
index 0000000000..4bf29a3993
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionRuntimeException.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.service;
+
+/**
+ * Base class for runtime exceptions raised by contribution services.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ContributionRuntimeException extends RuntimeException {
+ private static final long serialVersionUID = 7711215366287498896L;
+
+ protected ContributionRuntimeException() {
+ super();
+ }
+
+ protected ContributionRuntimeException(String message) {
+ super(message);
+ }
+
+ protected ContributionRuntimeException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ContributionRuntimeException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionService.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionService.java
new file mode 100644
index 0000000000..d82f89b79e
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionService.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.service;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+
+/**
+ * Service interface that manages artifacts contributed to a Tuscany runtime.
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ContributionService {
+ /**
+ * Contribute an artifact to the SCA Domain. The type of the contribution is
+ * determined by the Content-Type of the resource or, if that is undefined,
+ * by some implementation-specific means (such as mapping an extension in
+ * the URL's path).
+ *
+ * @param contributionURI The URI that is used as the contribution unique ID.
+ * @param sourceURL The location of the resource containing the artifact
+ * @param modelResolver The model resolver to use to resolve models in the
+ * scope of this contribution
+ * @param storeInRepository Flag that identifies if you want to copy the
+ * contribution to the repository
+ * @return The contribution model representing the contribution
+ * @throws DeploymentException if there was a problem with the contribution
+ * @throws IOException if there was a problem reading the resource
+ */
+ Contribution contribute(String contributionURI, URL sourceURL, boolean storeInRepository) throws ContributionException,
+ IOException;
+
+ /**
+ * Contribute an artifact to the SCA Domain. The type of the contribution is
+ * determined by the Content-Type of the resource or, if that is undefined,
+ * by some implementation-specific means (such as mapping an extension in
+ * the URL's path).
+ *
+ * @param contributionURI The URI that is used as the contribution unique ID.
+ * @param sourceURL The location of the resource containing the artifact
+ * @param modelResolver The model resolver to use to resolve models in the
+ * scope of this contribution
+ * @param storeInRepository Flag that identifies if you want to copy the
+ * contribution to the repository
+ * @return The contribution model representing the contribution
+ * @throws DeploymentException if there was a problem with the contribution
+ * @throws IOException if there was a problem reading the resource
+ */
+ Contribution contribute(String contributionURI, URL sourceURL, ModelResolver modelResolver, boolean storeInRepository) throws ContributionException,
+ IOException;
+
+ /**
+ * Contribute an artifact to the SCA Domain.
+ *
+ * @param contributionURI The URI that is used as the contribution unique ID.
+ * @param sourceURL The location of the resource containing the artifact.
+ * This is used to identify what name should be used when storing
+ * the contribution on the repository
+ * @param modelResolver The model resolver to use to resolve models in the
+ * scope of this contribution
+ * @param contributionContent A stream containing the resource being
+ * contributed; the stream will not be closed but the read
+ * position after the call is undefined
+ * @return The contribution model representing the contribution
+ * @throws DeploymentException if there was a problem with the contribution
+ * @throws IOException if there was a problem reading the stream
+ */
+ Contribution contribute(String contributionURI, URL sourceURL, InputStream contributionContent)
+ throws ContributionException, IOException;
+
+ /**
+ * Contribute an artifact to the SCA Domain.
+ *
+ * @param contributionURI The URI that is used as the contribution unique ID.
+ * @param sourceURL The location of the resource containing the artifact.
+ * This is used to identify what name should be used when storing
+ * the contribution on the repository
+ * @param modelResolver The model resolver to use to resolve models in the
+ * scope of this contribution
+ * @param contributionContent A stream containing the resource being
+ * contributed; the stream will not be closed but the read
+ * position after the call is undefined
+ * @return The contribution model representing the contribution
+ * @throws DeploymentException if there was a problem with the contribution
+ * @throws IOException if there was a problem reading the stream
+ */
+ Contribution contribute(String contributionURI, URL sourceURL, InputStream contributionContent, ModelResolver modelResolver)
+ throws ContributionException, IOException;
+
+ /**
+ * Get the model for an installed contribution
+ *
+ * @param contribution The URI of an installed contribution
+ * @return The model for the contribution or null if there is no such
+ * contribution
+ */
+ Contribution getContribution(String contribution);
+
+ /**
+ * Adds or updates a deployment composite using a supplied composite
+ * ("composite by value" - a data structure, not an existing resource in the
+ * domain) to the contribution identified by a supplied contribution URI.
+ * The added or updated deployment composite is given a relative URI that
+ * matches the "name" attribute of the composite, with a ".composite"
+ * suffix.
+ *
+ * @param contribution The contribution to where
+ * @param composite
+ * @throws ContributionException
+ */
+ void addDeploymentComposite(Contribution contribution, Composite composite) throws ContributionException;
+
+ /**
+ * Remove a contribution from the SCA domain
+ *
+ * @param contribution The URI of the contribution
+ * @throws DeploymentException
+ */
+ void remove(String contribution) throws ContributionException;
+
+} \ No newline at end of file
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionWireException.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionWireException.java
new file mode 100644
index 0000000000..f67b2a1e51
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionWireException.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.service;
+
+
+/**
+ * Denotes a problem while wiring models inside an SCA contribution.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ContributionWireException extends ContributionException {
+ private static final long serialVersionUID = -7459051598906813461L;
+
+ public ContributionWireException(String message) {
+ super(message);
+ }
+
+ public ContributionWireException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ContributionWireException(Throwable cause) {
+ super(cause);
+ }
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionWriteException.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionWriteException.java
new file mode 100644
index 0000000000..8bfdedf180
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ContributionWriteException.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.service;
+
+
+/**
+ * Denotes an exception while writing artifacts inside an SCA contribution.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ContributionWriteException extends ContributionException {
+ private static final long serialVersionUID = -7459051598906813461L;
+ private String resourceURI;
+
+ public ContributionWriteException(String message) {
+ super(message);
+ }
+
+ public ContributionWriteException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ContributionWriteException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Returns the location of the resource that was being written.
+ *
+ * @return the location of the resource that was being written
+ */
+ public String getResourceURI() {
+ return resourceURI;
+ }
+
+ /**
+ * Sets the location of the resource that was being written.
+ *
+ * @param resourceURI the location of the resource that was being written
+ */
+ public void setResourceURI(String resourceURI) {
+ this.resourceURI = resourceURI;
+ }
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/DefaultContributionListenerExtensionPoint.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/DefaultContributionListenerExtensionPoint.java
new file mode 100644
index 0000000000..9e77705ed3
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/DefaultContributionListenerExtensionPoint.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.service;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tuscany.sca.contribution.util.ServiceConfigurationUtil;
+
+/**
+ * Default implementation of a contribution listener extension point.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultContributionListenerExtensionPoint implements ContributionListenerExtensionPoint {
+
+ private List<ContributionListener> listeners = new ArrayList<ContributionListener>();
+ private boolean loadedListeners;
+
+ public void addContributionListener(ContributionListener listener) {
+ listeners.add(listener);
+ }
+
+ public List<ContributionListener> getContributionListeners() {
+ loadListeners();
+ return listeners;
+ }
+
+ public void removeContributionListener(ContributionListener listener) {
+ listeners.remove(listener);
+ }
+
+ /**
+ * Dynamically load listeners declared under META-INF/services
+ */
+ private void loadListeners() {
+ if (loadedListeners)
+ return;
+
+ // Get the databinding service declarations
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ List<String> listenerDeclarations;
+ try {
+ listenerDeclarations = ServiceConfigurationUtil.getServiceClassNames(classLoader, ContributionListener.class.getName());
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+
+ // Load data bindings
+ for (String listenerDeclaration: listenerDeclarations) {
+ ContributionListener listener;
+ try {
+ Class<ContributionListener> listenerClass = (Class<ContributionListener>)Class.forName(listenerDeclaration, true, classLoader);
+ listener = listenerClass.newInstance();
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException(e);
+ } catch (InstantiationException e) {
+ throw new IllegalArgumentException(e);
+ } catch (IllegalAccessException e) {
+ throw new IllegalArgumentException(e);
+ }
+ addContributionListener(listener);
+ }
+
+ loadedListeners = true;
+ }
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ExtensibleContributionListener.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ExtensibleContributionListener.java
new file mode 100644
index 0000000000..0b9aca70cf
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/ExtensibleContributionListener.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.service;
+
+import org.apache.tuscany.sca.contribution.Contribution;
+
+public class ExtensibleContributionListener implements ContributionListener {
+ private final ContributionListenerExtensionPoint listeners;
+
+ /**
+ * Default constructor receiving the listener extension point
+ *
+ * @param listeners
+ */
+ public ExtensibleContributionListener(ContributionListenerExtensionPoint listeners) {
+ this.listeners = listeners;
+ }
+
+ /**
+ * Process "contributionAdded" event to all resigtered listeners
+ */
+ public void contributionAdded(ContributionRepository repository, Contribution contribution) {
+ for (ContributionListener listener : listeners.getContributionListeners()) {
+ try {
+ listener.contributionAdded(repository, contribution);
+ } catch (Exception e) {
+ // ignore, contiue to the next listener
+ }
+ }
+ }
+
+ /**
+ * Process "contributionRemoved" event to all registered listeners
+ */
+ public void contributionRemoved(ContributionRepository repository, Contribution contribution) {
+ for (ContributionListener listener : listeners.getContributionListeners()) {
+ try {
+ listener.contributionRemoved(repository, contribution);
+ } catch (Exception e) {
+ // ignore, contiue to the next listener
+ }
+
+ }
+ }
+
+ /**
+ * Process "contributionUpdated" event to all registered listeners
+ */
+ public void contributionUpdated(ContributionRepository repository, Contribution oldContribution, Contribution contribution) {
+ for (ContributionListener listener : listeners.getContributionListeners()) {
+ try {
+ listener.contributionUpdated(repository, oldContribution, contribution);
+ } catch (Exception e) {
+ // ignore, contiue to the next listener
+ }
+
+ }
+ }
+
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/TypeDescriber.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/TypeDescriber.java
new file mode 100644
index 0000000000..b0e02f06fa
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/TypeDescriber.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.service;
+
+import java.net.URL;
+
+/**
+ * Provide content type for a given resource
+ *
+ * @version $Rev$ $Date$
+ */
+public interface TypeDescriber {
+ /**
+ * Get the content type for the specified resource
+ *
+ * @param resourceURL The resource url
+ * @param defaultType The default content type
+ * @return The content type
+ */
+ String getType(URL resourceURL, String defaultType);
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnrecognizedElementException.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnrecognizedElementException.java
new file mode 100644
index 0000000000..5079db4904
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnrecognizedElementException.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.service;
+
+import javax.xml.namespace.QName;
+
+/**
+ * Exception that indicates an element was encountered that could not be handled.
+ *
+ * @version $Rev$ $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.toString());
+ this.element = element;
+ }
+
+ /**
+ * Returns the element that could not be handled.
+ * @return the element that could not be handled.
+ */
+ public QName getElement() {
+ return element;
+ }
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedContentTypeException.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedContentTypeException.java
new file mode 100644
index 0000000000..764fe251f2
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/service/UnsupportedContentTypeException.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.service;
+
+/**
+ * Exception thrown to indicate that a Content-Type is not supported by this SCA Domain.
+ * The Content-Type value supplied will be returned as the message text for this exception.
+ *
+ * @version $Rev$ $Date$
+ */
+public class UnsupportedContentTypeException extends ContributionException {
+ private static final long serialVersionUID = -1831797280021355672L;
+
+ /**
+ * Constructor specifying the Content-Type value that is not supported.
+ *
+ * @param contentType the type that is not supported
+ */
+ public UnsupportedContentTypeException(String contentType) {
+ super(contentType);
+ }
+
+ /**
+ * Constructor specifying the Content-Type value that is not supported
+ * and an identifier to use with this exception (typically the resource being processed).
+ *
+ * @param contentType the type that is not supported
+ * @param identifier an identifier for this exception
+ */
+ public UnsupportedContentTypeException(String contentType, String identifier) {
+ super(contentType, identifier);
+ }
+}
diff --git a/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/util/ServiceConfigurationUtil.java b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/util/ServiceConfigurationUtil.java
new file mode 100644
index 0000000000..88d960994c
--- /dev/null
+++ b/branches/sca-java-1.0/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/util/ServiceConfigurationUtil.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+public class ServiceConfigurationUtil {
+
+ /**
+ * Read the service name from a configuration file
+ *
+ * @param classLoader
+ * @param name The name of the service class
+ * @return A class name which extends/implements the service class
+ * @throws IOException
+ */
+ public static List<String> getServiceClassNames(ClassLoader classLoader, String name) throws IOException {
+ List<String> classNames = new ArrayList<String>();
+ for (URL url: Collections.list(classLoader.getResources("META-INF/services/" + name))) {
+ InputStream is = url.openStream();
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(is));
+ while (true) {
+ String line = reader.readLine();
+ if (line == null)
+ break;
+ line = line.trim();
+ if (!line.startsWith("#") && !"".equals(line)) {
+ classNames.add(line.trim());
+ }
+ }
+ } finally {
+ if (reader != null)
+ reader.close();
+ if (is != null) {
+ try {
+ is.close();
+ } catch (IOException ioe) {}
+ }
+ }
+ }
+ return classNames;
+ }
+
+ /**
+ * Parse a service declaration in the form class;attr=value,attr=value and
+ * return a map of attributes
+ *
+ * @param declaration
+ * @return a map of attributes
+ */
+ public static Map<String, String> parseServiceDeclaration(String declaration) {
+ Map<String, String> attributes = new HashMap<String, String>();
+ StringTokenizer tokens = new StringTokenizer(declaration);
+ String className = tokens.nextToken(";");
+ if (className != null)
+ attributes.put("class", className);
+ for (; tokens.hasMoreTokens(); ) {
+ String key = tokens.nextToken("=").substring(1);
+ if (key == null)
+ break;
+ String value = tokens.nextToken(",").substring(1);
+ if (value == null)
+ break;
+ attributes.put(key, value);
+ }
+ return attributes;
+ }
+
+}