You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2014/11/04 08:37:02 UTC
svn commit: r1636516 -
/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ResourceHelper.java
Author: cziegeler
Date: Tue Nov 4 07:37:01 2014
New Revision: 1636516
URL: http://svn.apache.org/r1636516
Log:
SLING-4122 : Folders might be created concurrently resulting in SNS nodes. Copy code from Sling's API to avoid relying on the latest API release
Modified:
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ResourceHelper.java
Modified: sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ResourceHelper.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ResourceHelper.java?rev=1636516&r1=1636515&r2=1636516&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ResourceHelper.java (original)
+++ sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/support/ResourceHelper.java Tue Nov 4 07:37:01 2014
@@ -25,6 +25,7 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -264,41 +265,171 @@ public abstract class ResourceHelper {
public static void getOrCreateBasePath(final ResourceResolver resolver,
final String path)
throws PersistenceException {
- PersistenceException mostRecentPE = null;
- for(int i=0;i<5;i++) {
- try {
- ResourceUtil.getOrCreateResource(resolver,
+ getOrCreateResource(resolver,
path,
ResourceHelper.RESOURCE_TYPE_FOLDER,
ResourceHelper.RESOURCE_TYPE_FOLDER,
true);
- return;
- } catch ( final PersistenceException pe ) {
- //in case of exception, revert to last clean state and retry SLING-4014
- resolver.revert();
- mostRecentPE = pe;
- }
- }
- throw new PersistenceException("Unable to create resource with path " + path, mostRecentPE);
}
public static Resource getOrCreateResource(final ResourceResolver resolver,
final String path, final Map<String, Object> props)
throws PersistenceException {
- PersistenceException mostRecentPE = null;
- for(int i=0;i<5;i++) {
- try {
- return ResourceUtil.getOrCreateResource(resolver,
+ return getOrCreateResource(resolver,
path,
props,
ResourceHelper.RESOURCE_TYPE_FOLDER,
true);
+ }
+
+ /**
+ * Creates or gets the resource at the given path.
+ * This is a copy of Sling's API ResourceUtil method to avoid a dependency on the latest
+ * Sling API version! We can remove this once we update to Sling API > 2.8
+ * @param resolver The resource resolver to use for creation
+ * @param path The full path to be created
+ * @param resourceType The optional resource type of the final resource to create
+ * @param intermediateResourceType THe optional resource type of all intermediate resources
+ * @param autoCommit If set to true, a commit is performed after each resource creation.
+ */
+ private static Resource getOrCreateResource(
+ final ResourceResolver resolver,
+ final String path,
+ final String resourceType,
+ final String intermediateResourceType,
+ final boolean autoCommit)
+ throws PersistenceException {
+ final Map<String, Object> props;
+ if ( resourceType == null ) {
+ props = null;
+ } else {
+ props = Collections.singletonMap(ResourceResolver.PROPERTY_RESOURCE_TYPE, (Object)resourceType);
+ }
+ return getOrCreateResource(resolver, path, props, intermediateResourceType, autoCommit);
+ }
+
+ /**
+ * Creates or gets the resource at the given path.
+ * If an exception occurs, it retries the operation up to five times if autoCommit is enabled.
+ * In this case, {@link ResourceResolver#revert()} is called on the resolver before the
+ * creation is retried.
+ * This is a copy of Sling's API ResourceUtil method to avoid a dependency on the latest
+ * Sling API version! We can remove this once we update to Sling API > 2.8
+ *
+ * @param resolver The resource resolver to use for creation
+ * @param path The full path to be created
+ * @param resourceProperties The optional resource properties of the final resource to create
+ * @param intermediateResourceType THe optional resource type of all intermediate resources
+ * @param autoCommit If set to true, a commit is performed after each resource creation.
+ */
+ private static Resource getOrCreateResource(
+ final ResourceResolver resolver,
+ final String path,
+ final Map<String, Object> resourceProperties,
+ final String intermediateResourceType,
+ final boolean autoCommit)
+ throws PersistenceException {
+ PersistenceException mostRecentPE = null;
+ for(int i=0;i<5;i++) {
+ try {
+ return getOrCreateResourceInternal(resolver,
+ path,
+ resourceProperties,
+ intermediateResourceType,
+ autoCommit);
+ } catch ( final PersistenceException pe ) {
+ if ( autoCommit ) {
+ // in case of exception, revert to last clean state and retry
+ resolver.revert();
+ resolver.refresh();
+ mostRecentPE = pe;
+ } else {
+ throw pe;
+ }
+ }
+ }
+ throw mostRecentPE;
+ }
+
+ /**
+ * Creates or gets the resource at the given path.
+ * This is a copy of Sling's API ResourceUtil method to avoid a dependency on the latest
+ * Sling API version! We can remove this once we update to Sling API > 2.8
+ *
+ * @param resolver The resource resolver to use for creation
+ * @param path The full path to be created
+ * @param resourceProperties The optional resource properties of the final resource to create
+ * @param intermediateResourceType THe optional resource type of all intermediate resources
+ * @param autoCommit If set to true, a commit is performed after each resource creation.
+ */
+ private static Resource getOrCreateResourceInternal(
+ final ResourceResolver resolver,
+ final String path,
+ final Map<String, Object> resourceProperties,
+ final String intermediateResourceType,
+ final boolean autoCommit)
+ throws PersistenceException {
+ Resource rsrc = resolver.getResource(path);
+ if ( rsrc == null ) {
+ final int lastPos = path.lastIndexOf('/');
+ final String name = path.substring(lastPos + 1);
+
+ final Resource parentResource;
+ if ( lastPos == 0 ) {
+ parentResource = resolver.getResource("/");
+ } else {
+ final String parentPath = path.substring(0, lastPos);
+ parentResource = getOrCreateResource(resolver,
+ parentPath,
+ intermediateResourceType,
+ intermediateResourceType,
+ autoCommit);
+ }
+ if ( autoCommit ) {
+ resolver.refresh();
+ }
+ try {
+ int retry = 5;
+ while ( retry > 0 && rsrc == null ) {
+ rsrc = resolver.create(parentResource, name, resourceProperties);
+ // check for SNS
+ if ( !name.equals(rsrc.getName()) ) {
+ resolver.refresh();
+ resolver.delete(rsrc);
+ rsrc = resolver.getResource(parentResource, name);
+ }
+ retry--;
+ }
+ if ( rsrc == null ) {
+ throw new PersistenceException("Unable to create resource.");
+ }
} catch ( final PersistenceException pe ) {
- //in case of exception, revert to last clean state and retry SLING-4014
- resolver.revert();
- mostRecentPE = pe;
+ // this could be thrown because someone else tried to create this
+ // node concurrently
+ resolver.refresh();
+ rsrc = resolver.getResource(parentResource, name);
+ if ( rsrc == null ) {
+ throw pe;
+ }
+ }
+ if ( autoCommit ) {
+ try {
+ resolver.commit();
+ resolver.refresh();
+ rsrc = resolver.getResource(parentResource, name);
+ } catch ( final PersistenceException pe ) {
+ // try again - maybe someone else did create the resource in the meantime
+ // or we ran into Jackrabbit's stale item exception in a clustered environment
+ resolver.revert();
+ resolver.refresh();
+ rsrc = resolver.getResource(parentResource, name);
+ if ( rsrc == null ) {
+ rsrc = resolver.create(parentResource, name, resourceProperties);
+ resolver.commit();
+ }
+ }
}
}
- throw new PersistenceException("Unable to create resource with path " + path, mostRecentPE);
+ return rsrc;
}
}
\ No newline at end of file