Index: src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java =================================================================== --- src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java (revision 1306249) +++ src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java (working copy) @@ -50,6 +50,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.jar.JarFile; import java.util.jar.JarInputStream; import java.util.jar.Manifest; import java.util.regex.Matcher; @@ -100,6 +101,7 @@ public static final String CONFIG_KEY = "org.apache.karaf.features.configKey"; public static String VERSION_PREFIX = "version="; + private static final String REFERENCE_PROTOCOL = "reference"; private static final Logger LOGGER = LoggerFactory.getLogger(FeaturesServiceImpl.class); @@ -680,25 +682,57 @@ } protected Bundle installBundleIfNeeded(InstallationState state, BundleInfo bundleInfo, int defaultStartLevel, boolean verbose) throws IOException, BundleException { - InputStream is; + URL url; + Manifest m = null; + InputStream is = null; String bundleLocation = bundleInfo.getLocation(); LOGGER.debug("Checking " + bundleLocation); - try { - is = new BufferedInputStream(new URL(bundleLocation).openStream()); + try { + url = new URL(bundleLocation); + String protocol = url.getProtocol(); + if (REFERENCE_PROTOCOL.equals(protocol)) { + URI uri = URI.create(url.getFile()); + String scheme = uri.getScheme(); + if ("file".equalsIgnoreCase(scheme)) { + File reference = new File(uri); + if (reference.isDirectory()) { + File file = new File(reference, JarFile.MANIFEST_NAME); + if (file.exists()) { + InputStream inputStream = new FileInputStream(file); + try { + m = new Manifest(new BufferedInputStream(inputStream)); + } finally { + inputStream.close(); + } + } + } else { + JarFile jarFile = new JarFile(reference); + m = jarFile.getManifest(); + } + } else { + is = new BufferedInputStream(url.openStream()); + } + } else { + is = new BufferedInputStream(url.openStream()); + } } catch (RuntimeException e) { - LOGGER.error(e.getMessage()); + LOGGER.error(bundleLocation + " - " + e.getMessage()); throw e; } try { - is.mark(256 * 1024); - JarInputStream jar = new JarInputStream(is); - Manifest m = jar.getManifest(); - if(m == null) { - throw new BundleException("Manifest not present in the first entry of the zip " + bundleLocation); - } + if (is != null) { + is.mark(256 * 1024); + JarInputStream jar = new JarInputStream(is); + m = jar.getManifest(); + if(m == null) { + throw new BundleException("Manifest not present in the first entry of the zip " + bundleLocation); + } + } else if (m == null) { + throw new BundleException("Manifest not present at location " + bundleLocation); + } String sn = m.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME); if (sn == null) { - throw new BundleException("Jar is not a bundle, no Bundle-SymbolicName " + bundleLocation); + throw new BundleException("Location does not point to a bundle, no Bundle-SymbolicName " + bundleLocation); } // remove attributes from the symbolic name (like ;blueprint.graceperiod:=false suffix) int attributeIndexSep = sn.indexOf(';'); @@ -721,11 +755,13 @@ } } } - try { - is.reset(); - } catch (IOException e) { - is.close(); - is = new BufferedInputStream(new URL(bundleLocation).openStream()); + if (is != null) { + try { + is.reset(); + } catch (IOException e) { + is.close(); + is = new BufferedInputStream(url.openStream()); + } } LOGGER.debug("Installing bundle " + bundleLocation); if (verbose) { @@ -745,7 +781,9 @@ state.installed.add(b); return b; } finally { - is.close(); + if (is != null) { + is.close(); + } } }