Author: cziegeler
Date: Thu Oct 16 02:58:57 2008
New Revision: 705191
URL: http://svn.apache.org/viewvc?rev=705191&view=rev
Log:
SLING-699 : Synchronized bundle install/update/start/refresh, and only update
bundles if the version number is higher. Fixed some log messages.
Modified:
incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/BundleResourceProcessor.java
incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerImpl.java
Modified:
incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/BundleResourceProcessor.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/BundleResourceProcessor.java?rev=705191&r1=705190&r2=705191&view=diff
==============================================================================
---
incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/BundleResourceProcessor.java
(original)
+++
incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/BundleResourceProcessor.java
Thu Oct 16 02:58:57 2008
@@ -18,6 +18,7 @@
*/
package org.apache.sling.jcr.jcrinstall.osgi.impl;
+import static org.apache.sling.jcr.jcrinstall.osgi.InstallResultCode.IGNORED;
import static org.apache.sling.jcr.jcrinstall.osgi.InstallResultCode.INSTALLED;
import static org.apache.sling.jcr.jcrinstall.osgi.InstallResultCode.UPDATED;
@@ -37,6 +38,7 @@
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
import org.osgi.service.packageadmin.PackageAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -53,7 +55,6 @@
private final PackageAdmin packageAdmin;
private final Map<Long, Bundle> pendingBundles;
private final Logger log = LoggerFactory.getLogger(this.getClass());
- private final Object refreshLock = new Object();
BundleResourceProcessor(BundleContext ctx, PackageAdmin packageAdmin) {
this.ctx = ctx;
@@ -61,56 +62,80 @@
pendingBundles = new HashMap<Long, Bundle>();
}
- public int installOrUpdate(String uri, Map<String, Object> attributes,
InputStream data) throws Exception {
+ /**
+ * @throws BundleException
+ * @see
org.apache.sling.jcr.jcrinstall.osgi.OsgiResourceProcessor#installOrUpdate(java.lang.String,
java.util.Map, java.io.InputStream)
+ */
+ public int installOrUpdate(String uri, Map<String, Object> attributes,
InputStream data)
+ throws BundleException, IOException {
// Update if we already have a bundle id, else install
Bundle b = null;
boolean updated = false;
- // check whether we know the bundle and it exists
- final Long longId = (Long)attributes.get(KEY_BUNDLE_ID);
- if(longId != null) {
- b = ctx.getBundle(longId);
- }
+ synchronized (pendingBundles) {
+ // check whether we know the bundle and it exists
+ final Long longId = (Long)attributes.get(KEY_BUNDLE_ID);
+ if (longId != null) {
+ b = ctx.getBundle(longId);
+ }
- // either we don't know the bundle yet or it does not exist,
- // so check whether the bundle can be found by its symbolic name
- if (b == null) {
- // ensure we can mark and reset to read the manifest
- if (!data.markSupported()) {
- data = new BufferedInputStream(data);
+ // either we don't know the bundle yet or it does not exist,
+ // so check whether the bundle can be found by its symbolic name
+ if (b == null) {
+ // ensure we can mark and reset to read the manifest
+ if (!data.markSupported()) {
+ data = new BufferedInputStream(data);
+ }
+ final BundleInfo info = getMatchingBundle(data);
+ if ( info != null ) {
+ final Version availableVersion = new
Version((String)info.bundle.getHeaders().get(Constants.BUNDLE_VERSION));
+ final Version newVersion = new Version(info.newVersion);
+ if ( newVersion.compareTo(availableVersion) > 0 ) {
+ b = info.bundle;
+ } else {
+ log.debug("Ignore update of bundle {} from {} as the
installed version is equal or higher.", info.bundle.getSymbolicName(), uri);
+ return IGNORED;
+ }
+ }
}
- b = getMatchingBundle(data);
- }
- if (b != null) {
- b.update(data);
- updated = true;
- } else {
- uri = OsgiControllerImpl.getResourceLocation(uri);
- log.debug("No matching Bundle for uri {}, installing", uri);
- b = ctx.installBundle(uri, data);
- }
+ if (b != null) {
+ b.update(data);
+ updated = true;
+ // wait a little bit after an update
+ try {
+ Thread.sleep(1500);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ } else {
+ uri = OsgiControllerImpl.getResourceLocation(uri);
+ log.debug("No matching Bundle for uri {}, installing", uri);
+ b = ctx.installBundle(uri, data);
+ }
- // ensure the bundle id in the attributes, this may be overkill
- // in simple update situations, but is required for installations
- // and updates where there are no attributes yet
- attributes.put(KEY_BUNDLE_ID, b.getBundleId());
+ // ensure the bundle id in the attributes, this may be overkill
+ // in simple update situations, but is required for installations
+ // and updates where there are no attributes yet
+ attributes.put(KEY_BUNDLE_ID, b.getBundleId());
- synchronized(pendingBundles) {
pendingBundles.put(b.getBundleId(), b);
}
return updated ? UPDATED : INSTALLED;
}
+ /**
+ * @see
org.apache.sling.jcr.jcrinstall.osgi.OsgiResourceProcessor#uninstall(java.lang.String,
java.util.Map)
+ */
public void uninstall(String uri, Map<String, Object> attributes) throws
BundleException {
final Long longId = (Long)attributes.get(KEY_BUNDLE_ID);
- if(longId == null) {
- log.debug("No {} in metadata, bundle cannot be uninstalled");
+ if (longId == null) {
+ log.debug("No bundle id in metadata for {}, bundle cannot be
uninstalled.", uri);
} else {
final Bundle b = ctx.getBundle(longId);
- if(b == null) {
- log.debug("Bundle having id {} not found, cannot uninstall");
+ if (b == null) {
+ log.debug("Bundle having id {} not found, cannot uninstall",
longId);
} else {
synchronized(pendingBundles) {
pendingBundles.remove(b.getBundleId());
@@ -120,69 +145,76 @@
}
}
+ /**
+ * @see
org.apache.sling.jcr.jcrinstall.osgi.OsgiResourceProcessor#canProcess(java.lang.String)
+ */
public boolean canProcess(String uri) {
return uri.endsWith(BUNDLE_EXTENSION);
}
+ /**
+ * @see
org.apache.sling.jcr.jcrinstall.osgi.OsgiResourceProcessor#processResourceQueue()
+ */
public void processResourceQueue() {
-
- if(pendingBundles.isEmpty()) {
- return;
- }
-
- final List<Long> toRemove = new LinkedList<Long>();
- final List<Long> idList = new LinkedList<Long>();
synchronized(pendingBundles) {
+ if (pendingBundles.isEmpty()) {
+ return;
+ }
+ final List<Long> toRemove = new LinkedList<Long>();
+ final List<Long> idList = new LinkedList<Long>();
+
idList.addAll(pendingBundles.keySet());
- }
- for(Long id : idList) {
- final Bundle bundle = ctx.getBundle(id);
- if(bundle == null) {
- log.debug("Bundle id {} disappeared (bundle removed from
framework?), removed from pending bundles queue");
- toRemove.add(id);
- continue;
- }
- final int state = bundle.getState();
-
- switch ( state ) {
- case Bundle.ACTIVE :
- log.info("Bundle {} is active, removed from pending
bundles queue", bundle.getLocation());
- toRemove.add(id);
- break;
- case Bundle.STARTING :
- log.info("Bundle {} is starting.", bundle.getLocation());
- break;
- case Bundle.STOPPING :
- log.info("Bundle {} is stopping.", bundle.getLocation());
- break;
- case Bundle.UNINSTALLED :
- log.info("Bundle {} is uninstalled, removed from pending
bundles queue", bundle.getLocation());
+ boolean doRefresh = false;
+
+ for(Long id : idList) {
+ final Bundle bundle = ctx.getBundle(id);
+ if(bundle == null) {
+ log.debug("Bundle id {} disappeared (bundle removed from
framework?), removed from pending bundles queue", id);
toRemove.add(id);
- break;
- case Bundle.INSTALLED :
- log.debug("Bundle {} is installed but not resolved.",
bundle.getLocation());
- if ( !packageAdmin.resolveBundles(new Bundle[] {bundle}) )
{
- log.debug("Bundle {} is installed, failed to
resolve.", bundle.getLocation());
+ continue;
+ }
+ final int state = bundle.getState();
+
+ switch ( state ) {
+ case Bundle.ACTIVE :
+ log.info("Bundle {} is active, removed from pending
bundles queue", bundle.getLocation());
+ toRemove.add(id);
break;
- }
- // fall through to RESOLVED to start the bundle
- case Bundle.RESOLVED :
- log.info("Bundle {} is resolved, trying to start it.",
bundle.getLocation());
- try {
- bundle.start();
- } catch (BundleException e) {
- log.error("Exception during bundle start of Bundle " +
bundle.getLocation(), e);
- }
- break;
+ case Bundle.STARTING :
+ log.info("Bundle {} is starting.",
bundle.getLocation());
+ break;
+ case Bundle.STOPPING :
+ log.info("Bundle {} is stopping.",
bundle.getLocation());
+ break;
+ case Bundle.UNINSTALLED :
+ log.info("Bundle {} is uninstalled, removed from
pending bundles queue", bundle.getLocation());
+ toRemove.add(id);
+ doRefresh = true;
+ break;
+ case Bundle.INSTALLED :
+ log.debug("Bundle {} is installed but not resolved.",
bundle.getLocation());
+ if ( !packageAdmin.resolveBundles(new Bundle[]
{bundle}) ) {
+ log.debug("Bundle {} is installed, failed to
resolve.", bundle.getLocation());
+ break;
+ }
+ // fall through to RESOLVED to start the bundle
+ case Bundle.RESOLVED :
+ log.info("Bundle {} is resolved, trying to start it.",
bundle.getLocation());
+ try {
+ bundle.start();
+ } catch (BundleException e) {
+ log.error("Exception during bundle start of Bundle
" + bundle.getLocation(), e);
+ }
+ doRefresh = true;
+ break;
+ }
}
- }
- synchronized(refreshLock) {
- packageAdmin.refreshPackages(null);
- }
+ if ( doRefresh ) {
+ packageAdmin.refreshPackages(null);
+ }
- synchronized(pendingBundles) {
pendingBundles.keySet().removeAll(toRemove);
}
}
@@ -210,7 +242,7 @@
* with a symbolic name.
* @throws IOException If an error occurrs reading from the input stream.
*/
- private Bundle getMatchingBundle(InputStream data) throws IOException {
+ private BundleInfo getMatchingBundle(InputStream data) throws IOException {
// allow 2KB, this should be enough for the manifest
data.mark(2048);
@@ -237,7 +269,10 @@
Bundle[] bundles = ctx.getBundles();
for (Bundle bundle : bundles) {
if (symbolicName.equals(bundle.getSymbolicName())) {
- return bundle;
+ final BundleInfo info = new BundleInfo();
+ info.bundle = bundle;
+ info.newVersion =
manifest.getMainAttributes().getValue(Constants.BUNDLE_VERSION);
+ return info;
}
}
@@ -260,4 +295,9 @@
// fall back to no bundle found for update
return null;
}
+
+ protected static final class BundleInfo {
+ public Bundle bundle;
+ public String newVersion;
+ }
}
\ No newline at end of file
Modified:
incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerImpl.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerImpl.java?rev=705191&r1=705190&r2=705191&view=diff
==============================================================================
---
incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerImpl.java
(original)
+++
incubator/sling/trunk/extensions/jcrinstall/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerImpl.java
Thu Oct 16 02:58:57 2008
@@ -39,16 +39,16 @@
import org.slf4j.LoggerFactory;
/** OsgiController service
- *
+ *
* @scr.service
- * @scr.component
+ * @scr.component
* immediate="true"
* metatype="no"
- * @scr.property
- * name="service.description"
+ * @scr.property
+ * name="service.description"
* value="Sling jcrinstall OsgiController Service"
- * @scr.property
- * name="service.vendor"
+ * @scr.property
+ * name="service.vendor"
* value="The Apache Software Foundation"
*/
public class OsgiControllerImpl implements OsgiController, Runnable,
SynchronousBundleListener {
@@ -58,38 +58,38 @@
private final Logger log = LoggerFactory.getLogger(this.getClass());
private boolean running;
private long loopDelay;
-
+
public static final String STORAGE_FILENAME = "controller.storage";
-
+
/** @scr.reference */
private ConfigurationAdmin configAdmin;
-
+
/** @scr.reference */
private PackageAdmin packageAdmin;
-
+
/** Storage key: last modified as a Long */
public static final String KEY_LAST_MODIFIED = "last.modified";
-
+
/** Default value for getLastModified() */
public static final long LAST_MODIFIED_NOT_FOUND = -1;
-
+
protected void activate(ComponentContext context) throws IOException {
processors = new LinkedList<OsgiResourceProcessor>();
processors.add(new BundleResourceProcessor(context.getBundleContext(),
packageAdmin));
processors.add(new ConfigResourceProcessor(configAdmin));
-
+
storage = new
Storage(context.getBundleContext().getDataFile(STORAGE_FILENAME));
-
+
// start queue processing
running = true;
final Thread t = new Thread(this, getClass().getSimpleName() + "_" +
System.currentTimeMillis());
t.setDaemon(true);
t.start();
}
-
+
protected void deactivate(ComponentContext oldContext) {
running = false;
-
+
if(storage != null) {
try {
storage.saveToFile();
@@ -100,15 +100,15 @@
storage = null;
processors = null;
}
-
+
public int installOrUpdate(String uri, long lastModified, InputStream
data) throws IOException, JcrInstallException {
int result = IGNORED;
final OsgiResourceProcessor p = getProcessor(uri);
- if(p != null) {
+ if (p != null) {
try {
final Map<String, Object> map = storage.getMap(uri);
result = p.installOrUpdate(uri, map, data);
- if(result != IGNORED) {
+ if (result != IGNORED) {
map.put(KEY_LAST_MODIFIED, new Long(lastModified));
}
storage.saveToFile();
@@ -120,7 +120,7 @@
}
return result;
}
-
+
public void uninstall(String uri) throws JcrInstallException {
final OsgiResourceProcessor p = getProcessor(uri);
if(p != null) {
@@ -133,7 +133,7 @@
}
}
}
-
+
public Set<String> getInstalledUris() {
return storage.getKeys();
}
@@ -143,46 +143,46 @@
*/
public long getLastModified(String uri) {
long result = LAST_MODIFIED_NOT_FOUND;
-
+
if(storage.contains(uri)) {
final Map<String, Object> uriData = storage.getMap(uri);
- final Long lastMod = (Long)uriData.get(KEY_LAST_MODIFIED);
+ final Long lastMod = (Long)uriData.get(KEY_LAST_MODIFIED);
if(lastMod != null) {
result = lastMod.longValue();
}
}
return result;
}
-
+
static String getResourceLocation(String uri) {
return "jcrinstall://" + uri;
}
-
+
/** Return the first processor that accepts given uri, null if not found */
OsgiResourceProcessor getProcessor(String uri) {
OsgiResourceProcessor result = null;
-
+
if(processors == null) {
throw new IllegalStateException("Processors are not set");
}
-
+
for(OsgiResourceProcessor p : processors) {
if(p.canProcess(uri)) {
result = p;
break;
}
}
-
+
if(result == null) {
log.debug("No processor found for resource {}", uri);
}
-
+
return result;
}
-
+
/** Schedule our next scan sooner if anything happens to bundles */
public void bundleChanged(BundleEvent e) {
- loopDelay = 0;
+ //loopDelay = 0;
}
/** Process our resource queues at regular intervals, more often if
@@ -198,7 +198,7 @@
for(OsgiResourceProcessor p : processors) {
p.processResourceQueue();
}
-
+
} catch (Exception e) {
log.warn("Exception in run()", e);
} finally {