Author: bdelacretaz
Date: Mon May 4 15:23:36 2009
New Revision: 771331
URL: http://svn.apache.org/viewvc?rev=771331&view=rev
Log:
SLING-904 - InstallableDataWrapper stores bundle data locally, in case
InputStream is gone when installing
Added:
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/InstallableDataWrapper.java
(with props)
Modified:
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/OsgiController.java
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerImpl.java
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerTask.java
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/test/java/org/apache/sling/jcr/jcrinstall/osgi/impl/BundleResourceProcessorTest.java
Modified:
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/OsgiController.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/OsgiController.java?rev=771331&r1=771330&r2=771331&view=diff
==============================================================================
---
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/OsgiController.java
(original)
+++
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/OsgiController.java
Mon May 4 15:23:36 2009
@@ -41,7 +41,7 @@
* @param attributes metadata stored by the OsgiController, will be
* removed after calling this method
*/
- void scheduleUninstall(String uri) throws JcrInstallException;
+ void scheduleUninstall(String uri) throws IOException, JcrInstallException;
/** Return the list of uri for resources that have been installed
* by this controller.
Added:
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/InstallableDataWrapper.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/InstallableDataWrapper.java?rev=771331&view=auto
==============================================================================
---
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/InstallableDataWrapper.java
(added)
+++
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/InstallableDataWrapper.java
Mon May 4 15:23:36 2009
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.jcr.jcrinstall.osgi.impl;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.sling.jcr.jcrinstall.osgi.InstallableData;
+import org.osgi.framework.BundleContext;
+
+/** Wraps InstallableData instances that provide an InputStream
+ * so that their data comes from our BundleContext's storage.
+ *
+ * Needed as InstallableData will be provided by a separate bundle,
+ * with InputStreams that might not be available anymore once
+ * the data is actually installed, for example if that data comes
+ * from a JCR repository that's deactivated due to bundle updates.
+ */
+class InstallableDataWrapper implements InstallableData {
+
+ private InstallableData wrapped;
+ private final File dataFile;
+ private static int fileCounter;
+
+ InstallableDataWrapper(InstallableData d, BundleContext bc) throws
IOException {
+ wrapped = d;
+
+ // If d adapts to an input stream, save its content in
+ // our BundleContext storage
+ final InputStream is = wrapped.adaptTo(InputStream.class);
+ if(is == null) {
+ dataFile = null;
+ } else {
+ OutputStream os = null;
+ try {
+ String filename = getClass().getName();
+ synchronized (getClass()) {
+ filename += "." + (++fileCounter);
+ }
+ dataFile = bc.getDataFile(filename);
+
+ os = new BufferedOutputStream(new
FileOutputStream(dataFile));
+ final byte[] buffer = new byte[16384];
+ int count = 0;
+ while((count = is.read(buffer, 0,
buffer.length)) > 0) {
+ os.write(buffer, 0, count);
+ }
+ os.flush();
+ } finally {
+ is.close();
+ if(os != null) {
+ os.close();
+ }
+ }
+ }
+ }
+
+ public int getBundleStartLevel() {
+ return wrapped.getBundleStartLevel();
+ }
+
+ /** Adapt the underlying data to the provided type.
+ * @return null if cannot be adapted */
+ @SuppressWarnings("unchecked")
+ public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+ // If we saved out content to a data file, use that
+ if(InputStream.class.equals(type) && dataFile != null) {
+ try {
+ return (AdapterType)(new
BufferedInputStream(new FileInputStream(dataFile)));
+ } catch(IOException ioe) {
+ throw new IllegalStateException("Unable to open
data file " + dataFile.getAbsolutePath());
+ }
+ } else {
+ return wrapped.adaptTo(type);
+ }
+ }
+
+ public String getDigest() {
+ return wrapped.getDigest();
+ }
+
+ void cleanup() {
+ if(dataFile != null) {
+ dataFile.delete();
+ }
+ wrapped = null;
+ }
+
+}
Propchange:
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/InstallableDataWrapper.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/InstallableDataWrapper.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Modified:
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerImpl.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerImpl.java?rev=771331&r1=771330&r2=771331&view=diff
==============================================================================
---
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerImpl.java
(original)
+++
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerImpl.java
Mon May 4 15:23:36 2009
@@ -30,6 +30,7 @@
import org.apache.sling.jcr.jcrinstall.osgi.OsgiController;
import org.apache.sling.jcr.jcrinstall.osgi.OsgiResourceProcessor;
import org.apache.sling.jcr.jcrinstall.osgi.ResourceOverrideRules;
+import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.SynchronousBundleListener;
import org.osgi.service.cm.ConfigurationAdmin;
@@ -54,6 +55,7 @@
*/
public class OsgiControllerImpl implements OsgiController,
SynchronousBundleListener {
+ private BundleContext bundleContext;
private Storage storage;
private OsgiResourceProcessorList processors;
private final Logger log = LoggerFactory.getLogger(this.getClass());
@@ -79,11 +81,13 @@
public static final long LAST_MODIFIED_NOT_FOUND = -1;
protected void activate(ComponentContext context) throws IOException {
+ bundleContext = context.getBundleContext();
processors = new OsgiResourceProcessorList(context.getBundleContext(),
packageAdmin, startLevel, configAdmin);
storage = new
Storage(context.getBundleContext().getDataFile(STORAGE_FILENAME));
}
protected void deactivate(ComponentContext oldContext) {
+ bundleContext = null;
if(storage != null) {
try {
storage.saveToFile();
@@ -104,13 +108,13 @@
public void scheduleInstallOrUpdate(String uri, InstallableData data)
throws IOException, JcrInstallException {
synchronized (tasks) {
- tasks.add(new OsgiControllerTask(storage, processors, roRules,
uri, data));
+ tasks.add(new OsgiControllerTask(storage, processors, roRules,
uri, data, bundleContext));
}
}
- public void scheduleUninstall(String uri) throws JcrInstallException {
+ public void scheduleUninstall(String uri) throws IOException,
JcrInstallException {
synchronized (tasks) {
- tasks.add(new OsgiControllerTask(storage, processors, roRules,
uri, null));
+ tasks.add(new OsgiControllerTask(storage, processors, roRules,
uri, null, bundleContext));
}
}
Modified:
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerTask.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerTask.java?rev=771331&r1=771330&r2=771331&view=diff
==============================================================================
---
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerTask.java
(original)
+++
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/main/java/org/apache/sling/jcr/jcrinstall/osgi/impl/OsgiControllerTask.java
Mon May 4 15:23:36 2009
@@ -28,6 +28,7 @@
import org.apache.sling.jcr.jcrinstall.osgi.JcrInstallException;
import org.apache.sling.jcr.jcrinstall.osgi.OsgiResourceProcessor;
import org.apache.sling.jcr.jcrinstall.osgi.ResourceOverrideRules;
+import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -52,13 +53,14 @@
OsgiResourceProcessorList processors,
ResourceOverrideRules roRules,
String uri,
- InstallableData data)
+ InstallableData data,
+ BundleContext bc) throws IOException
{
this.storage = storage;
this.processors = processors;
this.roRules = roRules;
this.uri = uri;
- this.data = data;
+ this.data = (data == null ? null : new
InstallableDataWrapper(data, bc));
}
@Override
@@ -72,12 +74,18 @@
;
}
- public Object call() throws JcrInstallException, IOException {
+ public Object call() throws Exception {
if(isInstallOrUpdate()) {
executeInstallOrUpdate();
} else {
executeUninstall();
}
+
+ // Cleanup InstallableDataWrapper
+ if(data instanceof InstallableDataWrapper) {
+ ((InstallableDataWrapper)data).cleanup();
+ }
+
return null;
}
@@ -85,7 +93,7 @@
return data != null;
}
- private void executeUninstall() throws JcrInstallException {
+ private void executeUninstall() throws Exception {
// If a corresponding higher priority resource is installed, ignore
this request
if(roRules != null) {
for(String r : roRules.getHigherPriorityResources(uri)) {
@@ -97,22 +105,17 @@
}
}
- try {
- // let each processor try to uninstall, one of them
- // should know how that handle uri
- for(OsgiResourceProcessor p : this.processors) {
- p.uninstall(uri, storage.getMap(uri));
- }
-
- storage.remove(uri);
- storage.saveToFile();
-
- } catch(Exception e) {
- throw new JcrInstallException("Exception in uninstall (" + uri +
")", e);
- }
+ // let each processor try to uninstall, one of them
+ // should know how that handle uri
+ for(OsgiResourceProcessor p : this.processors) {
+ p.uninstall(uri, storage.getMap(uri));
+ }
+
+ storage.remove(uri);
+ storage.saveToFile();
}
- private void executeInstallOrUpdate() throws JcrInstallException ,
IOException {
+ private void executeInstallOrUpdate() throws Exception {
// If a corresponding higher priority resource is already installed,
ignore this one
if(roRules != null) {
for(String r : roRules.getHigherPriorityResources(uri)) {
@@ -138,17 +141,11 @@
// let suitable OsgiResourceProcessor process install
final OsgiResourceProcessor p = processors.getProcessor(uri, data);
if (p != null) {
- try {
- final Map<String, Object> map = storage.getMap(uri);
- if(p.installOrUpdate(uri, map, data) != IGNORED) {
- map.put(OsgiControllerImpl.KEY_DIGEST, data.getDigest());
- }
- storage.saveToFile();
- } catch(IOException ioe) {
- throw ioe;
- } catch(Exception e) {
- throw new JcrInstallException("Exception in installOrUpdate ("
+ uri + ")", e);
+ final Map<String, Object> map = storage.getMap(uri);
+ if(p.installOrUpdate(uri, map, data) != IGNORED) {
+ map.put(OsgiControllerImpl.KEY_DIGEST, data.getDigest());
}
+ storage.saveToFile();
}
return;
Modified:
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/test/java/org/apache/sling/jcr/jcrinstall/osgi/impl/BundleResourceProcessorTest.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/test/java/org/apache/sling/jcr/jcrinstall/osgi/impl/BundleResourceProcessorTest.java?rev=771331&r1=771330&r2=771331&view=diff
==============================================================================
---
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/test/java/org/apache/sling/jcr/jcrinstall/osgi/impl/BundleResourceProcessorTest.java
(original)
+++
incubator/sling/trunk/contrib/extensions/jcrinstall/service/src/test/java/org/apache/sling/jcr/jcrinstall/osgi/impl/BundleResourceProcessorTest.java
Mon May 4 15:23:36 2009
@@ -41,6 +41,7 @@
private Mockery mockery;
private Sequence sequence;
+ private static int counter;
static class TestStorage extends Storage {
int saveCounter;
@@ -65,6 +66,7 @@
final OsgiControllerImpl c = new OsgiControllerImpl();
final BundleContext bc = mockery.mock(BundleContext.class);
+ Utilities.setField(c, "bundleContext", bc);
final PackageAdmin pa = mockery.mock(PackageAdmin.class);
final TestStorage s = new TestStorage(Utilities.getTestFile());
Utilities.setStorage(c, s);
@@ -72,7 +74,7 @@
final Bundle [] bundles = { b };
final long bundleId = 1234;
final String uri = "/test/bundle.jar";
- final MockInstallableData data = new MockInstallableData(uri);
+ final MockInstallableData data = new MockInstallableData(uri, "some
data");
final InputStream is = data.adaptTo(InputStream.class);
// We'll try installing a bundle, re-installing to cause
@@ -93,8 +95,12 @@
allowing(b).getLocation();
will(returnValue(uri));
allowing(bc).addFrameworkListener(with(any(FrameworkListener.class)));
+ allowing(bc).getDataFile(with(any(String.class)));
+ will(returnValue(getDataFile()));
- one(bc).installBundle(OsgiControllerImpl.getResourceLocation(uri),
is);
+ one(bc).installBundle(
+
with(equal(OsgiControllerImpl.getResourceLocation(uri))),
+ with(any(InputStream.class)));
inSequence(sequence);
will(returnValue(b));
@@ -105,7 +111,7 @@
one(b).stop();
inSequence(sequence);
- one(b).update(is);
+ one(b).update(with(any(InputStream.class)));
inSequence(sequence);
one(b).uninstall();
@@ -166,4 +172,8 @@
mockery.assertIsSatisfied();
t.active = false;
}
+
+ static File getDataFile() throws IOException {
+ return
File.createTempFile(BundleResourceProcessor.class.getSimpleName() +
(++counter),".tmp");
+ }
}