summaryrefslogtreecommitdiffstats
path: root/sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner
diff options
context:
space:
mode:
Diffstat (limited to 'sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner')
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java55
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java50
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java131
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/DirectoryContributionScanner.java173
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/JarContributionScanner.java143
5 files changed, 552 insertions, 0 deletions
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java b/sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java
new file mode 100644
index 0000000000..91697111af
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.scanner;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.tuscany.sca.contribution.Artifact;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+
+/**
+ * Interface for contribution package scanners
+ *
+ * Contribution scanners understand the format of the contribution and how to get the
+ * artifacts in the contribution.
+ *
+ * @version $Rev$ $Date$
+ * @tuscany.spi.extension.inheritfrom
+ */
+public interface ContributionScanner {
+
+ /**
+ * Returns the type of package supported by this package scanner.
+ *
+ * @return the package type
+ */
+ String getContributionType();
+
+ /**
+ * Returns a list of artifacts in the contribution.
+ *
+ * @param contribution Contribution URL
+ * @return List of artifact populated with URIs and location URL
+ * @throws ContributionReadException
+ * @throws IOException
+ */
+ List<Artifact> scan(Contribution contribution) throws ContributionReadException;
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java b/sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java
new file mode 100644
index 0000000000..1ca9def4ea
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScannerExtensionPoint.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tuscany.sca.contribution.scanner;
+
+/**
+ * An extension point for contribution scanners
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ContributionScannerExtensionPoint {
+
+ /**
+ * Add a ContributionScanner using the contribution type as the key.
+ *
+ * @param scanner The contribution scanner
+ */
+ void addContributionScanner(ContributionScanner scanner);
+
+ /**
+ * Remove a ContributionScanner.
+ *
+ * @param scanner The contribution scanner
+ */
+ void removeContributionScanner(ContributionScanner scanner);
+
+ /**
+ * Returns the ContributionScanner for the given contribution type.
+ *
+ * @param contributionType The contribution type
+ * @return The contribution scanner
+ */
+ ContributionScanner getContributionScanner(String contributionType);
+
+} \ No newline at end of file
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java b/sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java
new file mode 100644
index 0000000000..c5aed5ccd3
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.scanner;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tuscany.sca.contribution.Artifact;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.ContributionFactory;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.extensibility.ServiceDeclaration;
+
+/**
+ * Default implementation of a contribution scanner extension point.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DefaultContributionScannerExtensionPoint implements ContributionScannerExtensionPoint {
+
+ private Map<String, ContributionScanner> scanners = new HashMap<String, ContributionScanner>();
+ private boolean loaded;
+ private ExtensionPointRegistry registry;
+
+ public DefaultContributionScannerExtensionPoint(ExtensionPointRegistry registry) {
+ this.registry = registry;
+ }
+
+ public void addContributionScanner(ContributionScanner scanner) {
+ scanners.put(scanner.getContributionType(), scanner);
+ }
+
+ public void removeContributionScanner(ContributionScanner scanner) {
+ scanners.remove(scanner.getContributionType());
+ }
+
+ public ContributionScanner getContributionScanner(String contentType) {
+ loadScanners();
+ return scanners.get(contentType);
+ }
+
+ private synchronized void loadScanners() {
+ if (loaded)
+ return;
+
+ // Get the scanner service declarations
+ Collection<ServiceDeclaration> scannerDeclarations;
+ try {
+ scannerDeclarations = registry.getServiceDiscovery().getServiceDeclarations(ContributionScanner.class.getName());
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+
+ for (ServiceDeclaration scannerDeclaration: scannerDeclarations) {
+ Map<String, String> attributes = scannerDeclaration.getAttributes();
+
+ // Load a URL artifact scanner
+ String contributionType = attributes.get("type");
+
+ // Create a scanner wrapper and register it
+ ContributionScanner scanner = new LazyContributionScanner(registry, contributionType, scannerDeclaration);
+ addContributionScanner(scanner);
+ }
+
+ loaded = true;
+ }
+
+ /**
+ * A facade for contribution scanners.
+ */
+ private static class LazyContributionScanner implements ContributionScanner {
+ private ExtensionPointRegistry registry;
+ private ServiceDeclaration scannerDeclaration;
+ private String contributionType;
+ private ContributionScanner scanner;
+ private ContributionFactory contributionFactory;
+
+ private LazyContributionScanner(ExtensionPointRegistry registry, String contributionType, ServiceDeclaration scannerDeclaration) {
+ this.registry = registry;
+ this.scannerDeclaration = scannerDeclaration;
+ this.contributionType = contributionType;
+
+ FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ this.contributionFactory = factories.getFactory(ContributionFactory.class);
+ }
+
+ public List<Artifact> scan(Contribution contributionSourceURL) throws ContributionReadException {
+ return getScanner().scan(contributionSourceURL);
+ }
+
+ public String getContributionType() {
+ return contributionType;
+ }
+
+ private ContributionScanner getScanner() {
+ if (scanner == null) {
+ try {
+ Class<ContributionScanner> scannerClass = (Class<ContributionScanner>)scannerDeclaration.loadClass();
+ Constructor<ContributionScanner> constructor = scannerClass.getConstructor(ContributionFactory.class);
+ scanner = constructor.newInstance(contributionFactory);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ return scanner;
+ }
+ }
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/DirectoryContributionScanner.java b/sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/DirectoryContributionScanner.java
new file mode 100644
index 0000000000..4a064c8fa9
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/DirectoryContributionScanner.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.scanner.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.AccessControlException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.tuscany.sca.contribution.Artifact;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.ContributionFactory;
+import org.apache.tuscany.sca.contribution.PackageType;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.scanner.ContributionScanner;
+
+/**
+ * Folder contribution processor.
+ *
+ * @version $Rev$ $Date$
+ */
+public class DirectoryContributionScanner implements ContributionScanner {
+ private static final Logger logger = Logger.getLogger(DirectoryContributionScanner.class.getName());
+
+ private ContributionFactory contributionFactory;
+
+ public DirectoryContributionScanner(ContributionFactory contributionFactory) {
+ this.contributionFactory = contributionFactory;
+ }
+
+ public String getContributionType() {
+ return PackageType.FOLDER;
+ }
+
+ public List<Artifact> scan(Contribution contribution) throws ContributionReadException {
+ File directory = directory(contribution);
+ List<Artifact> artifacts = new ArrayList<Artifact>();
+ List<String> artifactURIs = scanContributionArtifacts(contribution);
+ for(String uri : artifactURIs) {
+ try {
+ File file = new File(directory, uri);
+
+ Artifact artifact = contributionFactory.createArtifact();
+ artifact.setURI(uri);
+ artifact.setLocation(file.toURI().toURL().toString());
+
+ artifacts.add(artifact);
+ } catch (MalformedURLException e) {
+ throw new ContributionReadException(e);
+ }
+ }
+
+ contribution.getTypes().add(getContributionType());
+ return artifacts;
+ }
+
+
+ /**
+ * Scan the contribution to retrieve all artifact uris
+ *
+ * @param contribution
+ * @return
+ * @throws ContributionReadException
+ */
+ private List<String> scanContributionArtifacts(Contribution contribution) throws ContributionReadException {
+ File directory = directory(contribution);
+ List<String> artifacts = new ArrayList<String>();
+ // [rfeng] There are cases that the folder contains symbolic links that point to the same physical directory
+ Set<File> visited = new HashSet<File>();
+ try {
+ traverse(artifacts, directory, directory, visited);
+ } catch (IOException e) {
+ throw new ContributionReadException(e);
+ }
+
+ return artifacts;
+ }
+
+ /**
+ * Recursively traverse a root directory
+ *
+ * @param fileList
+ * @param file
+ * @param root
+ * @param visited The visited directories
+ * @throws IOException
+ */
+ private static void traverse(List<String> fileList, File file, File root, Set<File> visited) throws IOException {
+
+ //TUSCANY-3667 - Google add some private directories when you deploy your application
+ //to GAE and trying to execute file IO operations on it's contents fails with AccessControlException
+ try {
+ if (file.isFile()) {
+ fileList.add(root.toURI().relativize(file.toURI()).toString());
+ } else if (file.isDirectory()) {
+ File dir = file.getCanonicalFile();
+ if (!visited.contains(dir)) {
+ // [rfeng] Add the canonical file into the visited set to avoid duplicate navigation of directories
+ // following the symbolic links
+ visited.add(dir);
+ String uri = root.toURI().relativize(file.toURI()).toString();
+ if (uri.endsWith("/")) {
+ uri = uri.substring(0, uri.length() - 1);
+ }
+ fileList.add(uri);
+
+ File[] files = file.listFiles();
+ for (File f : files) {
+ if (!f.getName().startsWith(".")) {
+ traverse(fileList, f, root, visited);
+ }
+ }
+ }
+ }
+ } catch (AccessControlException e) {
+ //TUSCANY-3667 - Log the AccessControlException error and continue without processing the file/directory
+ logger.log(Level.WARNING, "Error traversing file:" + file.getPath());
+ }
+
+ }
+
+ /**
+ * Get the contribution location as a file
+ *
+ * @param contribution
+ * @return
+ * @throws ContributionReadException
+ */
+ private File directory(Contribution contribution) throws ContributionReadException {
+ File file;
+ URI uri = null;
+ try {
+ uri = new URI(contribution.getLocation());
+ file = new File(uri);
+ } catch (URISyntaxException e) {
+ throw new ContributionReadException(e);
+ } catch(IllegalArgumentException e) {
+ // Hack for file:./a.txt or file:../a/c.wsdl
+ return new File(uri.getPath());
+ }
+ if (!file.exists() || !file.isDirectory()) {
+ throw new ContributionReadException(contribution.getLocation());
+ }
+ return file;
+ }
+
+
+}
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/JarContributionScanner.java b/sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/JarContributionScanner.java
new file mode 100644
index 0000000000..25be92c310
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/JarContributionScanner.java
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.tuscany.sca.contribution.scanner.impl;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+
+import org.apache.tuscany.sca.common.java.io.IOHelper;
+import org.apache.tuscany.sca.contribution.Artifact;
+import org.apache.tuscany.sca.contribution.Contribution;
+import org.apache.tuscany.sca.contribution.ContributionFactory;
+import org.apache.tuscany.sca.contribution.PackageType;
+import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
+import org.apache.tuscany.sca.contribution.scanner.ContributionScanner;
+
+/**
+ * JAR Contribution processor.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JarContributionScanner implements ContributionScanner {
+ private ContributionFactory contributionFactory;
+
+ public JarContributionScanner(ContributionFactory contributionFactory) {
+ this.contributionFactory = contributionFactory;
+ }
+
+ public String getContributionType() {
+ return PackageType.JAR;
+ }
+
+ public List<Artifact> scan(Contribution contribution) throws ContributionReadException {
+
+ // Assume the URL references a JAR file
+ try {
+ URL url = new URL(contribution.getLocation());
+ JarInputStream jar = new JarInputStream(IOHelper.openStream(url));
+ try {
+ Set<String> names = new HashSet<String>();
+ while (true) {
+ JarEntry entry = jar.getNextJarEntry();
+ if (entry == null) {
+ // EOF
+ break;
+ }
+
+ String name = entry.getName();
+ if (name.length() != 0 && !name.startsWith(".")) {
+
+ // Trim trailing /
+ if (name.endsWith("/")) {
+ name = name.substring(0, name.length() - 1);
+ }
+
+ // Add the entry name
+ if (!names.contains(name)) {
+ names.add(name);
+
+ // Add parent folder names to the list too
+ for (;;) {
+ int s = name.lastIndexOf('/');
+ if (s == -1) {
+ name = "";
+ } else {
+ name = name.substring(0, s);
+ }
+ if (name.length() != 0 && !names.contains(name)) {
+ names.add(name);
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Return list of artifacts
+ List<Artifact> artifacts = new ArrayList<Artifact>();
+ for(String uri : names) {
+ Artifact artifact = contributionFactory.createArtifact();
+ artifact.setURI(uri);
+ artifact.setLocation(getArtifactURL(contribution, uri).toString());
+
+ artifacts.add(artifact);
+ }
+
+ contribution.getTypes().add(getContributionType());
+ return artifacts;
+
+ } finally {
+ jar.close();
+ }
+ } catch (IOException e) {
+ throw new ContributionReadException(e);
+ }
+ }
+
+ /**
+ * Produces a location URL for a given artifact in the contribution
+ *
+ * @param contribution
+ * @param artifact
+ * @return
+ * @throws ContributionReadException
+ */
+ private static URL getArtifactURL(Contribution contribution, String artifact) throws ContributionReadException {
+ try {
+ URL url;
+ if (contribution.toString().startsWith("jar:")) {
+ url = new URL(new URL(contribution.getLocation()), artifact.toString());
+ } else {
+ url = new URL("jar:" + contribution.getLocation() + "!/" + artifact);
+ }
+ return url;
+ } catch (MalformedURLException e) {
+ throw new ContributionReadException(e);
+ }
+ }
+}