Return-Path: Delivered-To: apmail-felix-commits-archive@www.apache.org Received: (qmail 53937 invoked from network); 15 Oct 2009 10:14:54 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 15 Oct 2009 10:14:54 -0000 Received: (qmail 33370 invoked by uid 500); 15 Oct 2009 10:14:53 -0000 Delivered-To: apmail-felix-commits-archive@felix.apache.org Received: (qmail 33308 invoked by uid 500); 15 Oct 2009 10:14:53 -0000 Mailing-List: contact commits-help@felix.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@felix.apache.org Delivered-To: mailing list commits@felix.apache.org Received: (qmail 33299 invoked by uid 99); 15 Oct 2009 10:14:53 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 15 Oct 2009 10:14:53 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 15 Oct 2009 10:14:51 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 82E3423888D0; Thu, 15 Oct 2009 10:14:29 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r825454 - in /felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal: DirectoryWatcher.java Util.java Date: Thu, 15 Oct 2009 10:14:29 -0000 To: commits@felix.apache.org From: gnodet@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20091015101429.82E3423888D0@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: gnodet Date: Thu Oct 15 10:14:29 2009 New Revision: 825454 URL: http://svn.apache.org/viewvc?rev=825454&view=rev Log: FELIX-1756: allow fileinstall to override (i.e. update) bundles that have not been deployed by fileinstall initially Also fixes FELIX-1386: updating fileinstall bundle in watched directory causes IllegalStateException Modified: felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/Util.java Modified: felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java URL: http://svn.apache.org/viewvc/felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java?rev=825454&r1=825453&r2=825454&view=diff ============================================================================== --- felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java (original) +++ felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/DirectoryWatcher.java Thu Oct 15 10:14:29 2009 @@ -18,6 +18,7 @@ */ package org.apache.felix.fileinstall.internal; +import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FilenameFilter; @@ -36,6 +37,8 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.jar.JarInputStream; +import java.util.jar.Manifest; import org.apache.felix.fileinstall.ArtifactInstaller; import org.apache.felix.fileinstall.ArtifactListener; @@ -47,6 +50,7 @@ import org.osgi.framework.BundleException; import org.osgi.framework.BundleListener; import org.osgi.framework.Constants; +import org.osgi.framework.Version; import org.osgi.service.packageadmin.PackageAdmin; /** @@ -197,6 +201,15 @@ } catch (Throwable e) { + try + { + context.getBundle(); + } + catch (IllegalStateException t) + { + // FileInstall bundle has been uninstalled, exiting loop + return; + } log("In main loop, we have serious trouble", e); } } @@ -599,10 +612,6 @@ Map /**/ checksums = new HashMap/**/(); for (int i = 0; i < bundles.length; i++) { - Artifact artifact = new Artifact(); - artifact.setBundleId(bundles[i].getBundleId()); - artifact.setChecksum(Util.loadChecksum(bundles[i], context)); - artifact.setListener(null); // Convert to a URI because the location of a bundle // is typically a URI. At least, that's the case for // autostart bundles and bundles installed by fileinstall. @@ -633,10 +642,14 @@ // We can't do any meaningful processing for this bundle. continue; } - artifact.setPath(new File(path)); final int index = path.lastIndexOf('/'); if (index != -1 && path.startsWith(watchedDirPath)) { + Artifact artifact = new Artifact(); + artifact.setBundleId(bundles[i].getBundleId()); + artifact.setChecksum(Util.loadChecksum(bundles[i], context)); + artifact.setListener(null); + artifact.setPath(new File(path)); currentManagedArtifacts.put(new File(path), artifact); checksums.put(new File(path), new Long(artifact.getChecksum())); } @@ -659,7 +672,6 @@ if (bundle != null) { bundles.add(bundle); - Util.storeChecksum(bundle, artifact.getChecksum(), context); } } return bundles; @@ -701,7 +713,6 @@ if (bundle != null) { bundles.add(bundle); - Util.storeChecksum(bundle, artifact.getChecksum(), context); } } return bundles; @@ -722,10 +733,10 @@ */ private Bundle install(Artifact artifact) { + File path = artifact.getPath(); Bundle bundle = null; try { - File path = artifact.getPath(); // If the listener is an installer, ask for an update if (artifact.getListener() instanceof ArtifactInstaller) { @@ -734,30 +745,38 @@ // if the listener is an url transformer else if (artifact.getListener() instanceof ArtifactUrlTransformer) { - URL transformed = artifact.getTransformedUrl(); - Artifact badArtifact = (Artifact) installationFailures.get(artifact.getPath()); + Artifact badArtifact = (Artifact) installationFailures.get(path); if (badArtifact != null && badArtifact.getChecksum() == artifact.getChecksum()) { return null; // Don't attempt to install it; nothing has changed. } - bundle = context.installBundle(transformed.toString()); + URL transformed = artifact.getTransformedUrl(); + String location = transformed.toString(); + BufferedInputStream in = new BufferedInputStream(transformed.openStream()); + try + { + bundle = installOrUpdateBundle(location, in, artifact.getChecksum()); + } + finally + { + in.close(); + } artifact.setBundleId(bundle.getBundleId()); } - // else we need to ask for an update on the bundle + // if the listener is an artifact transformer else if (artifact.getListener() instanceof ArtifactTransformer) { - File transformed = artifact.getTransformed(); - Artifact badArtifact = (Artifact) installationFailures.get(artifact.getPath()); + Artifact badArtifact = (Artifact) installationFailures.get(path); if (badArtifact != null && badArtifact.getChecksum() == artifact.getChecksum()) { return null; // Don't attempt to install it; nothing has changed. } - InputStream in = new FileInputStream(transformed != null ? transformed : path); + File transformed = artifact.getTransformed(); + String location = path.toURI().normalize().toString(); + BufferedInputStream in = new BufferedInputStream(new FileInputStream(transformed != null ? transformed : path)); try { - // Some users wanted the location to be a URI (See FELIX-1269) - final String location = path.toURI().normalize().toString(); - bundle = context.installBundle(location, in); + bundle = installOrUpdateBundle(location, in, artifact.getChecksum()); } finally { @@ -771,16 +790,46 @@ } catch (Exception e) { - log("Failed to install artifact: " + artifact.getPath(), e); + log("Failed to install artifact: " + path, e); // Add it our bad jars list, so that we don't // attempt to install it again and again until the underlying // jar has been modified. - installationFailures.put(artifact.getPath(), artifact); + installationFailures.put(path, artifact); } return bundle; } + private Bundle installOrUpdateBundle(String bundleLocation, BufferedInputStream is, long checksum) throws IOException, BundleException { + is.mark(256 * 1024); + JarInputStream jar = new JarInputStream(is); + Manifest m = jar.getManifest(); + String sn = m.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME); + String vStr = m.getMainAttributes().getValue(Constants.BUNDLE_VERSION); + Version v = vStr == null ? Version.emptyVersion : Version.parseVersion(vStr); + Bundle[] bundles = context.getBundles(); + for (int i = 0; i < bundles.length; i++) { + Bundle b = bundles[i]; + if (b.getSymbolicName() != null && b.getSymbolicName().equals(sn)) { + vStr = (String) b.getHeaders().get(Constants.BUNDLE_VERSION); + Version bv = vStr == null ? Version.emptyVersion : Version.parseVersion(vStr); + if (v.equals(bv)) { + is.reset(); + if (Util.loadChecksum(b, context) != checksum) { + log("A bundle with the same symbolic name (" + sn + ") and version (" + vStr + ") is already installed. Updating this bundle instead.", null); + Util.storeChecksum(b, checksum, context); + b.update(is); + } + return b; + } + } + } + is.reset(); + Bundle b = context.installBundle(bundleLocation, is); + Util.storeChecksum(b, checksum, context); + return b; + } + /** * Uninstall a jar file. */ @@ -851,6 +900,7 @@ + ". The bundle has been uninstalled", null); return null; } + Util.storeChecksum(bundle, artifact.getChecksum(), context); bundle.update(); } // else we need to ask for an update on the bundle @@ -866,6 +916,7 @@ + ". The bundle has been uninstalled", null); return null; } + Util.storeChecksum(bundle, artifact.getChecksum(), context); InputStream in = new FileInputStream(transformed != null ? transformed : path); try { Modified: felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/Util.java URL: http://svn.apache.org/viewvc/felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/Util.java?rev=825454&r1=825453&r2=825454&view=diff ============================================================================== --- felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/Util.java (original) +++ felix/trunk/fileinstall/src/main/java/org/apache/felix/fileinstall/internal/Util.java Thu Oct 15 10:14:29 2009 @@ -39,7 +39,9 @@ import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; import org.osgi.framework.ServiceReference; +import org.osgi.framework.Version; import org.osgi.service.log.LogService; public class Util @@ -47,6 +49,8 @@ private static final String DELIM_START = "${"; private static final String DELIM_STOP = "}"; + private static final String CHECKSUM_SUFFIX = ".checksum"; + /** * Perform substitution on a property set * @@ -184,12 +188,13 @@ private static Logger getLogger(BundleContext context) { - if (logger != null && logger.isValidLogger(context)) - { - return logger; - } try { + context.getBundle(); + if (logger != null && logger.isValidLogger(context)) + { + return logger; + } logger = new OsgiLogger(context); } catch (Throwable t) @@ -383,7 +388,7 @@ public static void storeChecksum( Bundle b, long checksum, BundleContext bc ) { String key = getBundleKey(b); - File f = bc.getDataFile( key + ".checksum" ); + File f = bc.getDataFile( key + CHECKSUM_SUFFIX ); DataOutputStream dout = null; try { @@ -418,7 +423,7 @@ public static long loadChecksum( Bundle b, BundleContext bc ) { String key = getBundleKey(b); - File f = bc.getDataFile( key + ".checksum" ); + File f = bc.getDataFile( key + CHECKSUM_SUFFIX ); DataInputStream in = null; try { @@ -448,8 +453,8 @@ { StringBuffer sb = new StringBuffer(); sb.append(b.getSymbolicName()).append("_"); - String version = (String) b.getHeaders().get( "Bundle-Version" ); - sb.append(version != null ? version : "0.0.0"); + String version = (String) b.getHeaders().get(Constants.BUNDLE_VERSION); + sb.append(version != null ? version : Version.emptyVersion.toString()); return sb.toString(); }