summaryrefslogtreecommitdiffstats
path: root/sca-java-1.x/branches/sca-java-0.91/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionServiceImpl.java
diff options
context:
space:
mode:
Diffstat (limited to 'sca-java-1.x/branches/sca-java-0.91/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionServiceImpl.java')
-rw-r--r--sca-java-1.x/branches/sca-java-0.91/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionServiceImpl.java340
1 files changed, 340 insertions, 0 deletions
diff --git a/sca-java-1.x/branches/sca-java-0.91/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionServiceImpl.java b/sca-java-1.x/branches/sca-java-0.91/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionServiceImpl.java
new file mode 100644
index 0000000000..73bf678e04
--- /dev/null
+++ b/sca-java-1.x/branches/sca-java-0.91/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionServiceImpl.java
@@ -0,0 +1,340 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, 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.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.sca.assembly.AssemblyFactory;
+import org.apache.tuscany.sca.assembly.Composite;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.ContributionFactory;
+import org.apache.tuscany.sca.contribution.DeployedArtifact;
+import org.apache.tuscany.sca.contribution.processor.PackageProcessor;
+import org.apache.tuscany.sca.contribution.processor.URLArtifactProcessor;
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.contribution.service.ContributionException;
+import org.apache.tuscany.sca.contribution.service.ContributionMetadataLoaderException;
+import org.apache.tuscany.sca.contribution.service.ContributionRepository;
+import org.apache.tuscany.sca.contribution.service.ContributionService;
+import org.apache.tuscany.sca.contribution.service.util.IOHelper;
+
+/**
+ * Service interface that manages artifacts contributed to a Tuscany runtime.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ContributionServiceImpl implements ContributionService {
+
+ /**
+ * Repository where contributions are stored. Usually set by injection.
+ */
+ private ContributionRepository contributionRepository;
+
+ /**
+ * Registry of available package processors.
+ */
+ private PackageProcessor packageProcessor;
+
+ /**
+ * Registry of available artifact processors
+ */
+
+ private URLArtifactProcessor artifactProcessor;
+
+ /**
+ * xml factory used to create reader instance to load contribution metadata
+ */
+ private XMLInputFactory xmlFactory;
+
+ /**
+ * contribution metadata loader
+ */
+ private ContributionMetadataLoaderImpl contributionLoader;
+
+ /**
+ * Contribution registry This is a registry of processed Contributions indexed by URI
+ */
+ private Map<String, Contribution> contributionRegistry = new ConcurrentHashMap<String, Contribution>();
+
+ /**
+ * Contribution model facotry
+ */
+ private ContributionFactory contributionFactory;
+
+
+ public ContributionServiceImpl(ContributionRepository repository,
+ PackageProcessor packageProcessor,
+ URLArtifactProcessor artifactProcessor,
+ AssemblyFactory assemblyFactory,
+ ContributionFactory contributionFactory,
+ XMLInputFactory xmlFactory) {
+ super();
+ this.contributionRepository = repository;
+ this.packageProcessor = packageProcessor;
+ this.artifactProcessor = artifactProcessor;
+ this.xmlFactory = xmlFactory;
+
+ this.contributionFactory = contributionFactory;
+ this.contributionLoader = new ContributionMetadataLoaderImpl(assemblyFactory, contributionFactory);
+ }
+
+ public Contribution contribute(String contributionURI, URL sourceURL, ModelResolver modelResolver, boolean storeInRepository) throws ContributionException,
+ IOException {
+ if (contributionURI == null) {
+ throw new IllegalArgumentException("URI for the contribution is null");
+ }
+ if (sourceURL == null) {
+ throw new IllegalArgumentException("Source URL for the contribution is null");
+ }
+
+ return addContribution(contributionURI, sourceURL, null, modelResolver, storeInRepository);
+ }
+
+ public Contribution contribute(String contributionURI, URL sourceURL, InputStream input, ModelResolver modelResolver)
+ throws ContributionException, IOException {
+
+ return addContribution(contributionURI, sourceURL, input, modelResolver, true);
+ }
+
+ private Contribution initializeContributionMetadata(URL sourceURL, ModelResolver modelResolver) throws ContributionException {
+ Contribution contributionMetadata = null;
+ URL contributionMetadataURL;
+ URL generatedContributionMetadataURL;
+ InputStream metadataStream = null;
+
+ URL[] clUrls = {sourceURL};
+ URLClassLoader cl = new URLClassLoader(clUrls, null);
+
+ contributionMetadataURL = cl.getResource(Contribution.SCA_CONTRIBUTION_META);
+ generatedContributionMetadataURL = cl.getResource(Contribution.SCA_CONTRIBUTION_GENERATED_META);
+
+ try {
+ contributionMetadata = this.contributionFactory.createContribution();
+ contributionMetadata.setModelResolver(modelResolver);
+ if (contributionMetadataURL != null || generatedContributionMetadataURL != null) {
+ URL metadataURL = contributionMetadataURL != null ? contributionMetadataURL
+ : generatedContributionMetadataURL;
+
+ try {
+ metadataStream = metadataURL.openStream();
+ XMLStreamReader xmlReader = this.xmlFactory.createXMLStreamReader(metadataStream);
+ this.contributionLoader.load(contributionMetadata, xmlReader);
+
+ } catch (IOException ioe) {
+ throw new InvalidContributionMetadataException(ioe.getMessage(), metadataURL.toExternalForm(), ioe);
+ } catch (XMLStreamException xmle) {
+ throw new InvalidContributionMetadataException(xmle.getMessage(), metadataURL.toExternalForm(),
+ xmle);
+ } catch (ContributionMetadataLoaderException le) {
+ throw new InvalidContributionMetadataException(le.getMessage(), metadataURL.toExternalForm(), le);
+ }
+ }
+ } finally {
+ IOHelper.closeQuietly(metadataStream);
+ metadataStream = null;
+ }
+
+ if (contributionMetadata == null) {
+ contributionMetadata = this.contributionFactory.createContribution();
+ }
+
+ return contributionMetadata;
+
+ }
+
+ public Contribution getContribution(String id) {
+ return this.contributionRegistry.get(id);
+ }
+
+ public void remove(String contribution) throws ContributionException {
+ this.contributionRegistry.remove(contribution);
+ }
+
+ public void addDeploymentComposite(Contribution contribution, Composite composite) throws ContributionException {
+ DeployedArtifact artifact = this.contributionFactory.createDeployedArtifact();
+ artifact.setURI(composite.getURI());
+ artifact.setModel(composite);
+
+ contribution.getArtifacts().add(artifact);
+
+ contribution.getDeployables().add(composite);
+ }
+
+ /**
+ * Utility/Helper methods for contribution service
+ */
+
+ /**
+ * Note:
+ *
+ * @param contributionURI ContributionID
+ * @param sourceURL contribution location
+ * @param contributionStream contribution content
+ * @param storeInRepository flag if we store the contribution into the
+ * repository or not
+ * @return the contribution model representing the contribution
+ * @throws IOException
+ * @throws DeploymentException
+ */
+ private Contribution addContribution(String contributionURI,
+ URL sourceURL,
+ InputStream contributionStream,
+ ModelResolver modelResolver,
+ boolean storeInRepository) throws IOException, ContributionException {
+
+ if (contributionStream == null && sourceURL == null) {
+ throw new IllegalArgumentException("The content of the contribution is null");
+ }
+
+ // store the contribution in the contribution repository
+ URL locationURL = sourceURL;
+ if (contributionRepository != null && storeInRepository) {
+ if (contributionStream == null) {
+ locationURL = contributionRepository.store(contributionURI, sourceURL);
+ } else {
+ locationURL = contributionRepository.store(contributionURI, sourceURL, contributionStream);
+ }
+ }
+
+ Contribution contribution = initializeContributionMetadata(locationURL, modelResolver);
+ contribution.setURI(contributionURI.toString());
+ contribution.setLocation(locationURL.toString());
+
+ List<URI> contributionArtifacts = null;
+
+ //NOTE: if a contribution is stored on the repository
+ //the stream would be consumed at this point
+ if (storeInRepository || contributionStream == null) {
+ contributionStream = sourceURL.openStream();
+ try {
+ // process the contribution
+ contributionArtifacts = this.packageProcessor.getArtifacts(locationURL, contributionStream);
+ } finally {
+ IOHelper.closeQuietly(contributionStream);
+ contributionStream = null;
+ }
+ } else {
+ // process the contribution
+ contributionArtifacts = this.packageProcessor.getArtifacts(locationURL, contributionStream);
+ }
+
+ // Read all artifacts in the contribution
+ processReadPhase(contribution, contributionArtifacts);
+
+ // Resolve them
+ processResolvePhase(contribution);
+
+ // Add all composites under META-INF/sca-deployables to the
+ // list of deployables
+ String prefix = Contribution.SCA_CONTRIBUTION_DEPLOYABLES;
+ for (DeployedArtifact artifact : contribution.getArtifacts()) {
+ if (artifact.getModel() instanceof Composite) {
+ if (artifact.getURI().startsWith(prefix)) {
+ Composite composite = (Composite)artifact.getModel();
+ if (!contribution.getDeployables().contains(composite)) {
+ contribution.getDeployables().add(composite);
+ }
+ }
+ }
+ }
+
+ // store the contribution on the registry
+ this.contributionRegistry.put(contribution.getURI(), contribution);
+
+ return contribution;
+ }
+
+ /**
+ * This utility method process each artifact and delegates to proper
+ * artifactProcessor to read the model and generate the in-memory representation
+ *
+ * @param contribution
+ * @param artifacts
+ * @throws ContributionException
+ * @throws MalformedURLException
+ */
+ private void processReadPhase(Contribution contribution, List<URI> artifacts) throws ContributionException,
+ MalformedURLException {
+
+ ModelResolver modelResolver = contribution.getModelResolver();
+ URL contributionURL = new URL(contribution.getLocation());
+ for (URI a : artifacts) {
+ URL artifactURL = packageProcessor.getArtifactURL(new URL(contribution.getLocation()), a);
+
+ // Add the deployed artifact model to the resolver
+ DeployedArtifact artifact = this.contributionFactory.createDeployedArtifact();
+ artifact.setURI(a.toString());
+ artifact.setLocation(artifactURL.toString());
+ contribution.getArtifacts().add(artifact);
+ modelResolver.addModel(artifact);
+
+ // Let the artifact processor read the artifact into a model
+ Object model = this.artifactProcessor.read(contributionURL, a, artifactURL);
+ if (model != null) {
+ artifact.setModel(model);
+
+ // Add the loaded model to the model resolver
+ modelResolver.addModel(model);
+ }
+
+ }
+ }
+
+ /**
+ * This utility method process each artifact and delegates to proper
+ * artifactProcessor to resolve the model references
+ *
+ * @param contribution
+ * @throws ContributionException
+ */
+ @SuppressWarnings("unchecked")
+ private void processResolvePhase(Contribution contribution) throws ContributionException {
+ // for each artifact that was processed on the contribution
+ for (DeployedArtifact artifact : contribution.getArtifacts()) {
+ // resolve the model object
+ if (artifact.getModel() != null) {
+ this.artifactProcessor.resolve(artifact.getModel(), contribution.getModelResolver());
+ }
+ }
+
+ //resolve deployables from contribution metadata
+ List<Composite> resolvedDeployables = new ArrayList<Composite>();
+ for (Composite deployableComposite : contribution.getDeployables()) {
+ Composite resolvedDeployable = contribution.getModelResolver().resolveModel(Composite.class, deployableComposite);
+ resolvedDeployables.add(resolvedDeployable);
+ }
+
+ contribution.getDeployables().clear();
+ contribution.getDeployables().addAll(resolvedDeployables);
+ }
+
+}