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/05/07 15:22:03 UTC

[sling-org-apache-sling-feature-launcher] 02/02: SLING-8406: Allow the app class path of the feature launcher to be extended by URLs and allow the launcher extension to provide a classloader implementation

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

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

commit b957b3eccf312c209e9c8c00ace726d413a2088e
Author: Karl Pauls <ka...@gmail.com>
AuthorDate: Tue May 7 17:21:52 2019 +0200

    SLING-8406: Allow the app class path of the feature launcher to be extended by URLs and allow the launcher extension to provide a classloader implementation
---
 .../sling/feature/launcher/impl/Bootstrap.java     | 88 ++++++----------------
 .../launcher/impl/ExtensionContextImpl.java        |  6 ++
 .../sling/feature/launcher/impl/Installation.java  |  7 +-
 .../launcher/impl/launchers/FrameworkRunner.java   |  1 +
 .../sling/feature/launcher/spi/Launcher.java       | 58 ++++++++++++++
 .../launcher/spi/LauncherPrepareContext.java       |  3 +
 6 files changed, 96 insertions(+), 67 deletions(-)

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 400860b..d950a6b 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
@@ -19,8 +19,8 @@ package org.apache.sling.feature.launcher.impl;
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.net.MalformedURLException;
 import java.net.URL;
-import java.net.URLClassLoader;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -34,7 +34,6 @@ 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.json.FeatureJSONWriter;
-import org.apache.sling.feature.launcher.impl.launchers.FrameworkLauncher;
 import org.apache.sling.feature.launcher.spi.Launcher;
 import org.apache.sling.feature.launcher.spi.LauncherPrepareContext;
 import org.osgi.framework.FrameworkEvent;
