incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cziege...@apache.org
Subject svn commit: r1391014 - in /sling/trunk/bundles/servlets/post: ./ src/main/java/org/apache/sling/servlets/post/ src/main/java/org/apache/sling/servlets/post/impl/ src/main/java/org/apache/sling/servlets/post/impl/helper/ src/main/java/org/apache/sling/s...
Date Thu, 27 Sep 2012 13:52:05 GMT
Author: cziegeler
Date: Thu Sep 27 13:52:04 2012
New Revision: 1391014

URL: http://svn.apache.org/viewvc?rev=1391014&view=rev
Log:
SLING-2605 :  Use new CRUD support in POST servlet 

Modified:
    sling/trunk/bundles/servlets/post/pom.xml
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostOperation.java
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/SlingPostServlet.java
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingFileUploadHandler.java
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingPropertyValueHandler.java
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/AbstractCreateOperation.java
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/DeleteOperation.java
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ImportOperation.java
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ModifyOperation.java

Modified: sling/trunk/bundles/servlets/post/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/pom.xml?rev=1391014&r1=1391013&r2=1391014&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/pom.xml (original)
+++ sling/trunk/bundles/servlets/post/pom.xml Thu Sep 27 13:52:04 2012
@@ -116,7 +116,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.api</artifactId>
-            <version>2.1.0</version>
+            <version>2.2.5-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>

Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostOperation.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostOperation.java?rev=1391014&r1=1391013&r2=1391014&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostOperation.java (original)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostOperation.java Thu Sep 27 13:52:04 2012
@@ -57,20 +57,20 @@ public abstract class AbstractPostOperat
      * getting the absolute path of the item to operate on by calling the
      * {@link #getItemPath(SlingHttpServletRequest)} method and setting the
      * location and parent location on the response. After the operation has
-     * been done in the {@link #doRun(SlingHttpServletRequest, HtmlResponse, List)}
+     * been done in the {@link #doRun(SlingHttpServletRequest, PostResponse, List)}
      * method the session is saved if there are unsaved modifications. In case
      * of errorrs, the unsaved changes in the session are rolled back.
      *
      * @param request the request to operate on
-     * @param response The <code>HtmlResponse</code> to record execution
+     * @param response The <code>PostResponse</code> to record execution
      *            progress.
      */
-    public void run(SlingHttpServletRequest request,
-                    PostResponse response,
-                    SlingPostProcessor[] processors) {
-        Session session = request.getResourceResolver().adaptTo(Session.class);
+    public void run(final SlingHttpServletRequest request,
+                    final PostResponse response,
+                    final SlingPostProcessor[] processors) {
+        final Session session = request.getResourceResolver().adaptTo(Session.class);
 
-        VersioningConfiguration versionableConfiguration = getVersioningConfiguration(request);
+        final VersioningConfiguration versionableConfiguration = getVersioningConfiguration(request);
 
         try {
             // calculate the paths
@@ -98,7 +98,7 @@ public abstract class AbstractPostOperat
                 }
             }
 
-            Set<String> nodesToCheckin = new LinkedHashSet<String>();
+            final Set<String> nodesToCheckin = new LinkedHashSet<String>();
 
             // set changes on html response
             for(Modification change : changes) {
@@ -126,13 +126,13 @@ public abstract class AbstractPostOperat
             }
 
             if (isSessionSaveRequired(session, request)) {
-                session.save();
+                request.getResourceResolver().commit();
             }
 
             if (!isSkipCheckin(request)) {
                 // now do the checkins
                 for(String checkinPath : nodesToCheckin) {
-                    if (checkin(session, checkinPath)) {
+                    if (checkin(request.getResourceResolver(), checkinPath)) {
                         response.onChange("checkin", checkinPath);
                     }
                 }
@@ -146,7 +146,7 @@ public abstract class AbstractPostOperat
         } finally {
             try {
                 if (isSessionSaveRequired(session, request)) {
-                    session.refresh(false);
+                    request.getResourceResolver().revert();
                 }
             } catch (RepositoryException e) {
                 log.warn("RepositoryException in finally block: {}",
@@ -179,23 +179,35 @@ public abstract class AbstractPostOperat
             PostResponse response,
             List<Modification> changes) throws RepositoryException;
 
+    /**
+     * Get the versioning configuration.
+     */
     protected VersioningConfiguration getVersioningConfiguration(SlingHttpServletRequest request) {
         VersioningConfiguration versionableConfiguration =
             (VersioningConfiguration) request.getAttribute(VersioningConfiguration.class.getName());
         return versionableConfiguration != null ? versionableConfiguration : new VersioningConfiguration();
     }
 
+    /**
+     * Check if checkin should be skipped
+     */
     protected boolean isSkipCheckin(SlingHttpServletRequest request) {
         return !getVersioningConfiguration(request).isAutoCheckin();
     }
 
+    /**
+     * Check whether changes should be written back
+     */
     protected boolean isSkipSessionHandling(SlingHttpServletRequest request) {
         return Boolean.parseBoolean((String) request.getAttribute(SlingPostConstants.ATTR_SKIP_SESSION_HANDLING)) == true;
     }
 
+    /**
+     * Check whether commit to the resource resolver should be called.
+     */
     protected boolean isSessionSaveRequired(Session session, SlingHttpServletRequest request)
             throws RepositoryException {
-        return !isSkipSessionHandling(request) && session.hasPendingChanges();
+        return !isSkipSessionHandling(request) && request.getResourceResolver().hasChanges();
     }
 
     /**
@@ -209,12 +221,10 @@ public abstract class AbstractPostOperat
             if (!workspaceName.equals(session.getWorkspace().getName())) {
                 throw new RepositoryException("Incorrect workspace. Expecting " + workspaceName + ". Received "
                         + session.getWorkspace().getName());
-            } else {
-                return path.substring(wsSepPos + 1);
             }
-        } else {
-            return path;
+            return path.substring(wsSepPos + 1);
         }
+        return path;
     }
 
 
@@ -244,7 +254,7 @@ public abstract class AbstractPostOperat
     protected Iterator<Resource> getApplyToResources(
             SlingHttpServletRequest request) {
 
-        String[] applyTo = request.getParameterValues(SlingPostConstants.RP_APPLY_TO);
+        final String[] applyTo = request.getParameterValues(SlingPostConstants.RP_APPLY_TO);
         if (applyTo == null) {
             return null;
         }
@@ -428,14 +438,13 @@ public abstract class AbstractPostOperat
     protected Node findVersionableAncestor(Node node) throws RepositoryException {
         if (isVersionable(node)) {
             return node;
-        } else {
-            try {
-                node = node.getParent();
-                return findVersionableAncestor(node);
-            } catch (ItemNotFoundException e) {
-                // top-level
-                return null;
-            }
+        }
+        try {
+            node = node.getParent();
+            return findVersionableAncestor(node);
+        } catch (ItemNotFoundException e) {
+            // top-level
+            return null;
         }
     }
 
@@ -456,10 +465,10 @@ public abstract class AbstractPostOperat
         }
     }
 
-    private boolean checkin(Session session, String path) throws RepositoryException {
-        Item item = session.getItem(path);
-        if (item instanceof Node) {
-            Node node = (Node) item;
+    private boolean checkin(final ResourceResolver resolver, final String path) throws RepositoryException {
+        final Resource rsrc = resolver.getResource(path);
+        final Node node = (rsrc == null ? null : rsrc.adaptTo(Node.class));
+        if (node != null) {
             if (node.isCheckedOut() && isVersionable(node)) {
                 node.checkin();
                 return true;
@@ -479,7 +488,7 @@ public abstract class AbstractPostOperat
         private Resource nextResource;
 
         private Iterator<Resource> resourceIterator = null;
-        
+
         ApplyToIterator(SlingHttpServletRequest request, String[] paths) {
             this.resolver = request.getResourceResolver();
             this.baseResource = request.getResource();
@@ -514,9 +523,8 @@ public abstract class AbstractPostOperat
             		//return the next resource in the iterator
         			Resource res = resourceIterator.next();
         			return res;
-        		} else {
-        			resourceIterator = null;
-        		}
+                }
+    			resourceIterator = null;
         	}
             while (pathIndex < paths.length) {
                 String path = paths[pathIndex];
@@ -536,15 +544,14 @@ public abstract class AbstractPostOperat
                             	resourceIterator = res.listChildren();
                             }
                     	}
-                    } 
+                    }
                 	if (resourceIterator != null) {
                 		//return the first resource in the iterator
                 		if (resourceIterator.hasNext()) {
                 			Resource res = resourceIterator.next();
                 			return res;
-                		} else {
-                			resourceIterator = null;
                 		}
+                        resourceIterator = null;
                 	}
                 } else {
                     Resource res = resolver.getResource(baseResource, path);

Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/SlingPostServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/SlingPostServlet.java?rev=1391014&r1=1391013&r2=1391014&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/SlingPostServlet.java (original)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/SlingPostServlet.java Thu Sep 27 13:52:04 2012
@@ -226,7 +226,7 @@ public class SlingPostServlet extends Sl
 	/**
 	 * Redirects the HttpServletResponse, if redirectURL is not empty
 	 * @param redirectURL The computed redirect URL
-	 * @param response The HttpServletResponse to use for redirection 
+	 * @param response The HttpServletResponse to use for redirection
 	 * @return Whether a redirect was requested
 	 * @throws IOException
 	 */

Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingFileUploadHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingFileUploadHandler.java?rev=1391014&r1=1391013&r2=1391014&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingFileUploadHandler.java (original)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingFileUploadHandler.java Thu Sep 27 13:52:04 2012
@@ -28,6 +28,8 @@ import javax.servlet.ServletContext;
 
 import org.apache.jackrabbit.util.Text;
 import org.apache.sling.api.request.RequestParameter;
+import org.apache.sling.api.resource.PersistenceException;
+import org.apache.sling.api.resource.Resource;
 import org.apache.sling.servlets.post.Modification;
 
 /**
@@ -102,7 +104,7 @@ public class SlingFileUploadHandler {
      * @param prop the assembled property info
      * @throws RepositoryException if an error occurs
      */
-    public void setFile(Node parent, RequestProperty prop, List<Modification> changes)
+    private void setFile(Node parent, RequestProperty prop, List<Modification> changes)
             throws RepositoryException {
     	RequestParameter[] values = prop.getValues();
     	for (RequestParameter requestParameter : values) {
@@ -201,6 +203,26 @@ public class SlingFileUploadHandler {
 		}
     }
 
+    /**
+     * Uses the file(s) in the request parameter for creation of new nodes.
+     * if the parent node is a nt:folder a new nt:file is created. otherwise
+     * just a nt:resource. if the <code>name</code> is '*', the filename of
+     * the uploaded file is used.
+     *
+     * @param parent the parent node
+     * @param prop the assembled property info
+     * @throws RepositoryException if an error occurs
+     */
+    public void setFile(Resource parent, RequestProperty prop, List<Modification> changes)
+    throws RepositoryException, PersistenceException {
+        final Node node = parent.adaptTo(Node.class);
+        if ( node == null ) {
+            // TODO
+            throw new PersistenceException("Binary properties for resource '" + parent.getPath() + "' currently not supported.");
+        }
+        this.setFile(node, prop, changes);
+    }
+
     private Node getOrCreateChildNode(Node parent, String name, String typeHint,
             List<Modification> changes) throws RepositoryException {
         Node result;

Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingPropertyValueHandler.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingPropertyValueHandler.java?rev=1391014&r1=1391013&r2=1391014&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingPropertyValueHandler.java (original)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/SlingPropertyValueHandler.java Thu Sep 27 13:52:04 2012
@@ -27,10 +27,14 @@ import javax.jcr.Node;
 import javax.jcr.Property;
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
+import javax.jcr.Session;
 import javax.jcr.Value;
 import javax.jcr.ValueFactory;
 import javax.jcr.nodetype.ConstraintViolationException;
 
+import org.apache.sling.api.resource.ModifiableValueMap;
+import org.apache.sling.api.resource.PersistenceException;
+import org.apache.sling.api.resource.Resource;
 import org.apache.sling.servlets.post.Modification;
 import org.apache.sling.servlets.post.SlingPostConstants;
 
@@ -100,40 +104,48 @@ public class SlingPropertyValueHandler {
      * @param prop the request property
      * @throws RepositoryException if a repository error occurs
      */
-    public void setProperty(Node parent, RequestProperty prop)
-            throws RepositoryException {
+    public void setProperty(final Resource parent, final RequestProperty prop)
+    throws RepositoryException, PersistenceException {
+        final Modifiable mod = new Modifiable();
+        mod.resource = parent;
+        mod.node = parent.adaptTo(Node.class);
+        mod.valueMap = parent.adaptTo(ModifiableValueMap.class);
+        if ( mod.valueMap == null ) {
+            throw new PersistenceException("Resource at '" + parent.getPath() + "' is not modifiable.");
+        }
 
         final String name = prop.getName();
         if (prop.providesValue()) {
             // if user provided a value, don't mess with it
-            setPropertyAsIs(parent, prop);
+            setPropertyAsIs(mod, prop);
 
         } else if (AUTO_PROPS.containsKey(name)) {
             // avoid collision with protected properties
+            final boolean isNew = (mod.node != null ? mod.node.isNew() : true);
             try {
                 switch (AUTO_PROPS.get(name)) {
                     case CREATED:
-                        if (parent.isNew()) {
-                            setCurrentDate(parent, name);
+                        if (isNew) {
+                            setCurrentDate(mod, name);
                         }
                         break;
                     case CREATED_BY:
-                        if (parent.isNew()) {
-                            setCurrentUser(parent, name);
+                        if (isNew) {
+                            setCurrentUser(mod, name);
                         }
                         break;
                     case MODIFIED:
-                        setCurrentDate(parent, name);
+                        setCurrentDate(mod, name);
                         break;
                     case MODIFIED_BY:
-                        setCurrentUser(parent, name);
+                        setCurrentUser(mod, name);
                         break;
                 }
             } catch (ConstraintViolationException e) {
             }
         } else {
             // no magic field, set value as provided
-            setPropertyAsIs(parent, prop);
+            setPropertyAsIs(mod, prop);
         }
     }
 
@@ -143,12 +155,11 @@ public class SlingPropertyValueHandler {
      * @param name name of the property
      * @throws RepositoryException if a repository error occurs
      */
-    private void setCurrentDate(Node parent, String name)
-            throws RepositoryException {
+    private void setCurrentDate(Modifiable parent, String name)
+    throws RepositoryException, PersistenceException {
         removePropertyIfExists(parent, name);
-        changes.add(Modification.onModified(
-            parent.setProperty(name, now).getPath()
-        ));
+        parent.valueMap.put(name, now);
+        changes.add(Modification.onModified(parent.resource.getPath() + '/' + name));
     }
 
     /**
@@ -157,12 +168,12 @@ public class SlingPropertyValueHandler {
      * @param name name of the property
      * @throws RepositoryException if a repository error occurs
      */
-    private void setCurrentUser(Node parent, String name)
-            throws RepositoryException {
+    private void setCurrentUser(Modifiable parent, String name)
+    throws RepositoryException, PersistenceException {
         removePropertyIfExists(parent, name);
-        changes.add(Modification.onModified(
-            parent.setProperty(name, parent.getSession().getUserID()).getPath()
-        ));
+        final String user = parent.resource.getResourceResolver().getUserID();
+        parent.valueMap.put(name, user);
+        changes.add(Modification.onModified(parent.resource.getPath() + '/' + name));
     }
 
     /**
@@ -175,14 +186,19 @@ public class SlingPropertyValueHandler {
      *         it was not removed
      * @throws RepositoryException if a repository error occurs.
      */
-    private String removePropertyIfExists(Node parent, String name)
-            throws RepositoryException {
-        if (parent.hasProperty(name)) {
-            Property prop = parent.getProperty(name);
-            if (!prop.getDefinition().isMandatory()) {
-                String path = prop.getPath();
-                prop.remove();
-                return path;
+    private String removePropertyIfExists(final Modifiable parent, final String name)
+    throws RepositoryException, PersistenceException {
+        if (parent.valueMap.containsKey(name) ) {
+            if ( parent.node != null ) {
+                final Property prop = parent.node.getProperty(name);
+                if (!prop.getDefinition().isMandatory()) {
+                    final String path = prop.getPath();
+                    prop.remove();
+                    return path;
+                }
+            } else {
+                parent.valueMap.remove(name);
+                return parent.resource.getPath() + '/' + name;
             }
         }
         return null;
@@ -195,8 +211,8 @@ public class SlingPropertyValueHandler {
      * @param prop the request property
      * @throws RepositoryException if a repository error occurs.
      */
-    private void setPropertyAsIs(Node parent, RequestProperty prop)
-            throws RepositoryException {
+    private void setPropertyAsIs(final Modifiable parent, final RequestProperty prop)
+    throws RepositoryException, PersistenceException {
 
         String[] values = prop.getStringValues();
 
@@ -218,7 +234,8 @@ public class SlingPropertyValueHandler {
                 }
             }
 
-            final ValueFactory valFac = parent.getSession().getValueFactory();
+            // TODO - we should check for session
+            final ValueFactory valFac = parent.resource.getResourceResolver().adaptTo(Session.class).getValueFactory();
 
             final boolean multiValue = isMultiValue(parent, prop, values);
             final int type = getType(parent, prop);
@@ -245,7 +262,8 @@ public class SlingPropertyValueHandler {
     /**
      * Patches a multi-value property using add and remove operations per value.
      */
-    private String[] patch(Node parent, String name, String[] values) throws RepositoryException {
+    private String[] patch(final Modifiable parent, String name, String[] values)
+    throws RepositoryException, PersistenceException {
         // we do not use a Set here, as we want to be very restrictive in our
         // actions and avoid touching elements that are not modified through the
         // add/remove patch operations; e.g. if the value "foo" occurs twice
@@ -253,16 +271,25 @@ public class SlingPropertyValueHandler {
         // still be two times "foo" in the list, even if this is not a real set.
         List<String> oldValues = new ArrayList<String>();
 
-        if (parent.hasProperty(name)) {
-            Property p = parent.getProperty(name);
-
-            // can only patch multi-value props
-            if (!p.getDefinition().isMultiple()) {
-                return null;
-            }
+        if (parent.valueMap.containsKey(name)) {
+            if ( parent.node != null ) {
+                final Property p = parent.node.getProperty(name);
+
+                // can only patch multi-value props
+                if (!p.getDefinition().isMultiple()) {
+                    return null;
+                }
 
-            for (Value v : p.getValues()) {
-                oldValues.add(v.getString());
+                for (Value v : p.getValues()) {
+                    oldValues.add(v.getString());
+                }
+            } else {
+                final String[] setValues = parent.valueMap.get(name, String[].class);
+                if ( setValues != null ) {
+                    for(final String v : setValues) {
+                        oldValues.add(v);
+                    }
+                }
             }
         }
 
@@ -308,7 +335,7 @@ public class SlingPropertyValueHandler {
      * either by an explicit type hint in the request or simply the type of the
      * existing property.
      */
-    private int getType(Node parent, RequestProperty prop) throws RepositoryException {
+    private int getType(final Modifiable parent, RequestProperty prop) throws RepositoryException {
         // no explicit typehint
         int type = PropertyType.UNDEFINED;
         if (prop.getTypeHint() != null) {
@@ -320,8 +347,10 @@ public class SlingPropertyValueHandler {
         }
         String[] values = prop.getStringValues();
         if ( type == PropertyType.UNDEFINED && values != null && values.length > 0 ) {
-            if ( parent.hasProperty(prop.getName()) ) {
-                type = parent.getProperty(prop.getName()).getType();
+            if ( parent.node != null ) {
+                if ( parent.node.hasProperty(prop.getName()) ) {
+                    type = parent.node.getProperty(prop.getName()).getType();
+                }
             }
         }
         return type;
@@ -330,7 +359,7 @@ public class SlingPropertyValueHandler {
     /**
      * Returns whether the property should be handled as multi-valued.
      */
-    private boolean isMultiValue(Node parent, RequestProperty prop, String[] values) throws RepositoryException {
+    private boolean isMultiValue(final Modifiable parent, RequestProperty prop, String[] values) throws RepositoryException {
         // multiple values are provided
         if (values != null && values.length > 1) {
             return true;
@@ -344,8 +373,15 @@ public class SlingPropertyValueHandler {
             return true;
         }
         // nothing in the request, so check the current JCR property definition
-        if (parent.hasProperty(prop.getName()) ) {
-            return parent.getProperty(prop.getName()).getDefinition().isMultiple();
+        if ( parent.node != null ) {
+            if (parent.node.hasProperty(prop.getName()) ) {
+                return parent.node.getProperty(prop.getName()).getDefinition().isMultiple();
+            }
+        } else {
+            final Object value = parent.valueMap.get(prop.getName());
+            if ( value != null && value.getClass().isArray() ) {
+                return true;
+            }
         }
         return false;
     }
@@ -354,18 +390,24 @@ public class SlingPropertyValueHandler {
      * Clears a property: sets an empty string for single-value properties, and
      * removes multi-value properties.
      */
-    private void clearProperty(Node parent, RequestProperty prop) throws RepositoryException {
-        if (parent.hasProperty(prop.getName())) {
-            if (parent.getProperty(prop.getName()).getDefinition().isMultiple()) {
-                //the existing property is multi-valued, so just delete it?
-                final String removePath = removePropertyIfExists(parent, prop.getName());
-                if ( removePath != null ) {
-                    changes.add(Modification.onDeleted(removePath));
+    private void clearProperty(final Modifiable parent, RequestProperty prop)
+    throws RepositoryException, PersistenceException {
+        if (parent.valueMap.containsKey(prop.getName())) {
+            if ( parent.node != null ) {
+                if (parent.node.getProperty(prop.getName()).getDefinition().isMultiple()) {
+                    //the existing property is multi-valued, so just delete it?
+                    final String removePath = removePropertyIfExists(parent, prop.getName());
+                    if ( removePath != null ) {
+                        changes.add(Modification.onDeleted(removePath));
+                    }
+                } else {
+                    changes.add(Modification.onModified(
+                                    parent.node.setProperty(prop.getName(), "").getPath()
+                    ));
                 }
             } else {
-                changes.add(Modification.onModified(
-                    parent.setProperty(prop.getName(), "").getPath()
-                ));
+                parent.valueMap.put(prop.getName(), "");
+                changes.add(Modification.onModified(parent.resource.getPath() + '/' + prop.getName()));
             }
         }
     }
@@ -373,7 +415,8 @@ public class SlingPropertyValueHandler {
     /**
      * Removes the property if it exists.
      */
-    private void removeProperty(Node parent, RequestProperty prop) throws RepositoryException {
+    private void removeProperty(final Modifiable parent, RequestProperty prop)
+    throws RepositoryException, PersistenceException {
         final String removePath = removePropertyIfExists(parent, prop.getName());
         if ( removePath != null ) {
             changes.add(Modification.onDeleted(removePath));
@@ -383,11 +426,20 @@ public class SlingPropertyValueHandler {
     /**
      * Removes the property if it exists and is single-valued.
      */
-    private void removeIfSingleValueProperty(Node parent, RequestProperty prop) throws RepositoryException {
-        if (parent.hasProperty(prop.getName())) {
-            if (!parent.getProperty(prop.getName()).getDefinition().isMultiple()) {
-                // the existing property is single-valued, so we have to delete it before setting the
-                // multi-value variation
+    private void removeIfSingleValueProperty(final Modifiable parent,
+                    final RequestProperty prop)
+    throws RepositoryException, PersistenceException {
+        if (parent.valueMap.containsKey(prop.getName())) {
+            if ( parent.node != null ) {
+                if (!parent.node.getProperty(prop.getName()).getDefinition().isMultiple()) {
+                    // the existing property is single-valued, so we have to delete it before setting the
+                    // multi-value variation
+                    final String removePath = removePropertyIfExists(parent, prop.getName());
+                    if ( removePath != null ) {
+                        changes.add(Modification.onDeleted(removePath));
+                    }
+                }
+            } else {
                 final String removePath = removePropertyIfExists(parent, prop.getName());
                 if ( removePath != null ) {
                     changes.add(Modification.onDeleted(removePath));
@@ -402,22 +454,32 @@ public class SlingPropertyValueHandler {
      *
      * @return true only if parsing was successfull and the property was actually changed
      */
-    private boolean storeAsDate(Node parent, String name, String[] values, boolean multiValued, ValueFactory valFac) throws RepositoryException {
+    private boolean storeAsDate(final Modifiable parent, String name, String[] values, boolean multiValued, ValueFactory valFac)
+                    throws RepositoryException, PersistenceException {
         if (multiValued) {
-            Value[] array = dateParser.parse(values, valFac);
+            final Value[] array = dateParser.parse(values, valFac);
             if (array != null) {
-                changes.add(Modification.onModified(
-                    parent.setProperty(name, array).getPath()
-                ));
+                if ( parent.node != null ) {
+                    parent.node.setProperty(name, array);
+                } else {
+                    final Calendar[] dates = new Calendar[array.length];
+                    int index = 0;
+                    for(final Value v : array) {
+                        dates[index] = v.getDate();
+                        index++;
+                    }
+                    parent.valueMap.put(name, dates);
+                }
+                changes.add(Modification.onModified(parent.resource.getPath() + '/' + name));
                 return true;
             }
         } else {
             if (values.length >= 1) {
-                Calendar c = dateParser.parse(values[0]);
+                final Calendar c = dateParser.parse(values[0]);
                 if (c != null) {
-                    changes.add(Modification.onModified(
-                        parent.setProperty(name, c).getPath()
-                    ));
+                    parent.valueMap.put(name, c);
+                    changes.add(Modification.onModified(parent.resource.getPath() + '/' + name));
+
                     return true;
                 }
             }
@@ -431,12 +493,17 @@ public class SlingPropertyValueHandler {
      *
      * @return true only if parsing was successfull and the property was actually changed
      */
-    private boolean storeAsReference(Node parent, String name, String[] values, int type, boolean multiValued, ValueFactory valFac) throws RepositoryException {
+    private boolean storeAsReference(final Modifiable parent, String name, String[] values, int type, boolean multiValued, ValueFactory valFac)
+    throws RepositoryException, PersistenceException {
+        if ( parent.node == null ) {
+            // TODO
+            throw new PersistenceException("Resource " + parent.resource.getPath() + " does not support reference properties.");
+        }
         if (multiValued) {
             Value[] array = referenceParser.parse(values, valFac, isWeakReference(type));
             if (array != null) {
                 changes.add(Modification.onModified(
-                    parent.setProperty(name, array).getPath()
+                                parent.node.setProperty(name, array).getPath()
                 ));
                 return true;
             }
@@ -445,7 +512,7 @@ public class SlingPropertyValueHandler {
                 Value v = referenceParser.parse(values[0], valFac, isWeakReference(type));
                 if (v != null) {
                     changes.add(Modification.onModified(
-                        parent.setProperty(name, v).getPath()
+                                    parent.node.setProperty(name, v).getPath()
                     ));
                     return true;
                 }
@@ -458,26 +525,42 @@ public class SlingPropertyValueHandler {
      * Stores the property as string or via a strign value, but with an explicit
      * type. Both multi-value or single-value.
      */
-    private void store(Node parent, String name, String[] values, int type, boolean multiValued /*, ValueFactory valFac */) throws RepositoryException {
-        Property p = null;
+    private void store(final Modifiable parent,
+                    final String name,
+                    final String[] values,
+                    final int type,
+                    final boolean multiValued)
+    throws RepositoryException, PersistenceException {
+        // TODO
+        if ( parent.node != null ) {
+            Property p = null;
+
+            if (multiValued) {
+                if (type == PropertyType.UNDEFINED) {
+                    p = parent.node.setProperty(name, values);
+                } else {
+                    p = parent.node.setProperty(name, values, type);
+                }
+            } else if (values.length >= 1) {
+                if (type == PropertyType.UNDEFINED) {
+                    p = parent.node.setProperty(name, values[0]);
+                } else {
+                    p = parent.node.setProperty(name, values[0], type);
+                }
+            }
 
-        if (multiValued) {
-            if (type == PropertyType.UNDEFINED) {
-                p = parent.setProperty(name, values);
-            } else {
-                p = parent.setProperty(name, values, type);
+            if (p != null) {
+                changes.add(Modification.onModified(p.getPath()));
             }
-        } else if (values.length >= 1) {
-            if (type == PropertyType.UNDEFINED) {
-                p = parent.setProperty(name, values[0]);
-            } else {
-                p = parent.setProperty(name, values[0], type);
+        } else {
+            if (multiValued) {
+                parent.valueMap.put(name, values);
+                changes.add(Modification.onModified(parent.resource.getPath() + '/' + name));
+            } else if (values.length >= 1) {
+                parent.valueMap.put(name, values[0]);
+                changes.add(Modification.onModified(parent.resource.getPath() + '/' + name));
             }
         }
-
-        if (p != null) {
-            changes.add(Modification.onModified(p.getPath()));
-        }
     }
 
     /**
@@ -489,4 +572,10 @@ public class SlingPropertyValueHandler {
         MODIFIED,
         MODIFIED_BY
     }
+
+    public final static class Modifiable {
+        public Resource resource;
+        public ModifiableValueMap valueMap;
+        public Node node;
+    }
 }

Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/AbstractCreateOperation.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/AbstractCreateOperation.java?rev=1391014&r1=1391013&r2=1391014&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/AbstractCreateOperation.java (original)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/AbstractCreateOperation.java Thu Sep 27 13:52:04 2012
@@ -18,13 +18,14 @@
 package org.apache.sling.servlets.post.impl.operations;
 
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.regex.Pattern;
-import javax.jcr.Item;
+
 import javax.jcr.Node;
 import javax.jcr.PathNotFoundException;
 import javax.jcr.RepositoryException;
@@ -34,10 +35,15 @@ import javax.jcr.nodetype.ConstraintViol
 import javax.jcr.nodetype.NoSuchNodeTypeException;
 import javax.jcr.nodetype.NodeType;
 import javax.jcr.version.VersionException;
+import javax.servlet.ServletException;
 
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.request.RequestParameter;
 import org.apache.sling.api.request.RequestParameterMap;
+import org.apache.sling.api.resource.ModifiableValueMap;
+import org.apache.sling.api.resource.PersistenceException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.servlets.post.AbstractPostOperation;
 import org.apache.sling.servlets.post.Modification;
@@ -89,100 +95,123 @@ abstract class AbstractCreateOperation e
      *
      * @throws RepositoryException if a repository error occurs
      */
-    protected void processCreate(Session session,
-            Map<String, RequestProperty> reqProperties, PostResponse response, List<Modification> changes,
-            VersioningConfiguration versioningConfiguration)
-            throws RepositoryException {
+    protected void processCreate(final ResourceResolver resolver,
+            final Map<String, RequestProperty> reqProperties,
+            final PostResponse response,
+            final List<Modification> changes,
+            final VersioningConfiguration versioningConfiguration)
+    throws PersistenceException, RepositoryException {
 
-        String path = response.getPath();
+        final String path = response.getPath();
 
-        if (!session.itemExists(path)) {
+        if ( resolver.getResource(path) == null ) {
 
-            deepGetOrCreateNode(session, path, reqProperties, changes, versioningConfiguration);
+            deepGetOrCreateNode(resolver, path, reqProperties, changes, versioningConfiguration);
             response.setCreateRequest(true);
 
         } else {
-            updateNodeType(session, path, reqProperties, changes, versioningConfiguration);
-            updateMixins(session, path, reqProperties, changes, versioningConfiguration);
+            updateNodeType(resolver, path, reqProperties, changes, versioningConfiguration);
+            updateMixins(resolver, path, reqProperties, changes, versioningConfiguration);
         }
     }
 
-    protected void updateNodeType(Session session, String path, Map<String, RequestProperty> reqProperties,
-            List<Modification> changes, VersioningConfiguration versioningConfiguration) throws PathNotFoundException,
+    protected void updateNodeType(final ResourceResolver resolver,
+                    final String path,
+                    final Map<String, RequestProperty> reqProperties,
+                    final List<Modification> changes,
+                    final VersioningConfiguration versioningConfiguration)
+   throws PathNotFoundException,
             RepositoryException, NoSuchNodeTypeException, VersionException, ConstraintViolationException, LockException {
-        String nodeType = getPrimaryType(reqProperties, path);
+        final String nodeType = getPrimaryType(reqProperties, path);
         if (nodeType != null) {
-            Item item = session.getItem(path);
-            if (item.isNode()) {
-                Node node = (Node) item;
-                boolean wasVersionable = isVersionable(node);
-
-                checkoutIfNecessary(node, changes, versioningConfiguration);
-                node.setPrimaryType(nodeType);
+            final Resource rsrc = resolver.getResource(path);
+            final ModifiableValueMap mvm = rsrc.adaptTo(ModifiableValueMap.class);
+            if ( mvm != null ) {
+                final Node node = rsrc.adaptTo(Node.class);
+                final boolean wasVersionable = (node == null ? false : isVersionable(node));
+
+                if ( node != null ) {
+                    checkoutIfNecessary(node, changes, versioningConfiguration);
+                    node.setPrimaryType(nodeType);
+                } else {
+                    mvm.put("jcr:primaryType", nodeType);
+                }
 
-                // this is a bit of a cheat; there isn't a formal checkout, but assigning
-                // the mix:versionable mixin does an implicit checkout
-                if (!wasVersionable &&
-                        versioningConfiguration.isCheckinOnNewVersionableNode() &&
-                        isVersionable(node)) {
-                    changes.add(Modification.onCheckout(path));
+                if ( node != null ) {
+                    // this is a bit of a cheat; there isn't a formal checkout, but assigning
+                    // the mix:versionable mixin does an implicit checkout
+                    if (!wasVersionable &&
+                            versioningConfiguration.isCheckinOnNewVersionableNode() &&
+                            isVersionable(node)) {
+                        changes.add(Modification.onCheckout(path));
+                    }
                 }
             }
         }
     }
 
-    protected void updateMixins(Session session, String path, Map<String, RequestProperty> reqProperties,
-            List<Modification> changes, VersioningConfiguration versioningConfiguration) throws PathNotFoundException,
+    protected void updateMixins(final ResourceResolver resolver,
+                    final String path,
+                    final Map<String, RequestProperty> reqProperties,
+                    final List<Modification> changes,
+                    final VersioningConfiguration versioningConfiguration)
+    throws PathNotFoundException,
             RepositoryException, NoSuchNodeTypeException, VersionException, ConstraintViolationException, LockException {
-        String[] mixins = getMixinTypes(reqProperties, path);
+        final String[] mixins = getMixinTypes(reqProperties, path);
         if (mixins != null) {
 
-            Item item = session.getItem(path);
-            if (item.isNode()) {
+            final Resource rsrc = resolver.getResource(path);
+            final ModifiableValueMap mvm = rsrc.adaptTo(ModifiableValueMap.class);
+            if ( mvm != null ) {
+                final Node node = rsrc.adaptTo(Node.class);
 
-                Set<String> newMixins = new HashSet<String>();
+                final Set<String> newMixins = new HashSet<String>();
                 newMixins.addAll(Arrays.asList(mixins));
 
                 // clear existing mixins first
-                Node node = (Node) item;
-                checkoutIfNecessary(node, changes, versioningConfiguration);
-
-                for (NodeType mixin : node.getMixinNodeTypes()) {
-                    String mixinName = mixin.getName();
-                    if (!newMixins.remove(mixinName)) {
-                        node.removeMixin(mixinName);
+                if ( node != null ) {
+                    checkoutIfNecessary(node, changes, versioningConfiguration);
+                    for (NodeType mixin : node.getMixinNodeTypes()) {
+                        String mixinName = mixin.getName();
+                        if (!newMixins.remove(mixinName)) {
+                            node.removeMixin(mixinName);
+                        }
                     }
-                }
 
-                // add new mixins
-                for (String mixin : newMixins) {
-                    node.addMixin(mixin);
-                    // this is a bit of a cheat; there isn't a formal checkout, but assigning
-                    // the mix:versionable mixin does an implicit checkout
-                    if (mixin.equals("mix:versionable") &&
-                            versioningConfiguration.isCheckinOnNewVersionableNode()) {
-                        changes.add(Modification.onCheckout(path));
+                    // add new mixins
+                    for (String mixin : newMixins) {
+                        node.addMixin(mixin);
+                        // this is a bit of a cheat; there isn't a formal checkout, but assigning
+                        // the mix:versionable mixin does an implicit checkout
+                        if (mixin.equals("mix:versionable") &&
+                                versioningConfiguration.isCheckinOnNewVersionableNode()) {
+                            changes.add(Modification.onCheckout(path));
+                        }
                     }
+                } else {
+                    mvm.put("jcr:mixinTypes", mixins);
                 }
+
             }
         }
     }
 
     /**
      * Collects the properties that form the content to be written back to the
-     * repository.
+     * resource tree.
      *
      * @throws RepositoryException if a repository error occurs
      * @throws ServletException if an internal error occurs
      */
     protected Map<String, RequestProperty> collectContent(
-            SlingHttpServletRequest request, PostResponse response) {
+            final SlingHttpServletRequest request,
+            final PostResponse response) {
 
-        boolean requireItemPrefix = requireItemPathPrefix(request);
+        final boolean requireItemPrefix = requireItemPathPrefix(request);
 
         // walk the request parameters and collect the properties
-        LinkedHashMap<String, RequestProperty> reqProperties = new LinkedHashMap<String, RequestProperty>();
-        for (Map.Entry<String, RequestParameter[]> e : request.getRequestParameterMap().entrySet()) {
+        final LinkedHashMap<String, RequestProperty> reqProperties = new LinkedHashMap<String, RequestProperty>();
+        for (final Map.Entry<String, RequestParameter[]> e : request.getRequestParameterMap().entrySet()) {
             final String paramName = e.getKey();
 
             if (ignoreParameter(paramName)) {
@@ -195,14 +224,14 @@ abstract class AbstractCreateOperation e
             }
 
             // ensure the paramName is an absolute property name
-            String propPath = toPropertyPath(paramName, response);
+            final String propPath = toPropertyPath(paramName, response);
 
             // @TypeHint example
             // <input type="text" name="./age" />
             // <input type="hidden" name="./age@TypeHint" value="long" />
             // causes the setProperty using the 'long' property type
             if (propPath.endsWith(SlingPostConstants.TYPE_HINT_SUFFIX)) {
-                RequestProperty prop = getOrCreateRequestProperty(
+                final RequestProperty prop = getOrCreateRequestProperty(
                     reqProperties, propPath,
                     SlingPostConstants.TYPE_HINT_SUFFIX);
 
@@ -216,7 +245,7 @@ abstract class AbstractCreateOperation e
 
             // @DefaultValue
             if (propPath.endsWith(SlingPostConstants.DEFAULT_VALUE_SUFFIX)) {
-                RequestProperty prop = getOrCreateRequestProperty(
+                final RequestProperty prop = getOrCreateRequestProperty(
                     reqProperties, propPath,
                     SlingPostConstants.DEFAULT_VALUE_SUFFIX);
 
@@ -232,14 +261,14 @@ abstract class AbstractCreateOperation e
             // causes the JCR Text property to be set to the value of the
             // fulltext form field.
             if (propPath.endsWith(SlingPostConstants.VALUE_FROM_SUFFIX)) {
-                RequestProperty prop = getOrCreateRequestProperty(
+                final RequestProperty prop = getOrCreateRequestProperty(
                     reqProperties, propPath,
                     SlingPostConstants.VALUE_FROM_SUFFIX);
 
                 // @ValueFrom params must have exactly one value, else ignored
                 if (e.getValue().length == 1) {
-                    String refName = e.getValue()[0].getString();
-                    RequestParameter[] refValues = request.getRequestParameters(refName);
+                    final String refName = e.getValue()[0].getString();
+                    final RequestParameter[] refValues = request.getRequestParameters(refName);
                     if (refValues != null) {
                         prop.setValues(refValues);
                     }
@@ -253,7 +282,7 @@ abstract class AbstractCreateOperation e
             // <input name="./Text@Delete" type="hidden" />
             // causes the JCR Text property to be deleted before update
             if (propPath.endsWith(SlingPostConstants.SUFFIX_DELETE)) {
-                RequestProperty prop = getOrCreateRequestProperty(
+                final RequestProperty prop = getOrCreateRequestProperty(
                     reqProperties, propPath, SlingPostConstants.SUFFIX_DELETE);
 
                 prop.setDelete(true);
@@ -267,13 +296,13 @@ abstract class AbstractCreateOperation e
             // causes the JCR Text property to be set by moving the /tmp/path
             // property to Text.
             if (propPath.endsWith(SlingPostConstants.SUFFIX_MOVE_FROM)) {
-                RequestProperty prop = getOrCreateRequestProperty(
+                final RequestProperty prop = getOrCreateRequestProperty(
                     reqProperties, propPath,
                     SlingPostConstants.SUFFIX_MOVE_FROM);
 
                 // @MoveFrom params must have exactly one value, else ignored
                 if (e.getValue().length == 1) {
-                    String sourcePath = e.getValue()[0].getString();
+                    final String sourcePath = e.getValue()[0].getString();
                     prop.setRepositorySource(sourcePath, true);
                 }
 
@@ -286,13 +315,13 @@ abstract class AbstractCreateOperation e
             // causes the JCR Text property to be set by copying the /tmp/path
             // property to Text.
             if (propPath.endsWith(SlingPostConstants.SUFFIX_COPY_FROM)) {
-                RequestProperty prop = getOrCreateRequestProperty(
+                final RequestProperty prop = getOrCreateRequestProperty(
                     reqProperties, propPath,
                     SlingPostConstants.SUFFIX_COPY_FROM);
 
                 // @MoveFrom params must have exactly one value, else ignored
                 if (e.getValue().length == 1) {
-                    String sourcePath = e.getValue()[0].getString();
+                    final String sourcePath = e.getValue()[0].getString();
                     prop.setRepositorySource(sourcePath, false);
                 }
 
@@ -308,7 +337,7 @@ abstract class AbstractCreateOperation e
             // causes the JCR Text property to be set by copying the /tmp/path
             // property to Text.
             if (propPath.endsWith(SlingPostConstants.SUFFIX_IGNORE_BLANKS)) {
-                RequestProperty prop = getOrCreateRequestProperty(
+                final RequestProperty prop = getOrCreateRequestProperty(
                     reqProperties, propPath,
                     SlingPostConstants.SUFFIX_IGNORE_BLANKS);
 
@@ -320,7 +349,7 @@ abstract class AbstractCreateOperation e
             }
 
             if (propPath.endsWith(SlingPostConstants.SUFFIX_USE_DEFAULT_WHEN_MISSING)) {
-                RequestProperty prop = getOrCreateRequestProperty(
+                final RequestProperty prop = getOrCreateRequestProperty(
                     reqProperties, propPath,
                     SlingPostConstants.SUFFIX_USE_DEFAULT_WHEN_MISSING);
 
@@ -337,7 +366,7 @@ abstract class AbstractCreateOperation e
             // <input name="tags"          value="+apple" type="hidden" />
             // <input name="tags"          value="-orange" type="hidden" />
             if (propPath.endsWith(SlingPostConstants.SUFFIX_PATCH)) {
-                RequestProperty prop = getOrCreateRequestProperty(
+                final RequestProperty prop = getOrCreateRequestProperty(
                         reqProperties, propPath,
                         SlingPostConstants.SUFFIX_PATCH);
 
@@ -347,7 +376,7 @@ abstract class AbstractCreateOperation e
             }
 
             // plain property, create from values
-            RequestProperty prop = getOrCreateRequestProperty(reqProperties,
+            final RequestProperty prop = getOrCreateRequestProperty(reqProperties,
                 propPath, null);
             prop.setValues(e.getValue());
         }
@@ -432,85 +461,89 @@ abstract class AbstractCreateOperation e
      * @throws IllegalArgumentException if the path is relative and parent is
      *             <code>null</code>
      */
-    protected Node deepGetOrCreateNode(Session session, String path,
-            Map<String, RequestProperty> reqProperties, List<Modification> changes,
-            VersioningConfiguration versioningConfiguration)
-            throws RepositoryException {
+    protected Resource deepGetOrCreateNode(final ResourceResolver resolver,
+                    final String path,
+                    final Map<String, RequestProperty> reqProperties,
+                    final List<Modification> changes,
+                    final VersioningConfiguration versioningConfiguration)
+    throws PersistenceException, RepositoryException {
         if (log.isDebugEnabled()) {
-            log.debug("Deep-creating Node '{}'", path);
+            log.debug("Deep-creating resource '{}'", path);
         }
         if (path == null || !path.startsWith("/")) {
             throw new IllegalArgumentException("path must be an absolute path.");
         }
-        // get the starting node
-        String startingNodePath = path;
-        Node startingNode = null;
-        while (startingNode == null) {
-            if (startingNodePath.equals("/")) {
-                startingNode = session.getRootNode();
-            } else if (session.itemExists(startingNodePath)) {
-                startingNode = (Node) session.getItem(startingNodePath);
-                updateNodeType(session, startingNodePath, reqProperties, changes, versioningConfiguration);
-                updateMixins(session, startingNodePath, reqProperties, changes, versioningConfiguration);
+        // get the starting resource
+        String startingResourcePath = path;
+        Resource startingResource = null;
+        while (startingResource == null) {
+            if (startingResourcePath.equals("/")) {
+                startingResource = resolver.getResource("/");
+            } else if (resolver.getResource(startingResourcePath) != null) {
+                startingResource = resolver.getResource(startingResourcePath);
+                updateNodeType(resolver, startingResourcePath, reqProperties, changes, versioningConfiguration);
+                updateMixins(resolver, startingResourcePath, reqProperties, changes, versioningConfiguration);
             } else {
-                int pos = startingNodePath.lastIndexOf('/');
+                int pos = startingResourcePath.lastIndexOf('/');
                 if (pos > 0) {
-                    startingNodePath = startingNodePath.substring(0, pos);
+                    startingResourcePath = startingResourcePath.substring(0, pos);
                 } else {
-                    startingNodePath = "/";
+                    startingResourcePath = "/";
                 }
             }
         }
-        // is the searched node already existing?
-        if (startingNodePath.length() == path.length()) {
-            return startingNode;
+        // is the searched resource already existing?
+        if (startingResourcePath.length() == path.length()) {
+            return startingResource;
         }
         // create nodes
-        int from = (startingNodePath.length() == 1
+        int from = (startingResourcePath.length() == 1
                 ? 1
-                : startingNodePath.length() + 1);
-        Node node = startingNode;
+                : startingResourcePath.length() + 1);
+        Resource resource = startingResource;
         while (from > 0) {
             final int to = path.indexOf('/', from);
             final String name = to < 0 ? path.substring(from) : path.substring(
                 from, to);
-            // although the node should not exist (according to the first test
+            // although the resource should not exist (according to the first test
             // above)
             // we do a sanety check.
-            if (node.hasNode(name)) {
-                node = node.getNode(name);
-                updateNodeType(session, node.getPath(), reqProperties, changes, versioningConfiguration);
-                updateMixins(session, node.getPath(), reqProperties, changes, versioningConfiguration);
+            if (resource.getChild(name) != null) {
+                resource = resource.getChild(name);
+                updateNodeType(resolver, resource.getPath(), reqProperties, changes, versioningConfiguration);
+                updateMixins(resolver, resource.getPath(), reqProperties, changes, versioningConfiguration);
             } else {
                 final String tmpPath = to < 0 ? path : path.substring(0, to);
                 // check for node type
                 final String nodeType = getPrimaryType(reqProperties, tmpPath);
-                checkoutIfNecessary(node, changes, versioningConfiguration);
+
+                final Node node = resource.adaptTo(Node.class);
+                if ( node != null ) {
+                    checkoutIfNecessary(node, changes, versioningConfiguration);
+                }
 
                 try {
+                    final Map<String, Object> props = new HashMap<String, Object>();
                     if (nodeType != null) {
-                        node = node.addNode(name, nodeType);
-                    } else {
-                        node = node.addNode(name);
-
+                        props.put("jcr:primaryType", nodeType);
                     }
-                } catch (VersionException e) {
-                    log.error("Unable to create node named " + name + " in "+node.getPath());
-                    throw e;
-                }
-                // check for mixin types
-                final String[] mixinTypes = getMixinTypes(reqProperties,
-                    tmpPath);
-                if (mixinTypes != null) {
-                    for (String mix : mixinTypes) {
-                        node.addMixin(mix);
+                    // check for mixin types
+                    final String[] mixinTypes = getMixinTypes(reqProperties,
+                        tmpPath);
+                    if (mixinTypes != null) {
+                        props.put("jcr:mixinTypes", mixinTypes);
                     }
+
+                    resource = resolver.create(resource, name, props);
+                } catch (final PersistenceException e) {
+                    log.error("Unable to create resource named " + name + " in " + resource.getPath());
+                    throw e;
                 }
-                changes.add(Modification.onCreated(node.getPath()));
+                changes.add(Modification.onCreated(resource.getPath()));
             }
             from = to + 1;
         }
-        return node;
+        return resource;
     }
 
     /**
@@ -558,7 +591,7 @@ abstract class AbstractCreateOperation e
 		        // if the resulting path already exists then report an error
 		        Session session = request.getResourceResolver().adaptTo(Session.class);
 	            String jcrPath = removeAndValidateWorkspace(basePath, session);
-	            if (session.itemExists(jcrPath)) {
+	            if (request.getResourceResolver().getResource(jcrPath) != null) {
 	    		    throw new RepositoryException(
 	    			        "Collision in node names for path=" + basePath);
 	            }
@@ -595,28 +628,29 @@ abstract class AbstractCreateOperation e
     private String ensureUniquePath(SlingHttpServletRequest request, String basePath) throws RepositoryException {
 		// if resulting path exists, add a suffix until it's not the case
 		// anymore
-		Session session = request.getResourceResolver().adaptTo(Session.class);
+		final Session session = request.getResourceResolver().adaptTo(Session.class);
+        final ResourceResolver resolver = request.getResourceResolver();
 
 		String jcrPath = removeAndValidateWorkspace(basePath, session);
 
 		// if resulting path exists, add a suffix until it's not the case
 		// anymore
-		if (session.itemExists(jcrPath)) {
+		if (resolver.getResource(jcrPath) != null ) {
 		    for (int idx = 0; idx < 1000; idx++) {
 		        String newPath = jcrPath + "_" + idx;
-		        if (!session.itemExists(newPath)) {
+		        if (resolver.getResource(newPath) == null) {
 		            basePath = basePath + "_" + idx;
 		            jcrPath = newPath;
 		            break;
 		        }
 		    }
+	        // if it still exists there are more than 1000 nodes ?
+	        if (resolver.getResource(jcrPath) != null ) {
+	            throw new RepositoryException(
+	                "Collision in generated node names for path=" + basePath);
+	        }
 		}
 
-		// if it still exists there are more than 1000 nodes ?
-		if (session.itemExists(jcrPath)) {
-		    throw new RepositoryException(
-		        "Collision in generated node names for path=" + basePath);
-		}
 
 		return basePath;
     }

Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/DeleteOperation.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/DeleteOperation.java?rev=1391014&r1=1391013&r2=1391014&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/DeleteOperation.java (original)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/DeleteOperation.java Thu Sep 27 13:52:04 2012
@@ -19,11 +19,11 @@ package org.apache.sling.servlets.post.i
 import java.util.Iterator;
 import java.util.List;
 
-import javax.jcr.Item;
+import javax.jcr.Node;
 import javax.jcr.RepositoryException;
-import javax.servlet.http.HttpServletResponse;
 
 import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.PersistenceException;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.servlets.post.AbstractPostOperation;
 import org.apache.sling.servlets.post.Modification;
@@ -38,35 +38,52 @@ import org.apache.sling.servlets.post.Ve
 public class DeleteOperation extends AbstractPostOperation {
 
     @Override
-    protected void doRun(SlingHttpServletRequest request, PostResponse response, List<Modification> changes)
+    protected void doRun(final SlingHttpServletRequest request,
+                    final PostResponse response,
+                    final List<Modification> changes)
     throws RepositoryException {
-        VersioningConfiguration versioningConfiguration = getVersioningConfiguration(request);
+        final VersioningConfiguration versioningConfiguration = getVersioningConfiguration(request);
 
-        Iterator<Resource> res = getApplyToResources(request);
+        final Iterator<Resource> res = getApplyToResources(request);
         if (res == null) {
 
-            Resource resource = request.getResource();
-            Item item = resource.adaptTo(Item.class);
-            if (item == null) {
-                response.setStatus(HttpServletResponse.SC_NOT_FOUND,
-                    "Missing source " + resource + " for delete");
-                return;
+            final Resource resource = request.getResource();
+            final Node node = resource.adaptTo(Node.class);
+            if ( node != null ) {
+                checkoutIfNecessary(node.getParent(), changes, versioningConfiguration);
+
+                node.remove();
+            } else {
+                try {
+                    request.getResourceResolver().delete(resource);
+                } catch (final PersistenceException pe) {
+                    if ( pe.getCause() instanceof RepositoryException ) {
+                        throw (RepositoryException)pe.getCause();
+                    }
+                    throw new RepositoryException(pe);
+                }
             }
-            checkoutIfNecessary(item.getParent(), changes, versioningConfiguration);
-
-            item.remove();
             changes.add(Modification.onDeleted(resource.getPath()));
 
         } else {
 
             while (res.hasNext()) {
-                Resource resource = res.next();
-                Item item = resource.adaptTo(Item.class);
-                if (item != null) {
-                    checkoutIfNecessary(item.getParent(), changes, versioningConfiguration);
-                    item.remove();
-                    changes.add(Modification.onDeleted(resource.getPath()));
+                final Resource resource = res.next();
+                final Node node = resource.adaptTo(Node.class);
+                if ( node != null ) {
+                    checkoutIfNecessary(node.getParent(), changes, versioningConfiguration);
+                    node.remove();
+                } else {
+                    try {
+                        request.getResourceResolver().delete(resource);
+                    } catch (final PersistenceException pe) {
+                        if ( pe.getCause() instanceof RepositoryException ) {
+                            throw (RepositoryException)pe.getCause();
+                        }
+                        throw new RepositoryException(pe);
+                    }
                 }
+                changes.add(Modification.onDeleted(resource.getPath()));
             }
 
         }

Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ImportOperation.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ImportOperation.java?rev=1391014&r1=1391013&r2=1391014&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ImportOperation.java (original)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ImportOperation.java Thu Sep 27 13:52:04 2012
@@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRes
 
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.request.RequestParameter;
+import org.apache.sling.api.resource.PersistenceException;
 import org.apache.sling.jcr.contentloader.ContentImportListener;
 import org.apache.sling.jcr.contentloader.ContentImporter;
 import org.apache.sling.jcr.contentloader.ImportOptions;
@@ -65,7 +66,7 @@ public class ImportOperation extends Abs
     	}
     	return requestParameter.getString();
     }
-    
+
     @Override
     protected void doRun(SlingHttpServletRequest request, PostResponse response, final List<Modification> changes)
             throws RepositoryException {
@@ -83,7 +84,14 @@ public class ImportOperation extends Abs
         // do not change order unless you have a very good reason.
         Session session = request.getResourceResolver().adaptTo(Session.class);
 
-        processCreate(session, reqProperties, response, changes, versioningConfiguration);
+        try {
+            processCreate(request.getResourceResolver(), reqProperties, response, changes, versioningConfiguration);
+        } catch ( final PersistenceException pe) {
+            if ( pe.getCause() instanceof RepositoryException ) {
+                throw (RepositoryException)pe.getCause();
+            }
+            throw new RepositoryException(pe);
+        }
         String path = response.getPath();
         Node node = null;
         try {

Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ModifyOperation.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ModifyOperation.java?rev=1391014&r1=1391013&r2=1391014&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ModifyOperation.java (original)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ModifyOperation.java Thu Sep 27 13:52:04 2012
@@ -28,12 +28,15 @@ import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.nodetype.NodeType;
 import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
 
 import org.apache.sling.api.SlingException;
 import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.ModifiableValueMap;
+import org.apache.sling.api.resource.PersistenceException;
 import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.resource.ValueMap;
 import org.apache.sling.servlets.post.Modification;
 import org.apache.sling.servlets.post.PostResponse;
 import org.apache.sling.servlets.post.SlingPostConstants;
@@ -72,33 +75,43 @@ public class ModifyOperation extends Abs
     }
 
     @Override
-    protected void doRun(SlingHttpServletRequest request, PostResponse response, List<Modification> changes)
-            throws RepositoryException {
+    protected void doRun(final SlingHttpServletRequest request,
+                    final PostResponse response,
+                    final List<Modification> changes)
+    throws RepositoryException {
 
-        Map<String, RequestProperty> reqProperties = collectContent(request,
-                response);
+        try {
+            final Map<String, RequestProperty> reqProperties = collectContent(request, response);
 
-        VersioningConfiguration versioningConfiguration = getVersioningConfiguration(request);
+            final VersioningConfiguration versioningConfiguration = getVersioningConfiguration(request);
 
-        // do not change order unless you have a very good reason.
-        Session session = request.getResourceResolver().adaptTo(Session.class);
+            // do not change order unless you have a very good reason.
 
-        // ensure root of new content
-        processCreate(session, reqProperties, response, changes, versioningConfiguration);
+            // ensure root of new content
+            processCreate(request.getResourceResolver(), reqProperties, response, changes, versioningConfiguration);
 
-        // write content from existing content (@Move/CopyFrom parameters)
-        processMoves(session, reqProperties, changes, versioningConfiguration);
-        processCopies(session, reqProperties, changes, versioningConfiguration);
+            // write content from existing content (@Move/CopyFrom parameters)
+            processMoves(request.getResourceResolver(), reqProperties, changes, versioningConfiguration);
+            processCopies(request.getResourceResolver(), reqProperties, changes, versioningConfiguration);
 
-        // cleanup any old content (@Delete parameters)
-        processDeletes(session, reqProperties, changes, versioningConfiguration);
+            // cleanup any old content (@Delete parameters)
+            processDeletes(request.getResourceResolver(), reqProperties, changes, versioningConfiguration);
 
-        // write content from form
-        writeContent(session, reqProperties, changes, versioningConfiguration);
+            // write content from form
+            writeContent(request.getResourceResolver(), reqProperties, changes, versioningConfiguration);
 
-        // order content
-        String path = response.getPath();
-        orderNode(request, session.getItem(path), changes);
+            // order content
+            final Resource newResource = request.getResourceResolver().getResource(response.getPath());
+            final Node newNode = newResource.adaptTo(Node.class);
+            if ( newNode != null ) {
+                orderNode(request, newNode, changes);
+            }
+        } catch ( final PersistenceException pe) {
+            if ( pe.getCause() instanceof RepositoryException ) {
+                throw (RepositoryException)pe.getCause();
+            }
+            throw new RepositoryException(pe);
+        }
     }
 
     @Override
@@ -171,14 +184,14 @@ public class ModifyOperation extends Abs
      * request properties to the locations indicated by the resource properties.
      * @param checkedOutNodes
      */
-    private void processMoves(Session session,
+    private void processMoves(final ResourceResolver resolver,
             Map<String, RequestProperty> reqProperties, List<Modification> changes,
             VersioningConfiguration versioningConfiguration)
-            throws RepositoryException {
+            throws RepositoryException, PersistenceException {
 
         for (RequestProperty property : reqProperties.values()) {
             if (property.hasRepositoryMoveSource()) {
-                processMovesCopiesInternal(property, true, session,
+                processMovesCopiesInternal(property, true, resolver,
                     reqProperties, changes, versioningConfiguration);
             }
         }
@@ -189,14 +202,14 @@ public class ModifyOperation extends Abs
      * request properties to the locations indicated by the resource properties.
      * @param checkedOutNodes
      */
-    private void processCopies(Session session,
+    private void processCopies(final ResourceResolver resolver,
             Map<String, RequestProperty> reqProperties, List<Modification> changes,
             VersioningConfiguration versioningConfiguration)
-            throws RepositoryException {
+            throws RepositoryException, PersistenceException {
 
         for (RequestProperty property : reqProperties.values()) {
             if (property.hasRepositoryCopySource()) {
-                processMovesCopiesInternal(property, false, session,
+                processMovesCopiesInternal(property, false, resolver,
                     reqProperties, changes, versioningConfiguration);
             }
         }
@@ -224,12 +237,14 @@ public class ModifyOperation extends Abs
      *            recorded.
      * @throws RepositoryException May be thrown if an error occurrs.
      */
-    private void processMovesCopiesInternal(RequestProperty property,
-            boolean isMove, Session session,
+    private void processMovesCopiesInternal(
+                    RequestProperty property,
+            boolean isMove, final ResourceResolver resolver,
             Map<String, RequestProperty> reqProperties, List<Modification> changes,
             VersioningConfiguration versioningConfiguration)
-            throws RepositoryException {
+            throws RepositoryException, PersistenceException {
 
+        final Session session = resolver.adaptTo(Session.class);
         String propPath = property.getPath();
         String source = property.getRepositorySource();
 
@@ -245,9 +260,12 @@ public class ModifyOperation extends Abs
                 session.getItem(propPath).remove();
                 changes.add(Modification.onDeleted(propPath));
             } else {
-                Node parent = deepGetOrCreateNode(session, property.getParentPath(),
+                Resource parent = deepGetOrCreateNode(resolver, property.getParentPath(),
                     reqProperties, changes, versioningConfiguration);
-                checkoutIfNecessary(parent, changes, versioningConfiguration);
+                final Node node = parent.adaptTo(Node.class);
+                if ( node != null ) {
+                    checkoutIfNecessary(node, changes, versioningConfiguration);
+                }
             }
 
             // move through the session and record operation
@@ -298,10 +316,10 @@ public class ModifyOperation extends Abs
 
     /**
      * Removes all properties listed as {@link RequestProperty#isDelete()} from
-     * the repository.
+     * the resource.
      *
-     * @param session The <code>javax.jcr.Session</code> used to access the
-     *            repository to delete the properties.
+     * @param resolver The <code>ResourceResolver</code> used to access the
+     *            resources to delete the properties.
      * @param reqProperties The map of request properties to check for
      *            properties to be removed.
      * @param response The <code>HtmlResponse</code> to be updated with
@@ -309,29 +327,45 @@ public class ModifyOperation extends Abs
      * @throws RepositoryException Is thrown if an error occurrs checking or
      *             removing properties.
      */
-    private void processDeletes(Session session,
-            Map<String, RequestProperty> reqProperties,
-            List<Modification> changes,
-            VersioningConfiguration versioningConfiguration) throws RepositoryException {
-
-        for (RequestProperty property : reqProperties.values()) {
-
-            if (property.isDelete() && session.itemExists(property.getPath())) {
-                Node parent = (Node) session.getItem(property.getParentPath());
+    private void processDeletes(final ResourceResolver resolver,
+            final Map<String, RequestProperty> reqProperties,
+            final List<Modification> changes,
+            final VersioningConfiguration versioningConfiguration)
+    throws RepositoryException, PersistenceException {
+
+        for (final RequestProperty property : reqProperties.values()) {
+
+            if (property.isDelete()) {
+                final Resource parent = resolver.getResource(property.getParentPath());
+                if ( parent == null ) {
+                    continue;
+                }
+                final Node parentNode = parent.adaptTo(Node.class);
 
-                checkoutIfNecessary(parent, changes, versioningConfiguration);
+                if ( parentNode != null ) {
+                    checkoutIfNecessary(parentNode, changes, versioningConfiguration);
 
-                if (property.getName().equals("jcr:mixinTypes")) {
+                    if (property.getName().equals("jcr:mixinTypes")) {
 
-                    // clear all mixins
-                    for (NodeType mixin : parent.getMixinNodeTypes()) {
-                        parent.removeMixin(mixin.getName());
+                        // clear all mixins
+                        for (NodeType mixin : parentNode.getMixinNodeTypes()) {
+                            parentNode.removeMixin(mixin.getName());
+                        }
+
+                    } else {
+                        if ( parentNode.hasProperty(property.getName())) {
+                            parentNode.getProperty(property.getName()).remove();
+                        } else if ( parentNode.hasNode(property.getName())) {
+                            parentNode.getNode(property.getName()).remove();
+                        }
                     }
 
                 } else {
-
-                    session.getItem(property.getPath()).remove();
-
+                    final ValueMap vm = parent.adaptTo(ModifiableValueMap.class);
+                    if ( vm == null ) {
+                        throw new PersistenceException("Resource '" + parent.getPath() + "' is not modifiable.");
+                    }
+                    vm.remove(property.getName());
                 }
 
                 changes.add(Modification.onDeleted(property.getPath()));
@@ -344,28 +378,33 @@ public class ModifyOperation extends Abs
      * Writes back the content
      *
      * @throws RepositoryException if a repository error occurs
-     * @throws ServletException if an internal error occurs
+     * @throws PersistenceException if a persistence error occurs
      */
-    private void writeContent(Session session,
-            Map<String, RequestProperty> reqProperties, List<Modification> changes,
-            VersioningConfiguration versioningConfiguration)
-            throws RepositoryException {
+    private void writeContent(final ResourceResolver resolver,
+            final Map<String, RequestProperty> reqProperties,
+            final List<Modification> changes,
+            final VersioningConfiguration versioningConfiguration)
+    throws RepositoryException, PersistenceException {
 
-        SlingPropertyValueHandler propHandler = new SlingPropertyValueHandler(
-            dateParser, new ReferenceParser(session), changes);
+        final SlingPropertyValueHandler propHandler = new SlingPropertyValueHandler(
+            dateParser, new ReferenceParser(resolver.adaptTo(Session.class)), changes);
 
-        for (RequestProperty prop : reqProperties.values()) {
+        for (final RequestProperty prop : reqProperties.values()) {
             if (prop.hasValues()) {
-                Node parent = deepGetOrCreateNode(session,
+                final Resource parent = deepGetOrCreateNode(resolver,
                     prop.getParentPath(), reqProperties, changes, versioningConfiguration);
 
-                checkoutIfNecessary(parent, changes, versioningConfiguration);
+                final Node parentNode = parent.adaptTo(Node.class);
+                if ( parentNode != null ) {
+                    checkoutIfNecessary(parentNode, changes, versioningConfiguration);
+                }
 
                 // skip jcr special properties
                 if (prop.getName().equals("jcr:primaryType")
                     || prop.getName().equals("jcr:mixinTypes")) {
                     continue;
                 }
+
                 if (prop.isFileUpload()) {
                     uploadHandler.setFile(parent, prop, changes);
                 } else {
@@ -374,9 +413,4 @@ public class ModifyOperation extends Abs
             }
         }
     }
-
-
-
-
-
 }



Mime
View raw message