You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by pa...@apache.org on 2019/06/07 16:33:30 UTC

[sling-org-apache-sling-feature-launcher] 01/01: SLING-8421: Allow artifact providers that work with URLs instead of Files

This is an automated email from the ASF dual-hosted git repository.

pauls pushed a commit to branch issues/SLING-8421-2
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-launcher.git

commit 9b91069fd259234c7822ab2d15d460388244e7e7
Author: Karl Pauls <ka...@gmail.com>
AuthorDate: Fri Jun 7 18:33:17 2019 +0200

    SLING-8421: Allow artifact providers that work with URLs instead of Files
---
 pom.xml                                            |  6 +--
 .../sling/feature/launcher/impl/Bootstrap.java     | 21 ++------
 .../launcher/impl/ExtensionContextImpl.java        | 23 ++++-----
 .../feature/launcher/impl/FeatureProcessor.java    | 57 ++++------------------
 .../sling/feature/launcher/impl/Installation.java  | 18 +++----
 .../feature/launcher/impl/LauncherConfig.java      |  4 +-
 .../launcher/impl/launchers/AbstractRunner.java    | 23 ++++-----
 .../launcher/impl/launchers/FrameworkLauncher.java |  5 +-
 .../launcher/impl/launchers/FrameworkRunner.java   |  5 +-
 .../launcher/spi/LauncherPrepareContext.java       |  5 +-
 .../feature/launcher/spi/LauncherRunContext.java   |  6 +--
 .../launcher/spi/extensions/ExtensionContext.java  |  6 +--
 .../launcher/impl/ExtensionContextImplTest.java    |  3 +-
 13 files changed, 64 insertions(+), 118 deletions(-)

diff --git a/pom.xml b/pom.xml
index 4ec8ba1..85affda 100644
--- a/pom.xml
+++ b/pom.xml
@@ -113,19 +113,19 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.feature</artifactId>
-            <version>1.0.2</version>
+            <version>1.0.3-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.feature.io</artifactId>
-            <version>1.0.2</version>
+            <version>1.0.3-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.felix</groupId>
             <artifactId>org.apache.felix.converter</artifactId>
-            <version>1.0.0</version>
+            <version>1.0.8</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/Bootstrap.java b/src/main/java/org/apache/sling/feature/launcher/impl/Bootstrap.java
index d950a6b..47ee97c 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/Bootstrap.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/Bootstrap.java
@@ -31,8 +31,8 @@ import java.util.ServiceLoader;
 
 import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.Feature;
-import org.apache.sling.feature.io.file.ArtifactHandler;
-import org.apache.sling.feature.io.file.ArtifactManager;
+import org.apache.sling.feature.io.artifacts.ArtifactHandler;
+import org.apache.sling.feature.io.artifacts.ArtifactManager;
 import org.apache.sling.feature.io.json.FeatureJSONWriter;
 import org.apache.sling.feature.launcher.spi.Launcher;
 import org.apache.sling.feature.launcher.spi.LauncherPrepareContext;
@@ -141,24 +141,13 @@ public class Bootstrap {
                     }
 
                     @Override
