incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fmesc...@apache.org
Subject svn commit: r834413 - in /sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad: app/Main.java base/app/MainDelegate.java base/shared/LauncherClassLoader.java base/shared/Loader.java webapp/SlingServlet.java
Date Tue, 10 Nov 2009 10:16:15 GMT
Author: fmeschbe
Date: Tue Nov 10 10:16:13 2009
New Revision: 834413

URL: http://svn.apache.org/viewvc?rev=834413&view=rev
Log:
SLING-1095 Ensure proper updates of the Sling launcher JAR (see issue
for full description of the changes)

Modified:
    sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/app/Main.java
    sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/app/MainDelegate.java
    sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/shared/LauncherClassLoader.java
    sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/shared/Loader.java
    sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/webapp/SlingServlet.java

Modified: sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/app/Main.java
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/app/Main.java?rev=834413&r1=834412&r2=834413&view=diff
==============================================================================
--- sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/app/Main.java (original)
+++ sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/app/Main.java Tue
Nov 10 10:16:13 2009
@@ -51,7 +51,7 @@
     // The name of the environment variable to consult to find out
     // about sling.home
     private static final String ENV_SLING_HOME = "SLING_HOME";
-    
+
     public static void main(String[] args) {
         new Main(args);
     }
@@ -60,6 +60,8 @@
 
     private final String slingHome;
 
+    private final Loader loader;
+
     private Launcher sling;
 
     private Main(String[] args) {
@@ -71,13 +73,28 @@
 
         // support usage first
         doHelp();
-        
+
         // check for control commands (might exit)
         doControlCommand();
-        
+
         // sling.home from the command line or system properties, else default
         this.slingHome = getSlingHome(commandLineArgs);
-        info("Starting Sling in " + slingHome, null);
+        File slingHomeFile = new File(slingHome);
+        if (slingHomeFile.isAbsolute()) {
+            info("Starting Sling in " + slingHome, null);
+        } else {
+            info("Starting Sling in " + slingHome + " ("
+                + slingHomeFile.getAbsolutePath() + ")", null);
+        }
+
+        // The Loader helper
+        Loader loaderTmp = null;
+        try {
+            loaderTmp = new Loader(slingHome);
+        } catch (IllegalArgumentException iae) {
+            startupFailure(iae.getMessage(), null);
+        }
+        this.loader = loaderTmp;
 
         Runtime.getRuntime().addShutdownHook(this);
 
@@ -104,7 +121,7 @@
             sling.stop();
         }
     }
