Index: pom.xml =================================================================== --- pom.xml (revision 1300512) +++ pom.xml (working copy) @@ -105,6 +105,11 @@ org.ops4j.pax.url + pax-url-reference + 1.4.0.RC1 + + + org.ops4j.pax.url pax-url-wrap Index: src/main/java/org/apache/karaf/tooling/features/CustomBundleURLStreamHandlerFactory.java =================================================================== --- src/main/java/org/apache/karaf/tooling/features/CustomBundleURLStreamHandlerFactory.java (revision 1300512) +++ src/main/java/org/apache/karaf/tooling/features/CustomBundleURLStreamHandlerFactory.java (working copy) @@ -28,12 +28,15 @@ private static final String SPRING_URI_PREFIX = "spring"; private static final String BLUEPRINT_URI_PREFIX = "blueprint"; private static final String WAR_URI_PREFIX = "war"; + private static final String REFERENCE_URI_PREFIX = "reference"; public URLStreamHandler createURLStreamHandler(String protocol) { if (protocol.equals(MVN_URI_PREFIX)) { return new org.ops4j.pax.url.mvn.Handler(); } else if (protocol.equals(WRAP_URI_PREFIX)){ return new org.ops4j.pax.url.wrap.Handler(); + } else if (protocol.equals(REFERENCE_URI_PREFIX)) { + return new org.ops4j.pax.url.reference.Handler(); } else if (protocol.equals(FEATURE_URI_PREFIX)){ return new FeatureURLHandler(); } else if (protocol.equals(SPRING_URI_PREFIX)){ Index: src/main/java/org/apache/karaf/tooling/features/GenerateDescriptorMojo.java =================================================================== --- src/main/java/org/apache/karaf/tooling/features/GenerateDescriptorMojo.java (revision 1300512) +++ src/main/java/org/apache/karaf/tooling/features/GenerateDescriptorMojo.java (working copy) @@ -17,19 +17,32 @@ */ package org.apache.karaf.tooling.features; -import java.io.*; +import static org.apache.karaf.deployer.kar.KarArtifactInstaller.FEATURE_CLASSIFIER; + +import java.io.BufferedInputStream; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintStream; +import java.io.StringWriter; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; -import java.util.jar.JarInputStream; +import java.util.jar.JarFile; import java.util.jar.Manifest; import javax.xml.bind.JAXBException; import javax.xml.parsers.ParserConfigurationException; import javax.xml.stream.XMLStreamException; + import org.apache.karaf.features.internal.model.Bundle; import org.apache.karaf.features.internal.model.Dependency; import org.apache.karaf.features.internal.model.Feature; @@ -55,13 +68,13 @@ import org.sonatype.aether.RepositorySystem; import org.sonatype.aether.RepositorySystemSession; import org.sonatype.aether.artifact.Artifact; +import org.sonatype.aether.repository.ArtifactRepository; import org.sonatype.aether.repository.RemoteRepository; +import org.sonatype.aether.repository.WorkspaceRepository; import org.sonatype.aether.resolution.ArtifactRequest; import org.sonatype.aether.resolution.ArtifactResult; import org.xml.sax.SAXException; -import static org.apache.karaf.deployer.kar.KarArtifactInstaller.FEATURE_CLASSIFIER; - /** * Generates the features XML file * NB this requires a recent maven-install-plugin such as 2.3.1 @@ -276,9 +289,11 @@ } for (Map.Entry entry : localDependencies.entrySet()) { Artifact artifact = entry.getKey(); + ArtifactResult artifactResult = resolve(artifact); + artifact = artifactResult.getArtifact(); if (DependencyHelper.isFeature(artifact)) { if (aggregateFeatures && FEATURE_CLASSIFIER.equals(artifact.getClassifier())) { - File featuresFile = resolve(artifact); + File featuresFile = artifact.getFile(); if (featuresFile == null || !featuresFile.exists()) { throw new MojoExecutionException("Cannot locate file for feature: " + artifact + " at " + featuresFile); } @@ -293,24 +308,27 @@ feature.getFeature().add(dependency); } } else { - String bundleName = MavenUtil.artifactToMvn(artifact); - File bundleFile = resolve(artifact); + File bundleFile = artifact.getFile(); + ArtifactRepository repository = artifactResult.getRepository(); + String location = repository instanceof WorkspaceRepository ? bundleFile.toURI().toString() : MavenUtil.artifactToMvn(artifact); Manifest manifest = getManifest(bundleFile); - if (manifest == null || !ManifestUtils.isBundle(getManifest(bundleFile))) { - bundleName = "wrap:" + bundleName; + if (manifest == null || !ManifestUtils.isBundle(manifest)) { + location = "wrap:" + location; + } else if (repository instanceof WorkspaceRepository) { + location = "reference:" + location; } Bundle bundle = null; for (Bundle b: feature.getBundle()) { - if (bundleName.equals(b.getLocation())) { + if (location.equals(b.getLocation())) { bundle = b; break; } } if (bundle == null) { bundle = objectFactory.createBundle(); - bundle.setLocation(bundleName); + bundle.setLocation(location); feature.getBundle().add(bundle); } if ("runtime".equals(entry.getValue())) { @@ -340,29 +358,33 @@ * Extract the MANIFEST from the give file. */ private Manifest getManifest(File file) throws IOException { - InputStream is = null; + Manifest m = null; try { - is = new BufferedInputStream(new FileInputStream(file)); + if (file.isDirectory()) { + File resource = new File(file, JarFile.MANIFEST_NAME); + if (resource.exists()) { + InputStream inputStream = new FileInputStream(resource); + try { + m = new Manifest(new BufferedInputStream(inputStream)); + } finally { + inputStream.close(); + } + } + } else { + JarFile jarFile = new JarFile(file); + m = jarFile.getManifest(); + } } catch (Exception e) { getLogger().warn("Error while opening artifact", e); } - - try { - is.mark(256 * 1024); - JarInputStream jar = new JarInputStream(is); - Manifest m = jar.getManifest(); - if (m == null) { - getLogger().warn("Manifest not present in the first entry of the zip - " + file.getName()); - } - return m; - } finally { - if (is != null) { // just in case when we did not open bundle - is.close(); - } + + if (m == null) { + getLogger().warn("Manifest not present in the location " + file.getCanonicalPath()); } + return m; } - private File resolve(Artifact artifact) { + private ArtifactResult resolve(Artifact artifact) { ArtifactRequest request = new ArtifactRequest(); request.setArtifact(artifact); request.setRepositories(projectRepos); @@ -381,7 +403,7 @@ getLog().debug("Resolved artifact " + artifact + " to " + result.getArtifact().getFile() + " from " + result.getRepository()); - return result.getArtifact().getFile(); + return result; } Index: src/main/java/org/apache/karaf/tooling/features/ValidateDescriptorMojo.java =================================================================== --- src/main/java/org/apache/karaf/tooling/features/ValidateDescriptorMojo.java (revision 1300512) +++ src/main/java/org/apache/karaf/tooling/features/ValidateDescriptorMojo.java (working copy) @@ -17,6 +17,10 @@ */ package org.apache.karaf.tooling.features; +import static org.apache.karaf.tooling.features.ManifestUtils.getExports; +import static org.apache.karaf.tooling.features.ManifestUtils.getMandatoryImports; +import static org.apache.karaf.tooling.features.ManifestUtils.matches; + import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -26,7 +30,15 @@ import java.io.PrintStream; import java.net.URI; import java.net.URL; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.jar.JarFile; import java.util.jar.JarInputStream; import java.util.jar.Manifest; import java.util.zip.ZipException; @@ -61,7 +73,7 @@ /** * Validates a features XML file * - * @version $Revision:$ + * @version $Revision$ * @goal features-validate-descriptor * @execute phase="process-resources" * @requiresDependencyResolution runtime @@ -493,34 +505,67 @@ */ private Manifest getManifest(String bundle, Object artifact) throws ArtifactResolutionException, ArtifactNotFoundException, ZipException, IOException { - ZipFile file = null; + Manifest manifest = null; if (!(artifact instanceof Artifact)) { //not resolved as mvn artifact, so it's non-mvn protocol, just use the CustomBundleURLStreamHandlerFactory // to open stream - InputStream is = null; + URL url = null; + File reference = null; try { - is = new BufferedInputStream(new URL(bundle).openStream()); + url = new URL(bundle); + String protocol = url.getProtocol(); + if ("reference".equals(protocol)) { + URI uri = new URI(url.getFile()); + String scheme = uri.getScheme(); + if ("file".equalsIgnoreCase(scheme)) { + reference = new File(uri); + if (reference.isDirectory()) { + File file = new File(reference, JarFile.MANIFEST_NAME); + if (file.exists()) { + InputStream inputStream = new FileInputStream(reference); + try { + manifest = new Manifest(inputStream); + } finally { + inputStream.close(); + } + } + } else { + JarFile jarFile = new JarFile(reference); + manifest = jarFile.getManifest(); + } + } + } } catch (Exception e){ - getLog().warn("Error while opening artifact", e); + getLog().warn("Error while opening artifact " + bundle, e); } - - try { - is.mark(256 * 1024); - JarInputStream jar = new JarInputStream(is); - Manifest m = jar.getManifest(); - if(m == null) { - throw new IOException("Manifest not present in the first entry of the zip"); + if (reference != null) { + if (manifest == null) { + throw new IOException("Manifest not present in the location " + bundle); } - - return m; - } finally { - if (is != null) { // just in case when we did not open bundle - is.close(); + } else if (url != null) { + InputStream is = null; + try { + is = new BufferedInputStream(url.openStream()); + } catch (Exception e){ + getLog().warn("Error while opening artifact " + bundle, e); } + + try { + JarInputStream jar = new JarInputStream(is); + manifest = jar.getManifest(); + if(manifest == null) { + throw new IOException("Manifest not present in the first entry of the zip " + bundle); + } + } finally { + if (is != null) { // just in case when we did not open bundle + is.close(); + } + } } } else { Artifact mvnArtifact = (Artifact) artifact; File localFile = new File(localRepo.pathOf(mvnArtifact)); + ZipFile file; if (localFile.exists()) { // avoid going over to the repository if the file is already on // the disk @@ -533,12 +578,12 @@ PrintStream original = System.err; try { System.setErr(new PrintStream(new ByteArrayOutputStream())); - Manifest manifest = new Manifest(file.getInputStream(file.getEntry("META-INF/MANIFEST.MF"))); - return manifest; + manifest = new Manifest(file.getInputStream(file.getEntry(JarFile.MANIFEST_NAME))); } finally { System.setErr(original); } } + return manifest; } /*