diff options
author | lresende <lresende@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-11 23:26:33 +0000 |
---|---|---|
committer | lresende <lresende@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-11 23:26:33 +0000 |
commit | a40e527938d76ba71f211da7e327adb50384ba69 (patch) | |
tree | cb8f99f1727122b040a3f0fbb6649292b6a74302 /sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl | |
parent | 968721109881107520d7aefa91d7fcc0519d7739 (diff) |
Moving 1.x tags
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@835157 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl')
8 files changed, 1102 insertions, 0 deletions
diff --git a/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ArtifactTypeDescriberImpl.java b/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ArtifactTypeDescriberImpl.java new file mode 100644 index 0000000000..174a09a0c6 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ArtifactTypeDescriberImpl.java @@ -0,0 +1,106 @@ +/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.service.impl;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.tuscany.sca.contribution.ContentType;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.service.TypeDescriber;
+import org.apache.tuscany.sca.contribution.service.util.FileHelper;
+
+/**
+ * Implementation of the content describer for files
+ *
+ * @version $Rev$ $Date$
+ */
+public class ArtifactTypeDescriberImpl implements TypeDescriber {
+ private final Map<String, String> contentTypeRegistry = new HashMap<String, String>();
+
+ public ArtifactTypeDescriberImpl() {
+ super();
+ init();
+ }
+
+ /**
+ * Initialize contentType registry with know types based on known file extensions
+ */
+ private void init() {
+ contentTypeRegistry.put("COMPOSITE", ContentType.COMPOSITE);
+ contentTypeRegistry.put("SCDL", ContentType.COMPOSITE);
+ contentTypeRegistry.put("WSDL", ContentType.WSDL);
+ contentTypeRegistry.put("JAR", ContentType.JAR);
+ }
+
+ protected String resolveContentyTypeByExtension(URL resourceURL) {
+ String artifactExtension = FileHelper.getExtension(resourceURL.getPath());
+ if (artifactExtension == null) {
+ return null;
+ }
+ return contentTypeRegistry.get(artifactExtension.toUpperCase());
+ }
+
+ /**
+ * Build contentType for a specific resource. We first check if the file is
+ * a supported one (looking into our registry based on resource extension)
+ * If not found, we try to check file contentType Or we return
+ * defaultContentType provided
+ *
+ * @param resourceURL The artifact url
+ * @param defaultContentType The default content type if we can't find the correc one
+ * @return The content type
+ */
+ public String getType(URL resourceURL, String defaultContentType) {
+ URLConnection connection = null;
+ String contentType = defaultContentType;
+
+ if (resourceURL.getProtocol().equals("file") && FileHelper.toFile(resourceURL).isDirectory()) {
+ // Special case : contribution is a folder
+ contentType = ContentType.FOLDER;
+ } else if (resourceURL.toExternalForm().endsWith(Contribution.SCA_CONTRIBUTION_META)
+ || resourceURL.toExternalForm().endsWith(Contribution.SCA_CONTRIBUTION_GENERATED_META)) {
+ // Special case : contribution metadata
+ contentType = ContentType.CONTRIBUTION_METADATA;
+ } else {
+ contentType = resolveContentyTypeByExtension(resourceURL);
+ if (contentType == null) {
+ try {
+ connection = resourceURL.openConnection();
+ contentType = connection.getContentType();
+
+ if (contentType == null || contentType.equals("content/unknown")) {
+ // here we couldn't figure out from our registry or from URL and it's not a special file
+ // return defaultContentType if provided
+ contentType = defaultContentType;
+ }
+ } catch (IOException io) {
+ // could not access artifact, just ignore and we will return
+ // null contentType
+ }
+ }
+ }
+ return contentType == null ? defaultContentType : contentType;
+ }
+
+}
diff --git a/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionMetadataLoaderImpl.java b/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionMetadataLoaderImpl.java new file mode 100644 index 0000000000..a089756308 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionMetadataLoaderImpl.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.tuscany.sca.contribution.service.impl; + +import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import 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.ContributionExport; +import org.apache.tuscany.sca.contribution.ContributionFactory; +import org.apache.tuscany.sca.contribution.ContributionImport; +import org.apache.tuscany.sca.contribution.service.ContributionMetadataLoader; +import org.apache.tuscany.sca.contribution.service.ContributionMetadataLoaderException; + +/** + * Loader that handles contribution metadata files + * + * @version $Rev: 515261 $ $Date: 2007-03-06 11:22:46 -0800 (Tue, 06 Mar 2007) $ + */ +public class ContributionMetadataLoaderImpl implements ContributionMetadataLoader { + private static final String SCA10_NS = "http://www.osoa.org/xmlns/sca/1.0"; + private static final String TARGET_NAMESPACE = "targetNamespace"; + + private static final QName CONTRIBUTION = new QName(SCA10_NS, "contribution"); + private static final QName DEPLOYABLE = new QName(SCA10_NS, "deployable"); + private static final QName IMPORT = new QName(SCA10_NS, "import"); + private static final QName EXPORT = new QName(SCA10_NS, "export"); + + private final AssemblyFactory assemblyFactory; + private final ContributionFactory contributionFactory; + + public ContributionMetadataLoaderImpl(AssemblyFactory assemblyFactory, ContributionFactory contributionFactory) { + super(); + this.assemblyFactory = assemblyFactory; + this.contributionFactory = contributionFactory; + } + + public QName getXMLType() { + return CONTRIBUTION; + } + + public void load(Contribution contribution, XMLStreamReader reader) throws XMLStreamException, ContributionMetadataLoaderException { + String targetNameSpaceURI = null; + + while (true) { + int event = reader.next(); + switch (event) { + case START_ELEMENT: + QName element = reader.getName(); + if (CONTRIBUTION.equals(element)) { + targetNameSpaceURI = reader.getAttributeValue(null, TARGET_NAMESPACE); + } else if (DEPLOYABLE.equals(element)) { + String name = reader.getAttributeValue(null, "composite"); + if (name == null) { + throw new InvalidValueException("Attribute 'composite' is missing"); + } + QName compositeName = null; + + int index = name.indexOf(':'); + if (index != -1) { + String prefix = name.substring(0, index); + String localPart = name.substring(index + 1); + String ns = reader.getNamespaceContext().getNamespaceURI(prefix); + if (ns == null) { + throw new InvalidValueException("Invalid prefix: " + prefix); + } + compositeName = new QName(targetNameSpaceURI, localPart, prefix); + } else { + String prefix = ""; + String localPart = name; + compositeName = new QName(targetNameSpaceURI, localPart, prefix); + } + + Composite composite = assemblyFactory.createComposite(); + composite.setName(compositeName); + composite.setUnresolved(true); + + contribution.getDeployables().add(composite); + } else if (IMPORT.equals(element)) { + String ns = reader.getAttributeValue(null, "namespace"); + if (ns == null) { + throw new InvalidValueException("Attribute 'namespace' is missing"); + } + String location = reader.getAttributeValue(null, "location"); + ContributionImport contributionImport = this.contributionFactory.createContributionImport(); + if (location != null) { + contributionImport.setLocation(location); + } + contributionImport.setNamespace(ns); + contribution.getImports().add(contributionImport); + } else if (EXPORT.equals(element)) { + String ns = reader.getAttributeValue(null, "namespace"); + if (ns == null) { + throw new InvalidValueException("Attribute 'namespace' is missing"); + } + ContributionExport contributionExport = this.contributionFactory.createContributionExport(); + contributionExport.setNamespace(ns); + contribution.getExports().add(contributionExport); + } + break; + case XMLStreamConstants.END_ELEMENT: + if (CONTRIBUTION.equals(reader.getName())) { + return; + } + break; + + } + } + } +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionRepositoryImpl.java b/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionRepositoryImpl.java new file mode 100644 index 0000000000..e2dc89782d --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionRepositoryImpl.java @@ -0,0 +1,266 @@ +/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.service.impl;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.sca.contribution.service.ContributionRepository;
+import org.apache.tuscany.sca.contribution.service.util.FileHelper;
+import org.apache.tuscany.sca.contribution.service.util.IOHelper;
+
+/**
+ * The default implementation of ContributionRepository
+ *
+ * @version $Rev$ $Date$
+ */
+public class ContributionRepositoryImpl implements ContributionRepository {
+ private static final String NS = "http://tuscany.apache.org/xmlns/1.0-SNAPSHOT";
+ private static final String DOMAIN_INDEX_FILENAME = "sca-domain.xml";
+ private final File rootFile;
+ private Map<String, String> contributionMap = new HashMap<String, String>();
+
+ private URI domain;
+ private XMLInputFactory factory;
+
+ /**
+ * Constructor with repository root
+ *
+ * @param repository
+ */
+ public ContributionRepositoryImpl(final String repository) throws IOException {
+ String root = repository;
+ if (repository == null) {
+ root = AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ // Default to <user.home>/.tuscany/domains/local/
+ String userHome = System.getProperty("user.home");
+ String slash = File.separator;
+ return userHome + slash + ".tuscany" + slash + "domains" + slash + "local" + slash;
+ }
+ });
+ }
+ this.rootFile = new File(root);
+ this.domain = rootFile.toURI();
+ FileHelper.forceMkdir(rootFile);
+ if (!rootFile.exists() || !rootFile.isDirectory() || !rootFile.canRead()) {
+ throw new IOException("The root is not a directory: " + repository);
+ }
+ factory = XMLInputFactory.newInstance("javax.xml.stream.XMLInputFactory", getClass().getClassLoader());
+ }
+
+ public URI getDomain() {
+ return domain;
+ }
+
+ /**
+ * Resolve contribution location in the repository -> root repository /
+ * contribution file -> contribution group id / artifact id / version
+ *
+ * @param contribution
+ * @return
+ */
+ private File mapToFile(URL sourceURL) {
+ String fileName = FileHelper.toFile(sourceURL).getName();
+ return new File(rootFile, "contributions" + File.separator + fileName);
+ }
+
+ /**
+ * Write a specific source inputstream to a file on disk
+ *
+ * @param source contents of the file to be written to disk
+ * @param target file to be written
+ * @throws IOException
+ */
+ public static void copy(InputStream source, File target) throws IOException {
+ BufferedOutputStream out = null;
+ BufferedInputStream in = null;
+
+ try {
+ out = new BufferedOutputStream(new FileOutputStream(target));
+ in = new BufferedInputStream(source);
+ IOHelper.copy(in, out);
+ } finally {
+ IOHelper.closeQuietly(out);
+ IOHelper.closeQuietly(in);
+ }
+ }
+
+ public URL store(String contribution, URL sourceURL, InputStream contributionStream) throws IOException {
+ // where the file should be stored in the repository
+ File location = mapToFile(sourceURL);
+ FileHelper.forceMkdir(location.getParentFile());
+
+ copy(contributionStream, location);
+
+ // add contribution to repositoryContent
+ URL contributionURL = location.toURL();
+ URI relative = rootFile.toURI().relativize(location.toURI());
+ contributionMap.put(contribution, relative.toString());
+ saveMap();
+
+ return contributionURL;
+ }
+
+ public URL store(String contribution, URL sourceURL) throws IOException {
+ // where the file should be stored in the repository
+ File location = mapToFile(sourceURL);
+ File source = FileHelper.toFile(sourceURL);
+ if (source == null || source.isFile()) {
+ InputStream is = sourceURL.openStream();
+ try {
+ return store(contribution, sourceURL, is);
+ } finally {
+ IOHelper.closeQuietly(is);
+ }
+ }
+
+ FileHelper.forceMkdir(location);
+ FileHelper.copyDirectory(source, location);
+
+ // add contribution to repositoryContent
+ URI relative = rootFile.toURI().relativize(location.toURI());
+ contributionMap.put(contribution, relative.toString());
+ saveMap();
+
+ return location.toURL();
+ }
+
+ public URL find(String contribution) {
+ if (contribution == null) {
+ return null;
+ }
+ String location = contributionMap.get(contribution);
+ if (location == null) {
+ return null;
+ }
+ try {
+ return new File(rootFile, location).toURL();
+ } catch (MalformedURLException e) {
+ // Should not happen
+ throw new AssertionError(e);
+ }
+ }
+
+ public void remove(String contribution) {
+ URL contributionURL = this.find(contribution);
+ if (contributionURL != null) {
+ // remove
+ try {
+ FileHelper.forceDelete(FileHelper.toFile(contributionURL));
+ this.contributionMap.remove(contribution);
+ saveMap();
+ } catch (IOException ioe) {
+ // handle file could not be removed
+ }
+ }
+ }
+
+ public List<String> list() {
+ return new ArrayList<String>(contributionMap.keySet());
+ }
+
+ public void init() {
+ File domainFile = new File(rootFile, "sca-domain.xml");
+ if (!domainFile.isFile()) {
+ return;
+ }
+ FileInputStream is;
+ try {
+ is = new FileInputStream(domainFile);
+ } catch (FileNotFoundException e) {
+ return;
+ }
+ try {
+ XMLStreamReader reader = factory.createXMLStreamReader(new InputStreamReader(is, "UTF-8"));
+ while (reader.hasNext()) {
+ switch (reader.getEventType()) {
+ case XMLStreamConstants.START_ELEMENT:
+ String name = reader.getName().getLocalPart();
+ if ("domain".equals(name)) {
+ String uri = reader.getAttributeValue(null, "uri");
+ if (uri != null) {
+ domain = URI.create(uri);
+ }
+ }
+ if ("contribution".equals(name)) {
+ String uri = reader.getAttributeValue(null, "uri");
+ String location = reader.getAttributeValue(null, "location");
+ contributionMap.put(uri, location);
+ }
+ break;
+ default:
+ break;
+ }
+ reader.next();
+ }
+ } catch (Exception e) {
+ // Ignore
+ } finally {
+ IOHelper.closeQuietly(is);
+ }
+ }
+
+ private void saveMap() {
+ File domainFile = new File(rootFile, DOMAIN_INDEX_FILENAME);
+ FileOutputStream os = null;
+ try {
+ os = new FileOutputStream(domainFile);
+ PrintWriter writer = new PrintWriter(new OutputStreamWriter(os, "UTF-8"));
+ writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+ writer.println("<domain uri=\"" + getDomain() + "\" xmlns=\"" + NS + "\">");
+ for (Map.Entry<String, String> e : contributionMap.entrySet()) {
+ writer.println(" <contribution uri=\"" + e.getKey() + "\" location=\"" + e.getValue() + "\"/>");
+ }
+ writer.println("</domain>");
+ writer.flush();
+ } catch (IOException e) {
+ throw new IllegalArgumentException(e);
+ } finally {
+ IOHelper.closeQuietly(os);
+ }
+ }
+
+ public void destroy() {
+ }
+
+}
diff --git a/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/ContributionServiceImpl.java b/sca-java-1.x/tags/0.91-incubating/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/tags/0.91-incubating/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); + } + +} diff --git a/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/InvalidContributionMetadataException.java b/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/InvalidContributionMetadataException.java new file mode 100644 index 0000000000..a7e0e2f2f5 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/InvalidContributionMetadataException.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.service.impl;
+
+import org.apache.tuscany.sca.contribution.service.ContributionException;
+
+/**
+ * Exception that indicates that the supplied XML Document invalid.
+ *
+ * @version $Rev: 511466 $ $Date: 2007-02-25 00:45:22 -0800 (Sun, 25 Feb 2007) $
+ */
+public class InvalidContributionMetadataException extends ContributionException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3184477070625689942L;
+
+ protected InvalidContributionMetadataException() {
+ }
+
+ protected InvalidContributionMetadataException(String message) {
+ super(message);
+ }
+
+ protected InvalidContributionMetadataException(String message, String identifier) {
+ super(message, identifier);
+ }
+
+ protected InvalidContributionMetadataException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ protected InvalidContributionMetadataException(String message, String identifier, Throwable cause) {
+ super(message, identifier, cause);
+ }
+
+ protected InvalidContributionMetadataException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/InvalidContributionURIException.java b/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/InvalidContributionURIException.java new file mode 100644 index 0000000000..e3109e795b --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/InvalidContributionURIException.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.service.impl;
+
+import org.apache.tuscany.sca.contribution.service.ContributionException;
+
+/**
+ * Exception that indicates that the supplied contribution URI is invalid or inexistent.
+ *
+ * @version $Rev: 511466 $ $Date: 2007-02-25 00:45:22 -0800 (Sun, 25 Feb 2007) $
+ */
+public class InvalidContributionURIException extends ContributionException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3184477070625689942L;
+
+ protected InvalidContributionURIException() {
+ }
+
+ protected InvalidContributionURIException(String message) {
+ super(message);
+ }
+
+ protected InvalidContributionURIException(String message, String identifier) {
+ super(message, identifier);
+ }
+
+ protected InvalidContributionURIException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ protected InvalidContributionURIException(String message, String identifier, Throwable cause) {
+ super(message, identifier, cause);
+ }
+
+ protected InvalidContributionURIException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/InvalidValueException.java b/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/InvalidValueException.java new file mode 100644 index 0000000000..ce0fb59476 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/InvalidValueException.java @@ -0,0 +1,46 @@ +/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.service.impl;
+
+import org.apache.tuscany.sca.contribution.service.ContributionMetadataLoaderException;
+
+/**
+ * Denotate invalid value found during parsing of the contribution metadata sidefile
+ *
+ * @version $Rev$ $Date$
+ */
+public class InvalidValueException extends ContributionMetadataLoaderException {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -1447696740893397938L;
+
+ public InvalidValueException(String message) {
+ super(message);
+ }
+
+ public InvalidValueException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public InvalidValueException(String message, String identifier, Throwable cause) {
+ super(message, identifier, cause);
+ }
+}
diff --git a/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/PackageTypeDescriberImpl.java b/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/PackageTypeDescriberImpl.java new file mode 100644 index 0000000000..165c9d0616 --- /dev/null +++ b/sca-java-1.x/tags/0.91-incubating/modules/contribution-impl/src/main/java/org/apache/tuscany/sca/contribution/service/impl/PackageTypeDescriberImpl.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.service.impl; + +import java.io.IOException; +import java.net.URL; +import java.net.URLConnection; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tuscany.sca.contribution.ContentType; +import org.apache.tuscany.sca.contribution.service.TypeDescriber; +import org.apache.tuscany.sca.contribution.service.util.FileHelper; + +/** + * Implementation of the content describer for contribution packages + * + * @version $Rev$ $Date$ + */ +public class PackageTypeDescriberImpl implements TypeDescriber { + private final Map<String, String> contentTypeRegistry = new HashMap<String, String>(); + + public PackageTypeDescriberImpl() { + super(); + init(); + } + + /** + * Initialize contentType registry with know types based on known file extensions + */ + private void init() { + contentTypeRegistry.put("JAR", ContentType.JAR); + } + + protected String resolveContentyTypeByExtension(URL resourceURL) { + String artifactExtension = FileHelper.getExtension(resourceURL.getPath()); + if (artifactExtension == null) { + return null; + } + return contentTypeRegistry.get(artifactExtension.toUpperCase()); + } + + /** + * Build contentType for a specific resource. We first check if the file is + * a supported one (looking into our registry based on resource extension) + * If not found, we try to check file contentType Or we return + * defaultContentType provided + * + * @param resourceURL The artifact url + * @param defaultContentType The default content type if we can't find the correc one + * @return The content type + */ + public String getType(URL resourceURL, String defaultContentType) { + URLConnection connection = null; + String contentType = defaultContentType; + + if (resourceURL.getProtocol().equals("file") && FileHelper.toFile(resourceURL).isDirectory()) { + // Special case : contribution is a folder + contentType = ContentType.FOLDER; + } else { + contentType = resolveContentyTypeByExtension(resourceURL); + if (contentType == null) { + try { + connection = resourceURL.openConnection(); + contentType = connection.getContentType(); + + if (contentType == null || contentType.equals("content/unknown")) { + // here we couldn't figure out from our registry or from URL and it's not a special file + // return defaultContentType if provided + contentType = defaultContentType; + } + } catch (IOException io) { + // could not access artifact, just ignore and we will return + // null contentType + } + } + } + return contentType == null ? defaultContentType : contentType; + } + +} |