-    
+
     // ---------- Notifiable interface
 
     /**
@@ -148,6 +165,13 @@
      *            used again.
      */
     public void updated(File updateFile) {
+
+        // clear the reference to the framework
+        sling = null;
+
+        // ensure we have a VM as clean as possible
+        loader.cleanupVM();
+
         if (updateFile == null) {
 
             info("Restarting Framework and Sling", null);
@@ -186,30 +210,28 @@
         if (launcherJar != null) {
             try {
                 info("Checking launcher JAR in " + slingHome, null);
-                if (Loader.installLauncherJar(launcherJar, slingHome)) {
+                if (loader.installLauncherJar(launcherJar)) {
                     info("Installed or Updated launcher JAR file from "
                         + launcherJar, null);
                 } else {
                     info("Existing launcher JAR file already up to date", null);
                 }
             } catch (IOException ioe) {
-                error("Failed installing " + launcherJar, ioe);
+                startupFailure("Failed installing " + launcherJar, ioe);
             }
         } else {
             info("No Launcher JAR to install", null);
         }
 
-        Object object;
+        Object object = null;
         try {
             info(
                 "Loading launcher class " + SharedConstants.DEFAULT_SLING_MAIN,
                 null);
-            object = Loader.loadLauncher(SharedConstants.DEFAULT_SLING_MAIN,
-                slingHome);
+            object = loader.loadLauncher(SharedConstants.DEFAULT_SLING_MAIN);
         } catch (IllegalArgumentException iae) {
-            error("Failed loading Sling class "
+            startupFailure("Failed loading Sling class "
                 + SharedConstants.DEFAULT_SLING_MAIN, iae);
-            return;
         }
 
         if (object instanceof Launcher) {
@@ -246,9 +268,9 @@
      * <tr><td>-y -z</td><td>y -> y, z -> z</td></tr>
      * <tr><td>-y x - -z a</td><td>y -> x, -z -> -z, a ->
a</td></tr>
      * </table>
-     * 
+     *
      * @param args The command line to parse
-     * 
+     *
      * @return The map of command line options and their values
      */
     static Map<String, String> parseCommandLine(String[] args) {
@@ -256,7 +278,7 @@
         boolean readUnparsed = false;
         for (int argc = 0; args != null && argc < args.length; argc++) {
             String arg = args[argc];
-            
+
             if (readUnparsed) {
                 commandLine.put(arg, arg);
             } else if (arg.startsWith("-")) {
@@ -283,7 +305,7 @@
         }
         return commandLine;
     }
-    
+
     /**
      * Define the sling.home parameter implementing the algorithme defined on
      * the wiki page to find the setting according to this algorithm:
@@ -302,28 +324,28 @@
 
         String slingHome = commandLine.get("c");
         if (slingHome != null) {
-            
+
             source = "command line";
 
         } else {
-            
+
             slingHome = System.getProperty(SharedConstants.SLING_HOME);
             if (slingHome != null) {
-                
+
                 source = "system property sling.home";
-                
+
             } else {
-                
+
                 slingHome = System.getenv(ENV_SLING_HOME);
                 if (slingHome != null) {
-                    
+
                     source = "environment variable SLING_HOME";
-                    
+
                 } else {
-                    
+
                     source = "default";
                     slingHome = SharedConstants.SLING_HOME_DEFAULT;
-                    
+
                 }
             }
         }
@@ -332,6 +354,12 @@
         return slingHome;
     }
 
+    private void startupFailure(String message, Throwable cause) {
+        error("Launcher JAR access failure: " + message, cause);
+        error("Shutting Down", null);
+        System.exit(1);
+    }
+
     // ---------- logging
 
     // emit an informational message to standard out
@@ -383,7 +411,7 @@
             System.out.println("usage: "
                 + Main.class.getName()
                 + " [ start | stop | status ] [ -j adr ] [ -l loglevel ] [ -f logfile ] [
-c slinghome ] [ -a address ] [ -p port ] [ -h ]");
-    
+
             System.out.println("    start         listen for control connection (uses -j)");
             System.out.println("    stop          terminate running Sling (uses -j)");
             System.out.println("    start         check whether Sling is running (uses-j)");
@@ -394,11 +422,11 @@
             System.out.println("    -a address    the interfact to bind to (use 0.0.0.0 for
any) (not supported yet)");
             System.out.println("    -p port       the port to listen to (default 8080)");
             System.out.println("    -h            prints this usage message");
-    
+
             System.exit(0);
         }
     }
-    
+
     private void doControlCommand() {
         String commandSocketSpec = commandLineArgs.remove("j");
         if ("j".equals(commandSocketSpec)) {

Modified: sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/app/MainDelegate.java
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/app/MainDelegate.java?rev=834413&r1=834412&r2=834413&view=diff
==============================================================================
--- sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/app/MainDelegate.java
(original)
+++ sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/app/MainDelegate.java
Tue Nov 10 10:16:13 2009
@@ -158,7 +158,7 @@
 
         try {
             ResourceProvider resProvider = new ClassLoaderResourceProvider(
-                MainDelegate.class.getClassLoader());
+                getClass().getClassLoader());
 
             // creating the instance launches the framework and we are done here
             // ..

Modified: sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/shared/LauncherClassLoader.java
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/shared/LauncherClassLoader.java?rev=834413&r1=834412&r2=834413&view=diff
==============================================================================
--- sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/shared/LauncherClassLoader.java
(original)
+++ sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/shared/LauncherClassLoader.java
Tue Nov 10 10:16:13 2009
@@ -74,7 +74,7 @@
     private final Set<String> launcherPackages;
 
     LauncherClassLoader(File launcherJar) throws MalformedURLException {
-        super(new URL[] { launcherJar.toURL() },
+        super(new URL[] { launcherJar.toURI().toURL() },
             LauncherClassLoader.class.getClassLoader());
 
         Set<String> collectedPackages = new HashSet<String>();
@@ -171,7 +171,7 @@
      * <p>
      * Example: Called for <i>org.osgi.framework.Bundle</i> this method returns
      * <i>org.osgi.framework</i>.
-     * 
+     *
      * @param name The fully qualified name of the class or resource to check
      * @param separator The separator for package segments
      */
@@ -183,7 +183,7 @@
     /**
      * Returns <code>true</code> if the launcher JAR file provides the package
      * to which the named class or resource belongs.
-     * 
+     *
      * @param name The fully qualified name of the class or resource to check
      * @param separator The separator for package segments
      */

Modified: sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/shared/Loader.java
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/shared/Loader.java?rev=834413&r1=834412&r2=834413&view=diff
==============================================================================
--- sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/shared/Loader.java
(original)
+++ sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/shared/Loader.java
Tue Nov 10 10:16:13 2009
@@ -20,13 +20,17 @@
 
 import java.beans.Introspector;
 import java.io.File;
+import java.io.FileFilter;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.net.JarURLConnection;
 import java.net.MalformedURLException;
+import java.net.URI;
 import java.net.URL;
 import java.net.URLConnection;
+import java.util.jar.JarFile;
 
 /**
  * The <code>Loader</code> class provides utility methods for the actual
@@ -35,6 +39,36 @@
 public class Loader {
 
     /**
+     * The Sling home folder set by the constructor
+     */
+    private final File slingHome;
+
+    /**
+     * The current launcher JAR file in use. Set on-demand by the
+     * {@link #getLauncherJarFile()} method and reset to the installed or
+     * updated launcher JAR file by the {@link #installLauncherJar(URL)} method.
+     */
+    private File launcherJarFile;
+
+    /**
+     * Creates a loader instance to load from the given Sling home folder.
+     * Besides ensuring the existence of the Sling home folder, the constructor
+     * also removes all but the most recent launcher JAR files from the Sling
+     * home folder (thus cleaning up from previous upgrades).
+     *
+     * @param slingHome The Sling home folder. If this is <code>null</code> the
+     *            default value {@link SharedConstants#SLING_HOME_DEFAULT} is
+     *            assumed.
+     * @throws IllegalArgumentException If the Sling home folder exists but is
+     *             not a directory or if the Sling home folder cannot be
+     *             created.
+     */
+    public Loader(final String slingHome) throws IllegalArgumentException {
+        this.slingHome = getSlingHomeFile(slingHome);
+        removeOldLauncherJars();
+    }
+
+    /**
      * Creates an URLClassLoader from a _launcher JAR_ file in the given
      * slingHome directory and loads and returns the launcher class identified
      * by the launcherClassName.
@@ -52,15 +86,15 @@
      *             instantiated. The cause of the failure is contained as the
      *             cause of the exception.
      */
-    public static Object loadLauncher(String launcherClassName, String slingHome) {
+    public Object loadLauncher(String launcherClassName) {
 
-        File launcherJarFile = getLauncherJarFile(slingHome);
+        final File launcherJarFile = getLauncherJarFile();
         if (!launcherJarFile.canRead()) {
             throw new IllegalArgumentException("Sling Launcher JAR "
                 + launcherJarFile + " is not accessible");
         }
 
-        ClassLoader loader;
+        final ClassLoader loader;
         try {
             loader = new LauncherClassLoader(launcherJarFile);
         } catch (MalformedURLException e) {
@@ -69,7 +103,7 @@
         }
 
         try {
-            Class<?> launcherClass = loader.loadClass(launcherClassName);
+            final Class<?> launcherClass = loader.loadClass(launcherClassName);
             return launcherClass.newInstance();
         } catch (ClassNotFoundException cnfe) {
             throw new IllegalArgumentException("Cannot find class "
@@ -88,16 +122,23 @@
      * Java VM as possible. Most notably the following traces are removed:
      * <ul>
      * <li>JavaBeans property caches
+     * <li>Close the Launcher Jar File (if opened by the platform)
      * </ul>
      * <p>
      * This method must be called when the notifier is called.
+     *
+     * @param slingHome The home directory of Sling. This is used to ensure the
+     *            launcher jar file is not open anymore (as much as possible).
      */
-    public static void cleanupVM() {
+    public void cleanupVM() {
 
         // ensure the JavaBeans introspector lets go of any classes it
         // may haved cached after introspection
         Introspector.flushCaches();
 
+        // if sling home is set, check whether we have to close the
+        // launcher JAR JarFile, which might be cached in the platform
+        closeLauncherJarFile(getLauncherJarFile());
     }
 
     /**
@@ -111,27 +152,82 @@
      *         <code>false</code> is returned.
      * @throws IOException If an error occurrs transferring the contents
      */
-    public static boolean installLauncherJar(URL launcherJar, String slingHome)
-            throws IOException {
-        File launcherJarDestFile = getLauncherJarFile(slingHome);
+    public boolean installLauncherJar(URL launcherJar) throws IOException {
+        final File currentLauncherJarFile = getLauncherJarFile();
 
         // check whether we have to overwrite
-        URLConnection launcherJarConn = launcherJar.openConnection();
-        long lastModifTime = launcherJarConn.getLastModified();
-        if (launcherJarDestFile.exists()) {
-            if (lastModifTime <= launcherJarDestFile.lastModified()) {
+        final URLConnection launcherJarConn = launcherJar.openConnection();
+        launcherJarConn.setUseCaches(false);
+        final long lastModifTime = launcherJarConn.getLastModified();
+        final File newLauncherJarFile;
+        if (currentLauncherJarFile.exists()) {
+
+            // nothing to do if there is no update
+            if (lastModifTime <= currentLauncherJarFile.lastModified()) {
                 return false;
             }
-            launcherJarDestFile.delete();
+
+            // use a new timestamped name for the new version
+            newLauncherJarFile = new File(slingHome,
+                SharedConstants.LAUNCHER_JAR_REL_PATH + "." + lastModifTime);
+
+        } else {
+
+            // create the current file
+            newLauncherJarFile = currentLauncherJarFile;
+
         }
 
-        spool(launcherJarConn.getInputStream(), launcherJarDestFile);
+        // store the new launcher JAR and set the last modification time
+        spool(launcherJarConn.getInputStream(), newLauncherJarFile);
+        newLauncherJarFile.setLastModified(lastModifTime);
+        launcherJarFile = newLauncherJarFile;
 
-        launcherJarDestFile.setLastModified(lastModifTime);
         return true;
     }
 
     /**
+     * Removes old candidate launcher JAR files leaving the most recent one as
+     * the launcher JAR file to use on next Sling startup.
+     *
+     * @param slingHome The Sling home directory location containing the
+     *            candidate launcher JAR files.
+     */
+    private void removeOldLauncherJars() {
+        final File[] launcherJars = getLauncherJarFiles();
+        if (launcherJars != null && launcherJars.length > 0) {
+
+            // start with the first entry being the newest
+            File mostRecentJarFile = launcherJars[0];
+            long mostRecentLastModification = mostRecentJarFile.lastModified();
+            for (int i = 1; i < launcherJars.length; i++) {
+
+                if (mostRecentLastModification < launcherJars[i].lastModified()) {
+                    // if this entry is newer than the fromer newest, remove
+                    // the former file and use this entry as the newest
+                    mostRecentJarFile.delete();
+                    mostRecentJarFile = launcherJars[i];
+                    mostRecentLastModification = mostRecentJarFile.lastModified();
+
+                } else {
+                    // otherwise remove this entry and keep on using the current
+                    launcherJars[i].delete();
+                }
+
+            }
+            // fact: mostRecentJarFile is the only remaining and the most recent
+
+            // ensure the most recent file has the common name
+            if (!SharedConstants.LAUNCHER_JAR_REL_PATH.equals(mostRecentJarFile.getName()))
{
+                File launcherFileName = new File(
+                    mostRecentJarFile.getParentFile(),
+                    SharedConstants.LAUNCHER_JAR_REL_PATH);
+                mostRecentJarFile.renameTo(launcherFileName);
+            }
+        }
+    }
+
+    /**
      * Spools the contents of the input stream to the given file replacing the
      * contents of the file with the contents of the input stream. When this
      * method returns, the input stream is guaranteed to be closed.
@@ -164,14 +260,84 @@
         }
     }
 
+    // ---------- internal helper
+
     /**
      * Returns a <code>File</code> object representing the Launcher JAR file
      * found in the sling home folder.
+     */
+    private File getLauncherJarFile() {
+        if (launcherJarFile == null) {
+            final File[] launcherJars = getLauncherJarFiles();
+            if (launcherJars == null || launcherJars.length == 0) {
+
+                // return a non-existing file naming the desired primary name
+                launcherJarFile = new File(slingHome,
+                    SharedConstants.LAUNCHER_JAR_REL_PATH);
+
+            } else if (launcherJars.length == 1) {
+
+                // only a single file existing, that's it
+                launcherJarFile = launcherJars[0];
+
+            } else {
+
+                // start with the first entry being the newest
+                File mostRecentJarFile = launcherJars[0];
+                long mostRecentLastModification = mostRecentJarFile.lastModified();
+                for (int i = 1; i < launcherJars.length; i++) {
+
+                    // if this entry is newer than the fromer newest, use this
+                    // entry
+                    // as the newest
+                    if (mostRecentLastModification < launcherJars[i].lastModified()) {
+                        mostRecentJarFile = launcherJars[i];
+                        mostRecentLastModification = mostRecentJarFile.lastModified();
+                    }
+
+                }
+                launcherJarFile = mostRecentJarFile;
+            }
+        }
+
+        return launcherJarFile;
+    }
+
+    /**
+     * Returns all files in the <code>slingHome</code> directory which may be
+     * considered as launcher JAR files. These files all start with the
+     * {@link SharedConstants#LAUNCHER_JAR_REL_PATH}. This list may be empty if
+     * the launcher JAR file has not been installed yet.
+     *
+     * @param slingHome The sling home directory where the launcher JAR files
+     *            are stored
+     * @return The list of candidate launcher JAR files, which may be empty.
+     *         <code>null</code> is returned if an IO error occurrs trying to
+     *         list the files.
+     */
+    private File[] getLauncherJarFiles() {
+        return slingHome.listFiles(new FileFilter() {
+            public boolean accept(File pathname) {
+                return pathname.isFile()
+                    && pathname.getName().startsWith(
+                        SharedConstants.LAUNCHER_JAR_REL_PATH);
+            }
+        });
+    }
+
+    /**
+     * Returns the <code>slingHome</code> path as a directory. If the directory
+     * does not exist it is created. If creation fails or if
+     * <code>slingHome</code> exists but is not a directory a
+     * <code>IllegalArgumentException</code> is thrown.
      *
-     * @throws IllegalArgumentException if the sling home folder cannot be
-     *             created or exists as a non-directory filesystem entry.
+     * @param slingHome The sling home directory where the launcher JAR files
+     *            are stored
+     * @return The Sling home directory
+     * @throws IllegalArgumentException if <code>slingHome</code> exists and
is
+     *             not a directory or cannot be created as a directory.
      */
-    private static File getLauncherJarFile(String slingHome) {
+    private static File getSlingHomeFile(String slingHome) {
         if (slingHome == null) {
             slingHome = SharedConstants.SLING_HOME_DEFAULT;
         }
@@ -187,6 +353,20 @@
                 + " cannot be created as a directory");
         }
 
-        return new File(slingDir, SharedConstants.LAUNCHER_JAR_REL_PATH);
+        return slingDir;
+    }
+
+    private static void closeLauncherJarFile(final File launcherJar) {
+        try {
+            final URI launcherJarUri = launcherJar.toURI();
+            final URL launcherJarRoot = new URL("jar:" + launcherJarUri + "!/");
+            final URLConnection conn = launcherJarRoot.openConnection();
+            if (conn instanceof JarURLConnection) {
+                final JarFile jarFile = ((JarURLConnection) conn).getJarFile();
+                jarFile.close();
+            }
+        } catch (Exception e) {
+            // better logging here
+        }
     }
 }

Modified: sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/webapp/SlingServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/webapp/SlingServlet.java?rev=834413&r1=834412&r2=834413&view=diff
==============================================================================
--- sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/webapp/SlingServlet.java
(original)
+++ sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/webapp/SlingServlet.java
Tue Nov 10 10:16:13 2009
@@ -45,7 +45,7 @@
  * <p>
  * This class goes into the secondary artifact with the classifier <i>webapp</i>
  * to be used as the main servlet to be registered in the servlet container.
- * 
+ *
  * @see <a href="http://cwiki.apache.org/SLING/the-sling-launchpad.html">The
  *      Sling Launchpad</a>
  */
@@ -61,6 +61,8 @@
 
     private String slingHome;
 
+    private Loader loader;
+
     private Servlet sling;
 
     /**
@@ -149,6 +151,11 @@
         if (sling != null) {
             sling.destroy();
         }
+
+        // clear fields
+        slingHome = null;
+        loader = null;
+        sling = null;
     }
 
     // ---------- Notifiable interface
@@ -183,7 +190,7 @@
      * If an <code>InputStream</code> was provided, this has been copied to a
      * temporary file, which will be used in place of the existing launcher jar
      * file.
-     * 
+     *
      * @param updateFile The temporary file to replace the existing launcher jar
      *            file. If <code>null</code> the existing launcher jar will be
      *            used again.
@@ -197,6 +204,9 @@
             }
         }
 
+        // ensure we have a VM as clean as possible
+        loader.cleanupVM();
+
         if (updateFile == null) {
 
             log("Restarting Framework and Sling");
@@ -243,6 +253,14 @@
      * {@link #init()} to install the launcher jar and actually start sling.
      */
     private void startSling() {
+
+        try {
+            this.loader = new Loader(slingHome);
+        } catch (IllegalArgumentException iae) {
+            startupFailure(null, iae);
+            return;
+        }
+
         try {
             URL launcherJar = getServletContext().getResource(
                 SharedConstants.DEFAULT_SLING_LAUNCHER_JAR);
@@ -278,27 +296,26 @@
         if (launcherJar != null) {
             try {
                 log("Checking launcher JAR in " + slingHome);
-                if (Loader.installLauncherJar(launcherJar, slingHome)) {
+                if (loader.installLauncherJar(launcherJar)) {
                     log("Installed or Updated launcher JAR file from " + launcherJar);
                 } else {
                     log("Existing launcher JAR file is already up to date");
                 }
             } catch (IOException ioe) {
-                log("Failed installing " + launcherJar, ioe);
+                startupFailure("Failed installing " + launcherJar, ioe);
+                return;
             }
         } else {
             log("No Launcher JAR to install");
         }
 
-        Object object = Loader.loadLauncher(
-            SharedConstants.DEFAULT_SLING_SERVLET, slingHome);
+        Object object = null;
         try {
             log("Loading launcher class "
                 + SharedConstants.DEFAULT_SLING_SERVLET);
-            object = Loader.loadLauncher(SharedConstants.DEFAULT_SLING_SERVLET,
-                slingHome);
+            object = loader.loadLauncher(SharedConstants.DEFAULT_SLING_SERVLET);
         } catch (IllegalArgumentException iae) {
-            log("Cannot load Launcher Servlet "
+            startupFailure("Cannot load Launcher Servlet "
                 + SharedConstants.DEFAULT_SLING_SERVLET, iae);
             return;
         }
@@ -319,13 +336,7 @@
                 this.startFailureCounter = 0;
                 log("Startup completed");
             } catch (ServletException se) {
-                Throwable cause = se.getCause();
-                if (cause == null) {
-                    cause = se;
-                }
-
-                log("Failed to start Sling in " + slingHome, cause);
-                startFailureCounter++;
+                startupFailure(null, se);
             }
         }
 
@@ -349,7 +360,7 @@
      * does not provide the Servlet API 2.5
      * <code>ServletContext.getContextPath()</code> method and the
      * <code>request</code> parameter is <code>null</code>.
-     * 
+     *
      * @param args The command line arguments
      * @return The value to use for sling.home or <code>null</code> if the value
      *         cannot be retrieved.
@@ -417,4 +428,25 @@
         return prefix + contextPath.replace('/', '_');
     }
 
+    private void startupFailure(String message, Throwable cause) {
+
+        // ensure message
+        if (message == null) {
+            message = "Failed to start Sling in " + slingHome;
+        }
+
+        // unwrap to get the real cause
+        while (cause.getCause() != null) {
+            cause = cause.getCause();
+        }
+
+        // log it now and increase the failure counter
+        log(message, cause);
+        startFailureCounter++;
+
+        // ensure the startingSling fields is not set
+        synchronized (this) {
+            startingSling = null;
+        }
+    }
 }



Mime
View raw message