SLING-5591 : Race condition in installer: cached artifacts might be made unavailable
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1734096 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/sling/installer/api/tasks/TransformationResult.java b/src/main/java/org/apache/sling/installer/api/tasks/TransformationResult.java
index 138b505..1022321 100644
--- a/src/main/java/org/apache/sling/installer/api/tasks/TransformationResult.java
+++ b/src/main/java/org/apache/sling/installer/api/tasks/TransformationResult.java
@@ -129,4 +129,11 @@
public Version getVersion() {
return this.version;
}
+
+ @Override
+ public String toString() {
+ return "TransformationResult [resourceType=" + resourceType + ", id=" + id + ", version=" + version
+ + ", attributes=" + attributes + "]";
+ }
+
}
diff --git a/src/main/java/org/apache/sling/installer/api/tasks/package-info.java b/src/main/java/org/apache/sling/installer/api/tasks/package-info.java
index ae26ea2..0d63906 100644
--- a/src/main/java/org/apache/sling/installer/api/tasks/package-info.java
+++ b/src/main/java/org/apache/sling/installer/api/tasks/package-info.java
@@ -17,7 +17,7 @@
* under the License.
*/
-@Version("1.3.2")
+@Version("1.3.4")
package org.apache.sling.installer.api.tasks;
import aQute.bnd.annotation.Version;
diff --git a/src/main/java/org/apache/sling/installer/core/impl/DefaultTransformer.java b/src/main/java/org/apache/sling/installer/core/impl/DefaultTransformer.java
index 0951536..33466e1 100644
--- a/src/main/java/org/apache/sling/installer/core/impl/DefaultTransformer.java
+++ b/src/main/java/org/apache/sling/installer/core/impl/DefaultTransformer.java
@@ -46,6 +46,7 @@
/**
* @see org.apache.sling.installer.core.impl.InternalService#init(org.osgi.framework.BundleContext, org.apache.sling.installer.api.ResourceChangeListener, RetryHandler)
*/
+ @Override
public void init(final BundleContext bctx, final ResourceChangeListener rcl, RetryHandler retryHandler) {
// nothing to do
}
@@ -53,6 +54,7 @@
/**
* @see org.apache.sling.installer.core.impl.InternalService#deactivate()
*/
+ @Override
public void deactivate() {
// nothing to do
}
@@ -60,6 +62,7 @@
/**
* @see org.apache.sling.installer.core.impl.InternalService#getDescription()
*/
+ @Override
public String getDescription() {
return "Apache Sling Installer - Default Resource Transformer";
}
@@ -67,10 +70,13 @@
/**
* @see org.apache.sling.installer.api.tasks.ResourceTransformer#transform(org.apache.sling.installer.api.tasks.RegisteredResource)
*/
+ @Override
public TransformationResult[] transform(final RegisteredResource resource) {
+ logger.debug("Trying to transform {} : {}", resource, resource.getType());
if ( resource.getType().equals(InstallableResource.TYPE_FILE) ) {
return checkBundle(resource);
}
+ logger.debug("Unsupported type {} : {}", resource, resource.getType());
return null;
}
@@ -79,14 +85,16 @@
* @return
*/
private TransformationResult[] checkBundle(final RegisteredResource resource) {
+ logger.debug("Checking headers for {}", resource);
final Util.BundleHeaders headers = Util.readBundleHeaders(resource, logger);
+ logger.debug("Found headers for {} : {}", resource, headers);
if ( headers != null ) {
// check the version for validity
boolean validVersion = true;
try {
new Version(headers.version);
} catch (final IllegalArgumentException iae) {
- logger.info("Rejecting bundle {} from {} due to invalid version information: {}.",
+ logger.info("Rejecting bundle {} from {} due to invalid version information: {}.",
new Object[] {headers.symbolicName, resource, headers.version});
validVersion = false;
}
@@ -105,6 +113,7 @@
tr.setResourceType(InstallableResource.TYPE_BUNDLE);
tr.setAttributes(attr);
+ logger.debug("Transformed {} to {}", resource, tr);
return new TransformationResult[] {tr};
}
}
diff --git a/src/main/java/org/apache/sling/installer/core/impl/FileDataStore.java b/src/main/java/org/apache/sling/installer/core/impl/FileDataStore.java
index 24bbfac..59e171e 100644
--- a/src/main/java/org/apache/sling/installer/core/impl/FileDataStore.java
+++ b/src/main/java/org/apache/sling/installer/core/impl/FileDataStore.java
@@ -61,7 +61,17 @@
public static FileDataStore SHARED;
/** Cache for url to digest mapping. */
- private final Map<String, String> digestCache = new HashMap<String, String>();
+ private final Map<String, CacheEntry> digestCache = new HashMap<String, CacheEntry>();
+
+ private static final class CacheEntry {
+ public final File file;
+ public final String digest;
+
+ public CacheEntry(final File file, final String digest) {
+ this.file = file;
+ this.digest = digest;
+ }
+ }
/**
* Create a file util instance and detect the installer directory.
@@ -139,34 +149,35 @@
// check if we already have this data
if ( digest != null ) {
synchronized ( this.digestCache ) {
- final String storedDigest = this.digestCache.get(url);
- if ( storedDigest != null && storedDigest.equals(digest) ) {
- return null;
+ final CacheEntry storedDigest = this.digestCache.get(url);
+ if ( storedDigest != null && storedDigest.digest.equals(digest) ) {
+ return storedDigest.file;
}
}
}
final int pos = url.lastIndexOf('/');
final String name = url.substring(pos + 1);
final String filename = (hint == null ? "rsrc" : hint) + '-' + name + '-' + getNextSerialNumber() + ".ser";
-
+
//replace special characters from the filename that are not allowed by the OS
final String filename2 = filename.replaceAll("[\\*\"/\\\\\\[\\]\\:\\;\\|\\=\\,]+", "_"); // Windows
-
+
final File file = this.getDataFile(filename2);
this.copyToLocalStorage(stream, file);
if ( digest != null ) {
synchronized ( this.digestCache ) {
- this.digestCache.put(url, digest);
+ this.digestCache.put(url, new CacheEntry(file, digest));
}
}
+
return file;
}
- public void updateDigestCache(final String url, final String digest) {
+ public void updateDigestCache(final String url, final File file, final String digest) {
synchronized ( this.digestCache ) {
- this.digestCache.put(url, digest);
+ this.digestCache.put(url, new CacheEntry(file, digest));
}
}
@@ -200,8 +211,8 @@
public void removeFromDigestCache(final String url, final String digest) {
synchronized ( this.digestCache ) {
- final String storedDigest = this.digestCache.get(url);
- if ( storedDigest != null && storedDigest.equals(digest) ) {
+ final CacheEntry entry = this.digestCache.get(url);
+ if ( entry != null && entry.digest.equals(digest) ) {
this.digestCache.remove(url);
}
}
diff --git a/src/main/java/org/apache/sling/installer/core/impl/InternalResource.java b/src/main/java/org/apache/sling/installer/core/impl/InternalResource.java
index 352e0bd..1dab202 100644
--- a/src/main/java/org/apache/sling/installer/core/impl/InternalResource.java
+++ b/src/main/java/org/apache/sling/installer/core/impl/InternalResource.java
@@ -124,7 +124,7 @@
digest = resource.getDigest();
} else {
digest = FileDataStore.computeDigest(dataFile);
- FileDataStore.SHARED.updateDigestCache(url, digest);
+ FileDataStore.SHARED.updateDigestCache(url, dataFile, digest);
}
}
}
diff --git a/src/main/java/org/apache/sling/installer/core/impl/PersistentResourceList.java b/src/main/java/org/apache/sling/installer/core/impl/PersistentResourceList.java
index 8a38c34..1989b03 100644
--- a/src/main/java/org/apache/sling/installer/core/impl/PersistentResourceList.java
+++ b/src/main/java/org/apache/sling/installer/core/impl/PersistentResourceList.java
@@ -144,13 +144,13 @@
for(final EntityResourceList group : this.data.values()) {
for(final RegisteredResource rr : group.getResources()) {
if ( ((RegisteredResourceImpl)rr).hasDataFile() ) {
- FileDataStore.SHARED.updateDigestCache(rr.getURL(), rr.getDigest());
+ FileDataStore.SHARED.updateDigestCache(rr.getURL(), ((RegisteredResourceImpl)rr).getDataFile(), rr.getDigest());
}
}
}
for(final RegisteredResource rr : this.untransformedResources ) {
if ( ((RegisteredResourceImpl)rr).hasDataFile() ) {
- FileDataStore.SHARED.updateDigestCache(rr.getURL(), rr.getDigest());
+ FileDataStore.SHARED.updateDigestCache(rr.getURL(), ((RegisteredResourceImpl)rr).getDataFile(), rr.getDigest());
}
}
}
diff --git a/src/main/java/org/apache/sling/installer/core/impl/RegisteredResourceImpl.java b/src/main/java/org/apache/sling/installer/core/impl/RegisteredResourceImpl.java
index 49fc097..b158262 100644
--- a/src/main/java/org/apache/sling/installer/core/impl/RegisteredResourceImpl.java
+++ b/src/main/java/org/apache/sling/installer/core/impl/RegisteredResourceImpl.java
@@ -235,6 +235,10 @@
return this.dataFile != null;
}
+ public File getDataFile() {
+ return this.dataFile;
+ }
+
/**
* Remove the data file
*/
@@ -259,14 +263,16 @@
/**
* @see org.apache.sling.installer.api.tasks.RegisteredResource#getURL()
*/
- public String getURL() {
+ @Override
+ public String getURL() {
return this.url;
}
/**
* @see org.apache.sling.installer.api.tasks.RegisteredResource#getInputStream()
*/
- public InputStream getInputStream() throws IOException {
+ @Override
+ public InputStream getInputStream() throws IOException {
if ( this.dataUri != null ) {
try {
final URI uri = new URI(this.dataUri);
@@ -284,20 +290,23 @@
/**
* @see org.apache.sling.installer.api.tasks.RegisteredResource#getDictionary()
*/
- public Dictionary<String, Object> getDictionary() {
+ @Override
+ public Dictionary<String, Object> getDictionary() {
return dictionary;
}
/**
* @see org.apache.sling.installer.api.tasks.RegisteredResource#getDigest()
*/
- public String getDigest() {
+ @Override
+ public String getDigest() {
return digest;
}
/**
* @see org.apache.sling.installer.api.tasks.RegisteredResource#getType()
*/
+ @Override
public String getType() {
return resourceType;
}
@@ -305,6 +314,7 @@
/**
* @see org.apache.sling.installer.api.tasks.RegisteredResource#getEntityId()
*/
+ @Override
public String getEntityId() {
return entity;
}
@@ -312,6 +322,7 @@
/**
* @see org.apache.sling.installer.api.tasks.TaskResource#getAttribute(java.lang.String)
*/
+ @Override
public Object getAttribute(final String key) {
return this.attributes.get(key);
}
@@ -319,6 +330,7 @@
/**
* @see org.apache.sling.installer.api.tasks.TaskResource#setAttribute(java.lang.String, java.lang.Object)
*/
+ @Override
public void setAttribute(final String key, final Object value) {
if ( value == null ) {
this.attributes.remove(key);
@@ -330,6 +342,7 @@
/**
* @see org.apache.sling.installer.api.tasks.RegisteredResource#getScheme()
*/
+ @Override
public String getScheme() {
return urlScheme;
}
@@ -337,6 +350,7 @@
/**
* @see org.apache.sling.installer.api.tasks.RegisteredResource#getPriority()
*/
+ @Override
public int getPriority() {
return priority;
}
@@ -344,6 +358,7 @@
/**
* @see org.apache.sling.installer.api.tasks.TaskResource#getState()
*/
+ @Override
public ResourceState getState() {
return this.state;
}
@@ -392,6 +407,7 @@
/**
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
+ @Override
public int compareTo(final RegisteredResourceImpl b) {
return compare(this, b);
}
@@ -426,14 +442,14 @@
*/
public static int compare(final TaskResource a, final TaskResource b) {
int result = 0;
-
+
// check entity id first
final String aId = a.getEntityId();
final String bId = b.getEntityId();
if(aId != null && bId != null) {
result = aId.compareTo(bId);
}
-
+
boolean hasVersion = false;
if ( result == 0 ) {
// compare versions
@@ -486,6 +502,7 @@
/**
* @see org.apache.sling.installer.api.tasks.TaskResource#getTemporaryAttribute(java.lang.String)
*/
+ @Override
public Object getTemporaryAttribute(final String key) {
if ( this.temporaryAttributes != null ) {
return this.temporaryAttributes.get(key);
@@ -496,6 +513,7 @@
/**
* @see org.apache.sling.installer.api.tasks.TaskResource#setTemporaryAttribute(java.lang.String, java.lang.Object)
*/
+ @Override
public void setTemporaryAttribute(final String key, final Object value) {
if ( this.temporaryAttributes == null ) {
this.temporaryAttributes = new HashMap<String, Object>();
@@ -572,7 +590,7 @@
this.removeDataFile();
}
this.dataFile = rsrc.getPrivateCopyOfFile();
- FileDataStore.SHARED.updateDigestCache(this.url, this.digest);
+ FileDataStore.SHARED.updateDigestCache(this.url, this.dataFile, this.digest);
}
}
}
@@ -626,6 +644,7 @@
/**
* @see org.apache.sling.installer.api.tasks.TaskResource#getVersion()
*/
+ @Override
public Version getVersion() {
final String vInfo = (String)this.getAttribute(Constants.BUNDLE_VERSION);
return (vInfo == null ? null : new Version(vInfo));
diff --git a/src/main/java/org/apache/sling/installer/core/impl/ResourceData.java b/src/main/java/org/apache/sling/installer/core/impl/ResourceData.java
index 5180ebf..dc241d5 100644
--- a/src/main/java/org/apache/sling/installer/core/impl/ResourceData.java
+++ b/src/main/java/org/apache/sling/installer/core/impl/ResourceData.java
@@ -92,7 +92,7 @@
if ( digest == null ) {
digest = FileDataStore.computeDigest(this.dataFile);
}
- FileDataStore.SHARED.updateDigestCache(url, digest);
+ FileDataStore.SHARED.updateDigestCache(url, this.dataFile, digest);
return digest;
}
diff --git a/src/main/java/org/apache/sling/installer/core/impl/Util.java b/src/main/java/org/apache/sling/installer/core/impl/Util.java
index 4085c40..fbf5ced 100644
--- a/src/main/java/org/apache/sling/installer/core/impl/Util.java
+++ b/src/main/java/org/apache/sling/installer/core/impl/Util.java
@@ -91,6 +91,8 @@
}
}
}
+ } else {
+ logger.debug("Unable to get input stream from {}", rsrc);
}
return result;
}
@@ -99,6 +101,12 @@
public String symbolicName;
public String version;
public String activationPolicy; // optional
+
+ @Override
+ public String toString() {
+ return "BundleHeaders [symbolicName=" + symbolicName + ", version=" + version + ", activationPolicy="
+ + activationPolicy + "]";
+ }
}
/**
@@ -125,10 +133,17 @@
}
return headers;
+ } else {
+ logger.debug("Unable to get version from manifest : {}", resource);
}
+ } else {
+ logger.debug("Unable to get symbolic name from manifest : {}", resource);
}
+ } else {
+ logger.debug("Unable to read manifest from : {}", resource);
}
} catch (final IOException ignore) {
+ logger.debug("Exception occured during processing of " + resource, ignore);
// ignore
}
return null;