-                    public File getArtifactFile(final ArtifactId artifact) throws IOException {
+                    public URL getArtifactFile(final ArtifactId artifact) throws IOException {
                         final ArtifactHandler handler = artifactManager.getArtifactHandler(":" + artifact.toMvnPath());
-                        return handler.getFile();
+                        return handler.getLocalURL();
                     }
 
                     @Override
-                    public void addAppJar(final File jar) {
-                        try {
-                            config.getInstallation().addAppJar(jar.toURI().toURL());
-                        }
-                        catch (MalformedURLException e) {
-                            throw new RuntimeException(e);
-                        }
-                    }
-
-                    @Override
-                    public void addAppJar(final URL jar)
-                    {
+                    public void addAppJar(final URL jar) {
                         config.getInstallation().addAppJar(jar);
                     }
                 };
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/ExtensionContextImpl.java b/src/main/java/org/apache/sling/feature/launcher/impl/ExtensionContextImpl.java
index 8f3bb6d..3d836e8 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/ExtensionContextImpl.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/ExtensionContextImpl.java
@@ -16,9 +16,9 @@
  */
 package org.apache.sling.feature.launcher.impl;
 
-import java.io.File;
-import java.io.FileReader;
 import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
 import java.net.URL;
 import java.util.Dictionary;
 import java.util.List;
@@ -50,12 +50,12 @@ class ExtensionContextImpl implements ExtensionContext {
     }
 
     @Override
-    public void addBundle(Integer startLevel, File file) {
+    public void addBundle(Integer startLevel, URL file) {
         installation.addBundle(startLevel, file);
     }
 
     @Override
-    public void addInstallableArtifact(File file) {
+    public void addInstallableArtifact(URL file) {
         installation.addInstallableArtifact(file);
     }
 
@@ -75,7 +75,7 @@ class ExtensionContextImpl implements ExtensionContext {
     }
 
     @Override
-    public Map<Integer, List<File>> getBundleMap() {
+    public Map<Integer, List<URL>> getBundleMap() {
         return installation.getBundleMap();
     }
 
@@ -85,22 +85,17 @@ class ExtensionContextImpl implements ExtensionContext {
     }
 
     @Override
-    public List<File> getInstallableArtifacts() {
+    public List<URL> getInstallableArtifacts() {
         return installation.getInstallableArtifacts();
     }
 
     @Override
-    public void addAppJar(File jar) {
-        prepareContext.addAppJar(jar);
-    }
-
-    @Override
     public void addAppJar(URL jar) {
         prepareContext.addAppJar(jar);
     }
 
     @Override
-    public File getArtifactFile(ArtifactId artifact) throws IOException {
+    public URL getArtifactFile(ArtifactId artifact) throws IOException {
         return prepareContext.getArtifactFile(artifact);
     }
 
@@ -110,11 +105,11 @@ class ExtensionContextImpl implements ExtensionContext {
         if (f != null)
             return f;
 
-        File file = getArtifactFile(artifact);
+        URL file = getArtifactFile(artifact);
         if (file == null)
             return null;
 
-        try (FileReader r = new FileReader(file)) {
+        try (Reader r = new InputStreamReader(file.openStream(), "UTF-8")) {
             return FeatureJSONReader.read(r, artifact.toMvnUrl());
         }
     }
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
index 175d209..7307020 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/FeatureProcessor.java
@@ -16,10 +16,10 @@
  */
 package org.apache.sling.feature.launcher.impl;
 
-import java.io.File;
-import java.io.FileReader;
 import java.io.IOException;
-import java.util.HashMap;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
 import java.util.List;
 import java.util.Map;
 import java.util.ServiceLoader;
@@ -31,15 +31,14 @@ import org.apache.sling.feature.Artifact;
 import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.Configuration;
 import org.apache.sling.feature.Extension;
-import org.apache.sling.feature.ExtensionType;
 import org.apache.sling.feature.Feature;
 import org.apache.sling.feature.builder.BuilderContext;
 import org.apache.sling.feature.builder.FeatureBuilder;
 import org.apache.sling.feature.builder.MergeHandler;
 import org.apache.sling.feature.builder.PostProcessHandler;
 import org.apache.sling.feature.io.IOUtils;
-import org.apache.sling.feature.io.file.ArtifactHandler;
-import org.apache.sling.feature.io.file.ArtifactManager;
+import org.apache.sling.feature.io.artifacts.ArtifactHandler;
+import org.apache.sling.feature.io.artifacts.ArtifactManager;
 import org.apache.sling.feature.io.json.FeatureJSONReader;
 import org.apache.sling.feature.launcher.spi.LauncherPrepareContext;
 import org.apache.sling.feature.launcher.spi.extensions.ExtensionHandler;
@@ -62,7 +61,7 @@ public class FeatureProcessor {
         final BuilderContext builderContext = new BuilderContext(id -> {
             try {
                 final ArtifactHandler handler = artifactManager.getArtifactHandler(id.toMvnUrl());
-                try (final FileReader r = new FileReader(handler.getFile())) {
+                try (final Reader r = new InputStreamReader(handler.getLocalURL().openStream(), "UTF-8")) {
                     final Feature f = FeatureJSONReader.read(r, handler.getUrl());
                     return f;
                 }
@@ -74,7 +73,7 @@ public class FeatureProcessor {
         builderContext.setArtifactProvider(id -> {
             try {
                 final ArtifactHandler handler = artifactManager.getArtifactHandler(id.toMvnUrl());
-                return handler.getFile();
+                return handler.getLocalURL();
             } catch (final IOException e) {
                 // ignore
                 return null;
@@ -93,7 +92,7 @@ public class FeatureProcessor {
         for (final String initFile : IOUtils.getFeatureFiles(config.getHomeDirectory(), config.getFeatureFiles())) {
             logger.debug("Reading feature file {}", initFile);
             final ArtifactHandler featureArtifact = artifactManager.getArtifactHandler(initFile);
-            try (final FileReader r = new FileReader(featureArtifact.getFile())) {
+            try (final Reader r = new InputStreamReader(featureArtifact.getLocalURL().openStream(), "UTF-8")) {
                 final Feature f = FeatureJSONReader.read(r, featureArtifact.getUrl());
                 loadedFeatures.put(f.getId(), f);
             } catch (Exception ex) {
@@ -134,7 +133,7 @@ public class FeatureProcessor {
             final Feature app, Map<ArtifactId, Feature> loadedFeatures) throws Exception {
         for(final Map.Entry<Integer, List<Artifact>> entry : app.getBundles().getBundlesByStartOrder().entrySet()) {
             for(final Artifact a : entry.getValue()) {
-                final File artifactFile = ctx.getArtifactFile(a.getId());
+                final URL artifactFile = ctx.getArtifactFile(a.getId());
 
                 config.getInstallation().addBundle(entry.getKey(), artifactFile);
             }
@@ -167,42 +166,4 @@ public class FeatureProcessor {
             }
         }
     }
-
-    /**
-     * Prepare the cache
-     * - add all bundles
-     * - add all other artifacts (only if startup mode is INSTALL)
-     * @param artifactManager The artifact manager
-     * @param app the feature with the artifacts
-     * @return An Artifact to File mapping.
-     * @throws Exception when something goes wrong.
-     */
-    public static Map<Artifact, File> calculateArtifacts(final ArtifactManager artifactManager,
-        final Feature app) throws Exception
-    {
-        Map<Artifact, File> result = new HashMap<>();
-        for (final Map.Entry<Integer, List<Artifact>> entry : app.getBundles().getBundlesByStartOrder().entrySet())
-        {
-            for (final Artifact a : entry.getValue())
-            {
-                final ArtifactHandler handler = artifactManager.getArtifactHandler(":" + a.getId().toMvnPath());
-                final File artifactFile = handler.getFile();
-
-                result.put(a, artifactFile);
-            }
-        }
-        for (final Extension ext : app.getExtensions())
-        {
-            if (ext.getType() == ExtensionType.ARTIFACTS
-                    && ext.getName().equals(Extension.EXTENSION_NAME_CONTENT_PACKAGES))
-            {
-                for (final Artifact a : ext.getArtifacts())
-                {
-                    final ArtifactHandler handler = artifactManager.getArtifactHandler(":" + a.getId().toMvnPath());
-                    result.put(a, handler.getFile());
-                }
-            }
-        }
-        return result;
-    }
 }
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/Installation.java b/src/main/java/org/apache/sling/feature/launcher/impl/Installation.java
index 483359e..9a32143 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/Installation.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/Installation.java
@@ -36,10 +36,10 @@ public class Installation implements LauncherRunContext {
     private final Map<String, String> fwkProperties = new HashMap<>();
 
     /** Bundle map */
-    private final Map<Integer, List<File>> bundleMap = new HashMap<>();
+    private final Map<Integer, List<URL>> bundleMap = new HashMap<>();
 
     /** Artifacts to be installed */
-    private final List<File> installables = new ArrayList<>();
+    private final List<URL> installables = new ArrayList<>();
 
     /** Configurations, they are installed on first start. */
     private final List<Object[]> configurations = new ArrayList<>();
@@ -68,10 +68,10 @@ public class Installation implements LauncherRunContext {
     /**
      * Add a bundle with the given start level
      * @param startLevel The start level
-     * @param file The bundle file
+     * @param file The url to the bundle file
      */
-    public void addBundle(final Integer startLevel, final File file) {
-        List<File> files = bundleMap.get(startLevel);
+    public void addBundle(final Integer startLevel, final URL file) {
+        List<URL> files = bundleMap.get(startLevel);
         if ( files == null ) {
             files = new ArrayList<>();
             bundleMap.put(startLevel, files);
@@ -81,9 +81,9 @@ public class Installation implements LauncherRunContext {
 
     /**
      * Add an artifact to be installed by the installer
-     * @param file The file
+     * @param file The url to the file
      */
-    public void addInstallableArtifact(final File file) {
+    public void addInstallableArtifact(final URL file) {
         this.installables.add(file);
     }
 
@@ -114,7 +114,7 @@ public class Installation implements LauncherRunContext {
      * @see org.apache.sling.feature.launcher.spi.LauncherRunContext#getBundleMap()
      */
     @Override
-    public Map<Integer, List<File>> getBundleMap() {
+    public Map<Integer, List<URL>> getBundleMap() {
         return this.bundleMap;
     }
 
@@ -130,7 +130,7 @@ public class Installation implements LauncherRunContext {
      * @see org.apache.sling.feature.launcher.spi.LauncherRunContext#getInstallableArtifacts()
      */
     @Override
-    public List<File> getInstallableArtifacts() {
+    public List<URL> getInstallableArtifacts() {
         return this.installables;
     }
 
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java b/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
index c011385..c5b1483 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/LauncherConfig.java
@@ -24,8 +24,8 @@ import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 
-import org.apache.sling.feature.io.file.ArtifactManagerConfig;
-import org.apache.sling.feature.io.file.spi.ArtifactProviderContext;
+import org.apache.sling.feature.io.artifacts.ArtifactManagerConfig;
+import org.apache.sling.feature.io.artifacts.spi.ArtifactProviderContext;
 
 /**
  * This class holds the configuration of the launcher.
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/launchers/AbstractRunner.java b/src/main/java/org/apache/sling/feature/launcher/impl/launchers/AbstractRunner.java
index b4d4275..d4deb1a 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/launchers/AbstractRunner.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/launchers/AbstractRunner.java
@@ -23,6 +23,7 @@ import java.io.InputStream;
 import java.lang.reflect.Array;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -65,17 +66,17 @@ public abstract class AbstractRunner implements Callable<Integer> {
 
     private final List<Object[]> configurations;
 
-    private final List<File> installables;
+    private final List<URL> installables;
 
     protected final Logger logger;
 
-    public AbstractRunner(final List<Object[]> configurations, final List<File> installables) {
+    public AbstractRunner(final List<Object[]> configurations, final List<URL> installables) {
         this.configurations = new ArrayList<>(configurations);
         this.installables = installables;
         logger = LoggerFactory.getLogger("launcher");
     }
 
-    protected void setupFramework(final Framework framework, final Map<Integer, List<File>> bundlesMap)
+    protected void setupFramework(final Framework framework, final Map<Integer, List<URL>> bundlesMap)
     throws BundleException {
         if ( !configurations.isEmpty() ) {
             this.configAdminTracker = new ServiceTracker<>(framework.getBundleContext(),
@@ -226,19 +227,19 @@ public abstract class AbstractRunner implements Callable<Integer> {
      * @param bundleMap The map with the bundles indexed by start level
      * @throws IOException, BundleException If anything goes wrong.
      */
-    private void install(final Framework framework, final Map<Integer, List<File>> bundleMap)
+    private void install(final Framework framework, final Map<Integer, List<URL>> bundleMap)
     throws IOException, BundleException {
         final BundleContext bc = framework.getBundleContext();
         int defaultStartLevel = getProperty(bc, "felix.startlevel.bundle", 1);
         for(final Integer startLevel : sortStartLevels(bundleMap.keySet(), defaultStartLevel)) {
             logger.debug("Installing bundles with start level {}", startLevel);
 
-            for(final File file : bundleMap.get(startLevel)) {
-                logger.debug("- {}", file.getName());
+            for(final URL file : bundleMap.get(startLevel)) {
+                logger.debug("- {}", file);
 
                 // use reference protocol. This avoids copying the binary to the cache directory
                 // of the framework
-                final Bundle bundle = bc.installBundle("reference:" + file.toURI().toURL(), null);
+                final Bundle bundle = bc.installBundle("reference:" + file, null);
 
                 // fragment?
                 if ( !isSystemBundleFragment(bundle) && getFragmentHostHeader(bundle) == null ) {
@@ -290,13 +291,13 @@ public abstract class AbstractRunner implements Callable<Integer> {
                     Integer.class);
 
             for(int i=0; i<this.installables.size();i++) {
-                final File f = this.installables.get(i);
+                final URL f = this.installables.get(i);
                 final Dictionary<String, Object> dict = new Hashtable<>();
                 dict.put("resource.uri.hint", f.toURI().toString());
-                final Object rsrc = constructor.newInstance(f.getAbsolutePath(),
-                        new FileInputStream(f),
+                final Object rsrc = constructor.newInstance(f.getPath(),
+                        f.openStream(),
                         dict,
-                        f.getName(),
+                        f.getPath(),
                         "file",
                         null);
                 Array.set(resources, i, rsrc);
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java b/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java
index 22b4c32..eab44be 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkLauncher.java
@@ -18,6 +18,7 @@ package org.apache.sling.feature.launcher.impl.launchers;
 
 import java.io.File;
 import java.lang.reflect.Constructor;
+import java.net.URL;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -71,8 +72,8 @@ public class FrameworkLauncher implements Launcher {
             context.getLogger().debug("Bundles:");
             for(final Integer key : context.getBundleMap().keySet()) {
                 context.getLogger().debug("-- Start Level {}", key);
-                for(final File f : context.getBundleMap().get(key)) {
-                    context.getLogger().debug("  - {}", f.getName());
+                for(final URL f : context.getBundleMap().get(key)) {
+                    context.getLogger().debug("  - {}", f);
                 }
             }
             context.getLogger().debug("Settings: ");
diff --git a/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkRunner.java b/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkRunner.java
index 5d84dd4..0f12761 100644
--- a/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkRunner.java
+++ b/src/main/java/org/apache/sling/feature/launcher/impl/launchers/FrameworkRunner.java
@@ -17,6 +17,7 @@
 package org.apache.sling.feature.launcher.impl.launchers;
 
 import java.io.File;
+import java.net.URL;
 import java.util.List;
 import java.util.Map;
 import java.util.ServiceLoader;
@@ -40,9 +41,9 @@ public class FrameworkRunner extends AbstractRunner {
     private volatile int type = -1;
 
     public FrameworkRunner(final Map<String, String> frameworkProperties,
-            final Map<Integer, List<File>> bundlesMap,
+            final Map<Integer, List<URL>> bundlesMap,
             final List<Object[]> configurations,
-            final List<File> installables) throws Exception {
+            final List<URL> installables) throws Exception {
         super(configurations, installables);
 
         final ServiceLoader<FrameworkFactory> loader = ServiceLoader.load(FrameworkFactory.class);
diff --git a/src/main/java/org/apache/sling/feature/launcher/spi/LauncherPrepareContext.java b/src/main/java/org/apache/sling/feature/launcher/spi/LauncherPrepareContext.java
index 624b9fd..e0ec94d 100644
--- a/src/main/java/org/apache/sling/feature/launcher/spi/LauncherPrepareContext.java
+++ b/src/main/java/org/apache/sling/feature/launcher/spi/LauncherPrepareContext.java
@@ -16,7 +16,6 @@
  */
 package org.apache.sling.feature.launcher.spi;
 
-import java.io.File;
 import java.io.IOException;
 import java.net.URL;
 
@@ -35,9 +34,7 @@ public interface LauncherPrepareContext {
      */
     Logger getLogger();
 
-    void addAppJar(File jar);
-
     void addAppJar(URL url);
 
-    File getArtifactFile(ArtifactId artifact) throws IOException;
+    URL getArtifactFile(ArtifactId artifact) throws IOException;
 }
diff --git a/src/main/java/org/apache/sling/feature/launcher/spi/LauncherRunContext.java b/src/main/java/org/apache/sling/feature/launcher/spi/LauncherRunContext.java
index c2ec088..5c6d9fe 100644
--- a/src/main/java/org/apache/sling/feature/launcher/spi/LauncherRunContext.java
+++ b/src/main/java/org/apache/sling/feature/launcher/spi/LauncherRunContext.java
@@ -16,7 +16,7 @@
  */
 package org.apache.sling.feature.launcher.spi;
 
-import java.io.File;
+import java.net.URL;
 import java.util.List;
 import java.util.Map;
 
@@ -37,7 +37,7 @@ public interface LauncherRunContext {
      * Bundle map, key is the start level, value is a list of files.
      * @return The bundle map, might be empty
      */
-    Map<Integer, List<File>> getBundleMap();
+    Map<Integer, List<URL>> getBundleMap();
 
     /**
      * List of configurations.
@@ -56,7 +56,7 @@ public interface LauncherRunContext {
      * List of installable artifacts.
      * @return The list of files. The list might be empty.
      */
-    List<File> getInstallableArtifacts();
+    List<URL> getInstallableArtifacts();
 
     /**
      * Get the central logger
diff --git a/src/main/java/org/apache/sling/feature/launcher/spi/extensions/ExtensionContext.java b/src/main/java/org/apache/sling/feature/launcher/spi/extensions/ExtensionContext.java
index 21e38ca..3491442 100644
--- a/src/main/java/org/apache/sling/feature/launcher/spi/extensions/ExtensionContext.java
+++ b/src/main/java/org/apache/sling/feature/launcher/spi/extensions/ExtensionContext.java
@@ -21,8 +21,8 @@ import org.apache.sling.feature.Feature;
 import org.apache.sling.feature.launcher.spi.LauncherPrepareContext;
 import org.apache.sling.feature.launcher.spi.LauncherRunContext;
 
-import java.io.File;
 import java.io.IOException;
+import java.net.URL;
 import java.util.Dictionary;
 
 /**
@@ -34,13 +34,13 @@ public interface ExtensionContext extends LauncherPrepareContext, LauncherRunCon
      * @param startLevel The start level for the bundle.
      * @param file The file with the bundle.
      */
-    public void addBundle(final Integer startLevel, final File file);
+    public void addBundle(final Integer startLevel, final URL file);
 
     /**
      * Add an artifact to be installed by the launcher
      * @param file The file
      */
-    public void addInstallableArtifact(final File file);
+    public void addInstallableArtifact(final URL file);
 
     /**
      * Add a configuration to be installed by the launcher
diff --git a/src/test/java/org/apache/sling/feature/launcher/impl/ExtensionContextImplTest.java b/src/test/java/org/apache/sling/feature/launcher/impl/ExtensionContextImplTest.java
index e03b871..9271dd4 100644
--- a/src/test/java/org/apache/sling/feature/launcher/impl/ExtensionContextImplTest.java
+++ b/src/test/java/org/apache/sling/feature/launcher/impl/ExtensionContextImplTest.java
@@ -23,6 +23,7 @@ import org.junit.Test;
 import org.mockito.Mockito;
 
 import java.io.File;
+import java.net.URL;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -33,7 +34,7 @@ import static org.junit.Assert.assertNull;
 public class ExtensionContextImplTest {
     @Test
     public void testGetFeature() throws Exception {
-        File testFeatureFile = new File(getClass().getResource("/test-feature.json").getFile());
+        URL testFeatureFile = getClass().getResource("/test-feature.json");
 
         ArtifactId aid2 = ArtifactId.fromMvnId("g:a:2");
         LauncherPrepareContext lpc = Mockito.mock(LauncherPrepareContext.class);