You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by lr...@apache.org on 2009/12/18 00:28:49 UTC

svn commit: r891986 - in /tuscany/sca-java-2.x/trunk/modules: contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/ contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/ contribution/src/main/java/org/a...

Author: lresende
Date: Thu Dec 17 23:28:45 2009
New Revision: 891986

URL: http://svn.apache.org/viewvc?rev=891986&view=rev
Log:
TUSCANY-3395 - Tyding up the ContributionScanner API to scan the contribution and produce a list of Artifacts with proper URI and Location URL instead of doing this in two steps

Modified:
    tuscany/sca-java-2.x/trunk/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleContributionScanner.java
    tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/ContributionContentProcessor.java
    tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java
    tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java
    tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/DirectoryContributionScanner.java
    tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/JarContributionScanner.java

Modified: tuscany/sca-java-2.x/trunk/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleContributionScanner.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleContributionScanner.java?rev=891986&r1=891985&r2=891986&view=diff
==============================================================================
--- tuscany/sca-java-2.x/trunk/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleContributionScanner.java (original)
+++ tuscany/sca-java-2.x/trunk/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleContributionScanner.java Thu Dec 17 23:28:45 2009
@@ -31,7 +31,9 @@
 import java.util.jar.JarEntry;
 import java.util.jar.JarInputStream;
 
+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.ContributionException;
 import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