@@ -135,22 +134,30 @@ public class Bootstrap {
                 this.logger.info("");
                 this.logger.info("Assembling launcher...");
 
-                final LauncherPrepareContext ctx = new LauncherPrepareContext()
-                {
+                final LauncherPrepareContext ctx = new LauncherPrepareContext() {
                     @Override
                     public Logger getLogger() {
                         return logger;
                     }
 
                     @Override
-                    public File getArtifactFile(final ArtifactId artifact) throws IOException
-                    {
+                    public File getArtifactFile(final ArtifactId artifact) throws IOException {
                         final ArtifactHandler handler = artifactManager.getArtifactHandler(":" + artifact.toMvnPath());
                         return handler.getFile();
                     }
 
                     @Override
-                    public void addAppJar(final File jar)
+                    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)
                     {
                         config.getInstallation().addAppJar(jar);
                     }
@@ -265,7 +272,7 @@ public class Bootstrap {
             installation.getFrameworkProperties().put(START_LEVEL_PROP, "30");
         }
 
-        while (launcher.run(installation, createClassLoader(installation, launcher.getClass().getProtectionDomain().getCodeSource().getLocation())) == FrameworkEvent.STOPPED_SYSTEM_REFRESHED) {
+        while (launcher.run(installation, createClassLoader(installation, launcher)) == FrameworkEvent.STOPPED_SYSTEM_REFRESHED) {
             this.logger.info("Framework restart due to extension refresh");
         }
     }
@@ -276,23 +283,16 @@ public class Bootstrap {
      * @return The classloader.
      * @throws Exception If anything goes wrong
      */
-    public ClassLoader createClassLoader(final Installation installation, URL... extra) throws Exception {
+    public ClassLoader createClassLoader(final Installation installation, Launcher launcher) throws Exception {
         final List<URL> list = new ArrayList<>();
-        for(final File f : installation.getAppJars()) {
-            try {
-                list.add(f.toURI().toURL());
-            } catch (IOException e) {
-                // ignore
-            }
-        }
+
+        list.addAll(installation.getAppJars());
 
         list.add(Bootstrap.class.getProtectionDomain().getCodeSource().getLocation());
 
-        if (extra != null) {
-            for (URL url : extra) {
-                list.add(url);
-            }
-        }
+
+        // create a paranoid class loader, loading from parent last
+        final Launcher.LauncherClassLoader cl = launcher.createClassLoader();
 
         final URL[] urls = list.toArray(new URL[list.size()]);
 
@@ -302,49 +302,9 @@ public class Bootstrap {
                 this.logger.debug(" - {}", urls[i]);
             }
         }
-
-        // create a paranoid class loader, loading from parent last
-        final ClassLoader cl = new URLClassLoader(urls) {
-            @Override
-            public final Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
-                // First check if it's already loaded
-                Class<?> clazz = findLoadedClass(name);
-
-                if (clazz == null) {
-
-                    try {
-                        clazz = findClass(name);
-                    } catch (ClassNotFoundException cnfe) {
-                        ClassLoader parent = getParent();
-                        if (parent != null) {
-                            // Ask to parent ClassLoader (can also throw a CNFE).
-                            clazz = parent.loadClass(name);
-                        } else {
-                            // Propagate exception
-                            throw cnfe;
-                        }
-                    }
-                }
-
-                if (resolve) {
-                    resolveClass(clazz);
-                }
-
-                return clazz;
-            }
-
-            @Override
-            public final URL getResource(final String name) {
-
-                URL resource = findResource(name);
-                ClassLoader parent = this.getParent();
-                if (resource == null && parent != null) {
-                    resource = parent.getResource(name);
-                }
-
-                return resource;
-            }
-        };
+        for (URL u : urls) {
+            cl.addURL(u);
+        }
 
         Thread.currentThread().setContextClassLoader(cl);
 
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 33b31a4..8f3bb6d 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
@@ -19,6 +19,7 @@ package org.apache.sling.feature.launcher.impl;
 import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
+import java.net.URL;
 import java.util.Dictionary;
 import java.util.List;
 import java.util.Map;
@@ -94,6 +95,11 @@ class ExtensionContextImpl implements ExtensionContext {
     }
 
     @Override
+    public void addAppJar(URL jar) {
+        prepareContext.addAppJar(jar);
+    }
+
+    @Override
     public File getArtifactFile(ArtifactId artifact) throws IOException {
         return prepareContext.getArtifactFile(artifact);
     }
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 521d7da..483359e 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
@@ -17,6 +17,7 @@
 package org.apache.sling.feature.launcher.impl;
 
 import java.io.File;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.Dictionary;
 import java.util.HashMap;
@@ -44,7 +45,7 @@ public class Installation implements LauncherRunContext {
     private final List<Object[]> configurations = new ArrayList<>();
 
     /** The list of app jars. */
-    private final List<File> appJars = new ArrayList<>();
+    private final List<URL> appJars = new ArrayList<>();
 
     private volatile Logger logger;
 
@@ -52,7 +53,7 @@ public class Installation implements LauncherRunContext {
      * Add an application jar.
      * @param jar The application jar
      */
-    public void addAppJar(final File jar) {
+    public void addAppJar(final URL jar) {
         this.appJars.add(jar);
     }
 
@@ -60,7 +61,7 @@ public class Installation implements LauncherRunContext {
      * Get the list of application jars.
      * @return The list of app jars
      */
-    public List<File> getAppJars() {
+    public List<URL> getAppJars() {
         return this.appJars;
     }
 
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 91927ed..5d84dd4 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
@@ -89,6 +89,7 @@ public class FrameworkRunner extends AbstractRunner {
         if (!this.startFramework(framework, startTimeout, TimeUnit.SECONDS)) {
             throw new TimeoutException("Waited for more than " + startTimeout + " seconds to startup framework.");
         }
+        logger.info("Framework started");
 
         logger.debug("Startup took: " + (System.currentTimeMillis() - time));
 
diff --git a/src/main/java/org/apache/sling/feature/launcher/spi/Launcher.java b/src/main/java/org/apache/sling/feature/launcher/spi/Launcher.java
index 660aec0..79aa1dc 100644
--- a/src/main/java/org/apache/sling/feature/launcher/spi/Launcher.java
+++ b/src/main/java/org/apache/sling/feature/launcher/spi/Launcher.java
@@ -16,6 +16,9 @@
  */
 package org.apache.sling.feature.launcher.spi;
 
+import java.net.URL;
+import java.net.URLClassLoader;
+
 import org.apache.sling.feature.ArtifactId;
 import org.apache.sling.feature.Feature;
 
@@ -24,4 +27,59 @@ public interface Launcher {
     void prepare(LauncherPrepareContext context, ArtifactId frameworkId, Feature app) throws Exception;
 
     int run(LauncherRunContext context, ClassLoader cl) throws Exception;
+
+    default LauncherClassLoader createClassLoader() {
+        return new LauncherClassLoader();
+    }
+
+    class LauncherClassLoader extends URLClassLoader {
+        public LauncherClassLoader() {
+            super(new URL[0]);
+        }
+
+        @Override
+        public final void addURL(URL url) {
+            super.addURL(url);
+        }
+
+        @Override
+        public final Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+            // First check if it's already loaded
+            Class<?> clazz = findLoadedClass(name);
+
+            if (clazz == null) {
+
+                try {
+                    clazz = findClass(name);
+                } catch (ClassNotFoundException cnfe) {
+                    ClassLoader parent = getParent();
+                    if (parent != null) {
+                        // Ask to parent ClassLoader (can also throw a CNFE).
+                        clazz = parent.loadClass(name);
+                    } else {
+                        // Propagate exception
+                        throw cnfe;
+                    }
+                }
+            }
+
+            if (resolve) {
+                resolveClass(clazz);
+            }
+
+            return clazz;
+        }
+
+        @Override
+        public final URL getResource(final String name) {
+
+            URL resource = findResource(name);
+            ClassLoader parent = this.getParent();
+            if (resource == null && parent != null) {
+                resource = parent.getResource(name);
+            }
+
+            return resource;
+        }
+    }
 }
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 6ba3b1a..624b9fd 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
@@ -18,6 +18,7 @@ package org.apache.sling.feature.launcher.spi;
 
 import java.io.File;
 import java.io.IOException;
+import java.net.URL;
 
 import org.apache.sling.feature.ArtifactId;
 import org.slf4j.Logger;
@@ -36,5 +37,7 @@ public interface LauncherPrepareContext {
 
     void addAppJar(File jar);
 
+    void addAppJar(URL url);
+
     File getArtifactFile(ArtifactId artifact) throws IOException;
 }