Author: bdelacretaz Date: Fri Jan 8 10:13:21 2010 New Revision: 897151 URL: http://svn.apache.org/viewvc?rev=897151&view=rev Log: SLING-1273 - use BundleVersionInfo comparator to select most recent launcher jar file
Modified: sling/trunk/launchpad/base/pom.xml 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/shared/Loader.java sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/webapp/SlingServlet.java sling/trunk/launchpad/builder/src/main/bundles/list.xml sling/trunk/launchpad/bundles/pom.xml Modified: sling/trunk/launchpad/base/pom.xml URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/base/pom.xml?rev=897151&r1=897150&r2=897151&view=diff ============================================================================== --- sling/trunk/launchpad/base/pom.xml (original) +++ sling/trunk/launchpad/base/pom.xml Fri Jan 8 10:13:21 2010 @@ -97,6 +97,34 @@ </outputDirectory> </configuration> </execution> + <!-- Embed code from osgi.commons --> + <execution> + <id>extract-sling-commons-osgi</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <configuration> + <includeArtifactIds>org.apache.sling.commons.osgi</includeArtifactIds> + <excludeTransitive>true</excludeTransitive> + <outputDirectory> + ${project.build.directory}/classes + </outputDirectory> + </configuration> + </execution> + <!-- Embed osgi Version class from framework--> + <execution> + <id>extract-osgi-framework</id> + <goals> + <goal>unpack-dependencies</goal> + </goals> + <configuration> + <includeArtifactIds>org.apache.felix.framework</includeArtifactIds> + <excludeTransitive>true</excludeTransitive> + <outputDirectory> + ${project.build.directory}/classes + </outputDirectory> + </configuration> + </execution> </executions> </plugin> <plugin> @@ -123,6 +151,8 @@ <includes> <include>org/apache/sling/launchpad/base/shared/**</include> <include>org/apache/sling/launchpad/app/**</include> + <include>org/apache/sling/commons/osgi/**</include> + <include>org/osgi/framework/Version*</include> <include>META-INF/**</include> </includes> </configuration> @@ -151,6 +181,8 @@ META-INF/**, WEB-INF/classes/org/apache/sling/launchpad/base/shared/**, WEB-INF/classes/org/apache/sling/launchpad/webapp/**, + WEB-INF/classes/org/apache/sling/commons/osgi/**, + WEB-INF/classes/org/osgi/framework/Version*, WEB-INF/resources/** </packagingIncludes> <webResources> @@ -220,6 +252,12 @@ <scope>provided</scope> </dependency> <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.commons.osgi</artifactId> + <version>2.0.5-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> 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=897151&r1=897150&r2=897151&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 Fri Jan 8 10:13:21 2010 @@ -90,7 +90,12 @@ // The Loader helper Loader loaderTmp = null; try { - loaderTmp = new Loader(slingHome); + loaderTmp = new Loader(slingHome) { + @Override + protected void info(String msg) { + Main.info(msg, null); + } + }; } catch (IllegalArgumentException iae) { startupFailure(iae.getMessage(), null); } @@ -209,13 +214,8 @@ private void startSling(URL launcherJar) { if (launcherJar != null) { try { - info("Checking launcher JAR in " + slingHome, null); - 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); - } + info("Checking launcher JAR in folder " + slingHome, null); + loader.installLauncherJar(launcherJar); } catch (IOException ioe) { startupFailure("Failed installing " + launcherJar, ioe); } @@ -225,9 +225,6 @@ Object object = null; try { - info( - "Loading launcher class " + SharedConstants.DEFAULT_SLING_MAIN, - null); object = loader.loadLauncher(SharedConstants.DEFAULT_SLING_MAIN); } catch (IllegalArgumentException iae) { startupFailure("Failed loading Sling class " 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=897151&r1=897150&r2=897151&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 Fri Jan 8 10:13:21 2010 @@ -30,8 +30,15 @@ import java.net.URI; import java.net.URL; import java.net.URLConnection; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; import java.util.jar.JarFile; +import org.apache.sling.commons.osgi.bundleversion.BundleVersionInfo; +import org.apache.sling.commons.osgi.bundleversion.FileBundleVersionInfo; + /** * The <code>Loader</code> class provides utility methods for the actual * launchers to help launching the framework. @@ -44,13 +51,6 @@ 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 @@ -85,6 +85,7 @@ public Object loadLauncher(String launcherClassName) { final File launcherJarFile = getLauncherJarFile(); + info("Loading launcher class " + launcherClassName + " from " + launcherJarFile.getName()); if (!launcherJarFile.canRead()) { throw new IllegalArgumentException("Sling Launcher JAR " + launcherJarFile + " is not accessible"); @@ -137,47 +138,76 @@ /** * Copies the contents of the launcher JAR as indicated by the URL to the - * sling home directory and sets the last modification time stamp fo the - * file. If the existing file is not older than the contents of the launcher - * JAR file, the file is not replaced. + * sling home directory. If the existing file is is a more recent bundle version + * than the supplied launcher JAR file, it is is not replaced. * * @return <code>true</code> if the launcher JAR file has been installed or - * updated. If the launcher JAR is already up to date, - * <code>false</code> is returned. + * updated, <code>false</code> otherwise. * @throws IOException If an error occurrs transferring the contents */ public boolean installLauncherJar(URL launcherJar) throws IOException { final File currentLauncherJarFile = getLauncherJarFile(); - // check whether we have to overwrite + // Copy the new launcher jar to a temporary file, and + // extract bundle version info 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; + final File tmp = new File(slingHome, "Loader_tmp_" + System.currentTimeMillis() + SharedConstants.LAUNCHER_JAR_REL_PATH); + spool(launcherJarConn.getInputStream(), tmp); + final FileBundleVersionInfo newVi = new FileBundleVersionInfo(tmp); + boolean installNewLauncher = true; + + try { + if(!newVi.isBundle()) { + throw new IllegalArgumentException("New launcher jar is not a bundle, cannot get version info:" + launcherJar); } + + // Compare versions to decide whether to use the existing or new launcher jar + if (currentLauncherJarFile.exists()) { + final FileBundleVersionInfo currentVi = new FileBundleVersionInfo(currentLauncherJarFile); + if(!currentVi.isBundle()) { + throw new IllegalArgumentException("Existing launcher jar is not a bundle, cannot get version info:" + + currentLauncherJarFile.getAbsolutePath()); + } - // 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; + String info = null; + if(currentVi.compareTo(newVi) == 0) { + info = "up to date"; + installNewLauncher = false; + } else if(currentVi.compareTo(newVi) > 0) { + info = "more recent than ours"; + installNewLauncher = false; + } + + if(info != null) { + info("Existing launcher is " + info + ", using it: " + + getBundleInfo(currentVi) + " (" + currentLauncherJarFile.getName() + ")"); + } + } + if(installNewLauncher) { + final File f = new File(tmp.getParentFile(), SharedConstants.LAUNCHER_JAR_REL_PATH + "." + System.currentTimeMillis()); + tmp.renameTo(f); + info("Installing new launcher: " + launcherJar + ", " + getBundleInfo(newVi) + " (" + f.getName() + ")"); + } + } finally { + if(tmp.exists()) { + tmp.delete(); + } } - // store the new launcher JAR and set the last modification time - spool(launcherJarConn.getInputStream(), newLauncherJarFile); - newLauncherJarFile.setLastModified(lastModifTime); - launcherJarFile = newLauncherJarFile; - - return true; + return installNewLauncher; + } + + /** Return relevant bundle version info for logging */ + static String getBundleInfo(BundleVersionInfo<?> v) { + final StringBuilder sb = new StringBuilder(); + sb.append(v.getVersion()); + if(v.isSnapshot()) { + sb.append(", Last-Modified:"); + sb.append(new Date(v.getBundleLastModified())); + } + return sb.toString(); } /** @@ -190,33 +220,31 @@ 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(); + + // Remove all files except current one + final File current = getLauncherJarFile(); + for(File f : launcherJars) { + if(f.getAbsolutePath().equals(current.getAbsolutePath())) { + continue; } - + String versionInfo = null; + try { + FileBundleVersionInfo vi = new FileBundleVersionInfo(f); + versionInfo = getBundleInfo(vi); + } catch(IOException ignored) { + } + info("Deleting obsolete launcher jar: " + f.getName() + ", " + versionInfo); + f.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())) { + // And ensure the current file has the standard launcher name + if (!SharedConstants.LAUNCHER_JAR_REL_PATH.equals(current.getName())) { + info("Renaming current launcher jar " + current.getName() + + " to " + SharedConstants.LAUNCHER_JAR_REL_PATH); File launcherFileName = new File( - mostRecentJarFile.getParentFile(), + current.getParentFile(), SharedConstants.LAUNCHER_JAR_REL_PATH); - mostRecentJarFile.renameTo(launcherFileName); + current.renameTo(launcherFileName); } } } @@ -261,62 +289,67 @@ * 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 { + File result = null; + 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 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(); - } + // return a non-existing file naming the desired primary name + result = new File(slingHome, + SharedConstants.LAUNCHER_JAR_REL_PATH); - } - launcherJarFile = mostRecentJarFile; - } + } else { + // last file is the most recent one, use it + result = launcherJars[launcherJars.length - 1]; } - return launcherJarFile; + return result; } /** * Returns all files in the <code>slingHome</code> directory which may be - * considered as launcher JAR files. These files all start with the + * considered as launcher JAR files, sorted based on their bundle version + * information, most recent last. 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 + * <code>null</code> is returned if an IO error occurs trying to * list the files. */ private File[] getLauncherJarFiles() { - return slingHome.listFiles(new FileFilter() { + // Get list of files with names starting with our prefix + final File[] rawList = slingHome.listFiles(new FileFilter() { public boolean accept(File pathname) { return pathname.isFile() && pathname.getName().startsWith( SharedConstants.LAUNCHER_JAR_REL_PATH); } }); + + // Keep only those which have valid Bundle headers, and + // sort them according to the bundle version numbers + final List<FileBundleVersionInfo> list = new ArrayList<FileBundleVersionInfo>(); + for(File f : rawList) { + FileBundleVersionInfo fvi = null; + try { + fvi = new FileBundleVersionInfo(f); + } catch(IOException ioe) { + // Cannot read bundle info from jar file - should never happen?? + throw new IllegalStateException("Cannot read bundle information from loader file " + f.getAbsolutePath()); + } + if(fvi.isBundle()) { + list.add(fvi); + } + } + Collections.sort(list); + final File [] result = new File[list.size()]; + int i = 0; + for(FileBundleVersionInfo fvi : list) { + result[i++] = fvi.getSource(); + } + return result; } /** @@ -363,4 +396,8 @@ // better logging here } } + + /** Meant to be overridden to display or log info */ + protected void info(String msg) { + } } 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=897151&r1=897150&r2=897151&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 Fri Jan 8 10:13:21 2010 @@ -49,6 +49,7 @@ * @see <a href="http://cwiki.apache.org/SLING/the-sling-launchpad.html">The * Sling Launchpad</a> */ +...@suppresswarnings("serial") public class SlingServlet extends GenericServlet implements Notifiable { /** @@ -255,7 +256,12 @@ private void startSling() { try { - this.loader = new Loader(slingHome); + this.loader = new Loader(slingHome) { + @Override + protected void info(String msg) { + log(msg); + } + }; } catch (IllegalArgumentException iae) { startupFailure(null, iae); return; @@ -296,11 +302,7 @@ if (launcherJar != null) { try { log("Checking launcher JAR in " + 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"); - } + loader.installLauncherJar(launcherJar); } catch (IOException ioe) { startupFailure("Failed installing " + launcherJar, ioe); return; @@ -311,8 +313,6 @@ Object object = null; try { - log("Loading launcher class " - + SharedConstants.DEFAULT_SLING_SERVLET); object = loader.loadLauncher(SharedConstants.DEFAULT_SLING_SERVLET); } catch (IllegalArgumentException iae) { startupFailure("Cannot load Launcher Servlet " Modified: sling/trunk/launchpad/builder/src/main/bundles/list.xml URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/builder/src/main/bundles/list.xml?rev=897151&r1=897150&r2=897151&view=diff ============================================================================== --- sling/trunk/launchpad/builder/src/main/bundles/list.xml (original) +++ sling/trunk/launchpad/builder/src/main/bundles/list.xml Fri Jan 8 10:13:21 2010 @@ -19,7 +19,7 @@ <bundle> <groupId>org.apache.sling</groupId> <artifactId>org.apache.sling.commons.osgi</artifactId> - <version>2.0.4-incubator</version> + <version>2.0.5-SNAPSHOT</version> </bundle> <bundle> <groupId>org.apache.sling</groupId> Modified: sling/trunk/launchpad/bundles/pom.xml URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/bundles/pom.xml?rev=897151&r1=897150&r2=897151&view=diff ============================================================================== --- sling/trunk/launchpad/bundles/pom.xml (original) +++ sling/trunk/launchpad/bundles/pom.xml Fri Jan 8 10:13:21 2010 @@ -216,7 +216,7 @@ <dependency> <groupId>org.apache.sling</groupId> <artifactId>org.apache.sling.commons.osgi</artifactId> - <version>2.0.4-incubator</version> + <version>2.0.5-SNAPSHOT</version> <scope>provided</scope> </dependency> <dependency>