@@ -45,29 +47,94 @@
  * @version $Rev$ $Date$
  */
 public class OSGiBundleContributionScanner implements ContributionScanner {
+    private ContributionFactory contributionFactory;
 
-    public OSGiBundleContributionScanner() {
+    public OSGiBundleContributionScanner(ContributionFactory contributionFactory) {
+        this.contributionFactory = contributionFactory;
     }
 
     public String getContributionType() {
         return PackageType.BUNDLE;
     }
 
-    public URL getArtifactURL(Contribution contribution, String artifact) throws ContributionReadException {
-        Bundle bundle = null;
+
+
+    public List<Artifact> scan(Contribution contribution) throws ContributionReadException {
+        Bundle bundle = OSGiBundleActivator.findBundle(contribution.getLocation());
+
+        if (bundle == null) {
+            throw new IllegalArgumentException("Could not find OSGi bundle " + contribution.getLocation());
+        }
+
+        List<Artifact> artifacts = new ArrayList<Artifact>();
+        Set<String> bundleClassPath = new HashSet<String>();
+        String cp = (String)bundle.getHeaders().get(Constants.BUNDLE_CLASSPATH);
+        if (cp != null) {
+            String[] paths = cp.split(",");
+            for (String path : paths) {
+                bundleClassPath.add(path.trim());
+            }
+        }
+
         try {
-            bundle = OSGiBundleActivator.findBundle(contribution.getLocation());
-            if (bundle != null) {
-                URL url = bundle.getResource(artifact);
-                return url;
+            // Test if the bundle is an Eclipse project
+            boolean devMode = (bundle.getEntry("/.project") != null);
+            // FIXME: The entries can come from fragments. Do we need to have a way to differentiate the entries?
+            Enumeration<?> entries = bundle.findEntries("/", "*", true);
+            while (entries.hasMoreElements()) {
+                URL entry = (URL)entries.nextElement();
+                String entryName = entry.getPath();
+                if (devMode && entryName.contains("/.svn/")
+                    || entryName.startsWith("/.")
+                    || entryName.startsWith("/target/")
+                    || entryName.startsWith("/src/")) {
+                    // Ignore .svn files
+                    // Ignore .classpath, .project, src, and target
+                    continue;
+                }
+                if (entryName.startsWith("/")) {
+                    entryName = entryName.substring(1);
+                }
+                
+                //Add artifact to list
+                Artifact artifact = contributionFactory.createArtifact();
+                artifact.setURI(entryName);
+                artifact.setLocation(getArtifactURL(contribution, entryName).toString());
+                
+                artifacts.add(artifact);
+
+                //if Artifact is a JAR, add jar artifacts as well
+                if (entryName.endsWith(".jar") && bundleClassPath.contains(entryName)) {
+                    List<String> jarArtifactURIs = getJarArtifacts(entry, entry.openStream());
+                    for( String uri : jarArtifactURIs) {
+                        Artifact jarArtifact = contributionFactory.createArtifact();
+                        jarArtifact.setURI(uri);
+                        jarArtifact.setLocation(getArtifactURL(contribution, uri).toString());
+                        
+                        artifacts.add(jarArtifact);
+                        
+                    }
+                }
+
             }
         } catch (Exception e) {
+            throw new RuntimeException(e);
         }
-        return null;
+        contribution.getExtensions().add(bundle);
+        contribution.getTypes().add(getContributionType());
+        contribution.setClassLoader(new BundleClassLoader(bundle));
+        return artifacts;
     }
 
-    public List<String> getJarArtifacts(URL packageSourceURL, InputStream inputStream) throws ContributionException,
-        IOException {
+    /**
+     * Retrieve a list of Artifact URIs for a given JAR
+     * @param packageSourceURL
+     * @param inputStream
+     * @return
+     * @throws ContributionException
+     * @throws IOException
+     */
+    private List<String> getJarArtifacts(URL packageSourceURL, InputStream inputStream) throws ContributionException, IOException {
         if (packageSourceURL == null) {
             throw new IllegalArgumentException("Invalid null package source URL.");
         }
@@ -103,7 +170,7 @@
                     }
                 }
             }
-
+            
             // Return list of URIs
             List<String> artifacts = new ArrayList<String>();
             for (String name : names) {
@@ -115,59 +182,30 @@
             jar.close();
         }
     }
+    
 
-    public List<String> scan(Contribution contribution) throws ContributionReadException {
-        Bundle bundle = OSGiBundleActivator.findBundle(contribution.getLocation());
-
-        if (bundle == null) {
-            throw new IllegalArgumentException("Could not find OSGi bundle " + contribution.getLocation());
-        }
-
-        List<String> artifacts = new ArrayList<String>();
-        Set<String> bundleClassPath = new HashSet<String>();
-        String cp = (String)bundle.getHeaders().get(Constants.BUNDLE_CLASSPATH);
-        if (cp != null) {
-            String[] paths = cp.split(",");
-            for (String path : paths) {
-                bundleClassPath.add(path.trim());
-            }
-        }
-
+    /**
+     * Given an artifact URI, return it's location URL
+     * 
+     * @param contribution
+     * @param artifact
+     * @return
+     * @throws ContributionReadException
+     */
+    private URL getArtifactURL(Contribution contribution, String artifact) throws ContributionReadException {
+        Bundle bundle = null;
         try {
-            // Test if the bundle is an Eclipse project
-            boolean devMode = (bundle.getEntry("/.project") != null);
-            // FIXME: The entries can come from fragments. Do we need to have a way to differentiate the entries?
-            Enumeration<?> entries = bundle.findEntries("/", "*", true);
-            while (entries.hasMoreElements()) {
-                URL entry = (URL)entries.nextElement();
-                String entryName = entry.getPath();
-                if (devMode && entryName.contains("/.svn/")
-                    || entryName.startsWith("/.")
-                    || entryName.startsWith("/target/")
-                    || entryName.startsWith("/src/")) {
-                    // Ignore .svn files
-                    // Ignore .classpath, .project, src, and target
-                    continue;
-                }
-                if (entryName.startsWith("/")) {
-                    entryName = entryName.substring(1);
-                }
-                artifacts.add(entryName);
-
-                if (entryName.endsWith(".jar") && bundleClassPath.contains(entryName)) {
-                    artifacts.addAll(getJarArtifacts(entry, entry.openStream()));
-                }
-
+            bundle = OSGiBundleActivator.findBundle(contribution.getLocation());
+            if (bundle != null) {
+                URL url = bundle.getResource(artifact);
+                return url;
             }
         } catch (Exception e) {
-            throw new RuntimeException(e);
         }
-        contribution.getExtensions().add(bundle);
-        contribution.getTypes().add(getContributionType());
-        contribution.setClassLoader(new BundleClassLoader(bundle));
-        return artifacts;
+        return null;
     }
 
+
     private static class BundleClassLoader extends ClassLoader {
         private Bundle bundle;
         public BundleClassLoader(Bundle bundle) {
@@ -185,6 +223,7 @@
             return bundle.getResource(name);
         }
 
+        @SuppressWarnings("unchecked")
         @Override
         protected Enumeration<URL> findResources(String name) throws IOException {
             Enumeration<URL> urls = bundle.getResources(name);

Modified: tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/ContributionContentProcessor.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/ContributionContentProcessor.java?rev=891986&r1=891985&r2=891986&view=diff
==============================================================================
--- tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/ContributionContentProcessor.java (original)
+++ tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/impl/ContributionContentProcessor.java Thu Dec 17 23:28:45 2009
@@ -19,6 +19,7 @@
 package org.apache.tuscany.sca.contribution.processor.impl;
 
 import java.io.File;
+import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
@@ -123,32 +124,32 @@
             if (scanner == null) {
                 File file = toFile(contributionURL);
                 if (file != null && file.isDirectory()) {
-                    scanner = new DirectoryContributionScanner();
+                    scanner = new DirectoryContributionScanner(contributionFactory);
                 } else {
-                    scanner = new JarContributionScanner();
+                    scanner = new JarContributionScanner(contributionFactory);
                 }
             }
     
             // Scan the contribution and list the artifacts contained in it
-            List<Artifact> artifacts = contribution.getArtifacts();
             boolean contributionMetadata = false;
-            List<String> artifactURIs = scanner.scan(contribution);
-            for (String artifactURI: artifactURIs) {
-                URL artifactURL = scanner.getArtifactURL(contribution, artifactURI);
-    
+            List<Artifact> artifacts = scanner.scan(contribution);
+            for (Artifact artifact : artifacts) {
                 // Add the deployed artifact model to the contribution
-                Artifact artifact = this.contributionFactory.createArtifact();
-                artifact.setURI(artifactURI);
-                artifact.setLocation(artifactURL.toString());
-                artifacts.add(artifact);
                 modelResolver.addModel(artifact, context);
                 
-                monitor.pushContext("Artifact: " + artifactURI);
+                monitor.pushContext("Artifact: " + artifact.getURI());
     
                 old = context.setContribution(contribution);
                 try {
                     // Read each artifact
-                    Object model = artifactProcessor.read(contributionURL, URI.create(artifactURI), artifactURL, context);
+                    URL artifactLocationURL = null;
+                    try {
+                        artifactLocationURL = new URL(artifact.getLocation());
+                    } catch(MalformedURLException e) {
+                        //ignore
+                    }
+                    
+                    Object model = artifactProcessor.read(contributionURL, URI.create(artifact.getURI()), artifactLocationURL, context);
                     if (model != null) {
                         artifact.setModel(model);
         
@@ -171,6 +172,9 @@
                     context.setContribution(old);
                 }                    
             }
+            
+            List<Artifact> contributionArtifacts = contribution.getArtifacts();
+            contributionArtifacts.addAll(artifacts);
     
             // If no sca-contribution.xml file was provided then just consider
             // all composites in the contribution as deployables

Modified: tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java?rev=891986&r1=891985&r2=891986&view=diff
==============================================================================
--- tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java (original)
+++ tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/ContributionScanner.java Thu Dec 17 23:28:45 2009
@@ -19,9 +19,9 @@
 package org.apache.tuscany.sca.contribution.scanner;
 
 import java.io.IOException;
-import java.net.URL;
 import java.util.List;
 
+import org.apache.tuscany.sca.contribution.Artifact;
 import org.apache.tuscany.sca.contribution.Contribution;
 import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
 
@@ -46,22 +46,9 @@
      * Returns a list of artifacts in the contribution.
      *
      * @param contribution Contribution URL
-     * @return List of artifact URIs
+     * @return List of artifact populated with URIs and location URL
      * @throws ContributionReadException
      * @throws IOException
      */
-    List<String> scan(Contribution contribution) throws ContributionReadException;
-
-    /**
-     * Return the URL for an artifact in the contribution.
-     *
-     * This is needed for archives such as jar files that have specific URL schemes
-     * for the artifacts they contain.
-     *
-     * @param contribution Contribution URL
-     * @param artifact The relative URI for the artifact
-     * @throws ContributionReadException
-     * @return The artifact URL
-     */
-    URL getArtifactURL(Contribution contribution, String artifact) throws ContributionReadException;
+    List<Artifact> scan(Contribution contribution) throws ContributionReadException;
 }

Modified: tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java?rev=891986&r1=891985&r2=891986&view=diff
==============================================================================
--- tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java (original)
+++ tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/DefaultContributionScannerExtensionPoint.java Thu Dec 17 23:28:45 2009
@@ -21,15 +21,17 @@
 
 import java.io.IOException;
 import java.lang.reflect.Constructor;
-import java.net.URL;
 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;
 
 /**
@@ -79,7 +81,7 @@
             String contributionType = attributes.get("type");
 
             // Create a scanner wrapper and register it
-            ContributionScanner scanner = new LazyContributionScanner(contributionType, scannerDeclaration);
+            ContributionScanner scanner = new LazyContributionScanner(registry, contributionType, scannerDeclaration);
             addContributionScanner(scanner);
         }
 
@@ -90,21 +92,22 @@
      * 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(String contributionType, ServiceDeclaration scannerDeclaration) {
+        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 URL getArtifactURL(Contribution contributionSourceURL, String artifact) throws ContributionReadException {
-            return getScanner().getArtifactURL(contributionSourceURL, artifact);
-        }
-
-        public List<String> scan(Contribution contributionSourceURL) throws ContributionReadException {
+        public List<Artifact> scan(Contribution contributionSourceURL) throws ContributionReadException {
             return getScanner().scan(contributionSourceURL);
         }
 
@@ -116,8 +119,8 @@
             if (scanner == null) {
                 try {
                     Class<ContributionScanner> scannerClass = (Class<ContributionScanner>)scannerDeclaration.loadClass();
-                    Constructor<ContributionScanner> constructor = scannerClass.getConstructor();
-                    scanner = constructor.newInstance();
+                    Constructor<ContributionScanner> constructor = scannerClass.getConstructor(ContributionFactory.class);
+                    scanner = constructor.newInstance(contributionFactory);
                 } catch (Exception e) {
                     throw new IllegalStateException(e);
                 }

Modified: tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/DirectoryContributionScanner.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/DirectoryContributionScanner.java?rev=891986&r1=891985&r2=891986&view=diff
==============================================================================
--- tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/DirectoryContributionScanner.java (original)
+++ tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/DirectoryContributionScanner.java Thu Dec 17 23:28:45 2009
@@ -24,11 +24,12 @@
 import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
-import java.net.URL;
 import java.util.ArrayList;
 import java.util.List;
 
+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;
@@ -39,25 +40,47 @@
  * @version $Rev$ $Date$
  */
 public class DirectoryContributionScanner implements ContributionScanner {
-
-    public DirectoryContributionScanner() {
+    private ContributionFactory contributionFactory; 
+        
+    public DirectoryContributionScanner(ContributionFactory contributionFactory) {
+        this.contributionFactory = contributionFactory;
     }
 
     public String getContributionType() {
         return PackageType.FOLDER;
     }
 
-    public URL getArtifactURL(Contribution contribution, String artifact) throws ContributionReadException {
+    public List<Artifact> scan(Contribution contribution) throws ContributionReadException {
         File directory = directory(contribution);
-        File file = new File(directory, artifact);
-        try {
-            return file.toURI().toURL();
-        } catch (MalformedURLException e) {
-            throw new ContributionReadException(e);
+        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;
     }
 
-    public List<String> scan(Contribution contribution) throws ContributionReadException {
+    
+    /**
+     * 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>();
         try {
@@ -65,10 +88,10 @@
         } catch (IOException e) {
             throw new ContributionReadException(e);
         }
-        contribution.getTypes().add(getContributionType());
+        
         return artifacts;
     }
-
+    
     /**
      * Recursively traverse a root directory
      *
@@ -95,8 +118,15 @@
             }
         }
     }
-
-    private static File directory(Contribution contribution) throws ContributionReadException {
+        
+    /**
+     * 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 {
@@ -113,5 +143,6 @@
         }
         return file;
     }
+    
 
 }

Modified: tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/JarContributionScanner.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/JarContributionScanner.java?rev=891986&r1=891985&r2=891986&view=diff
==============================================================================
--- tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/JarContributionScanner.java (original)
+++ tuscany/sca-java-2.x/trunk/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/scanner/impl/JarContributionScanner.java Thu Dec 17 23:28:45 2009
@@ -30,7 +30,9 @@
 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;
@@ -41,29 +43,17 @@
  * @version $Rev$ $Date$
  */
 public class JarContributionScanner implements ContributionScanner {
+    private ContributionFactory contributionFactory;
 
-    public JarContributionScanner() {
+    public JarContributionScanner(ContributionFactory contributionFactory) {
+        this.contributionFactory = contributionFactory;
     }
 
     public String getContributionType() {
         return PackageType.JAR;
     }
 
-    public 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);
-        }
-    }
-
-    public List<String> scan(Contribution contribution) throws ContributionReadException {
+    public List<Artifact> scan(Contribution contribution) throws ContributionReadException {
 
         // Assume the URL references a JAR file
         try {
@@ -108,8 +98,16 @@
                     }
                 }
 
-                // Return list of URIs
-                List<String> artifacts = new ArrayList<String>(names);
+                // 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;
 
@@ -120,7 +118,26 @@
             throw new ContributionReadException(e);
         }
     }
-
-    public void postProcess(Contribution contribution) {
+    
+    /**
+     * 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);
+        }
     }
 }