incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fmesc...@apache.org
Subject svn commit: r1076637 [1/2] - 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/s...
Date Thu, 03 Mar 2011 14:25:57 GMT
Author: fmeschbe
Date: Thu Mar  3 14:25:56 2011
New Revision: 1076637

URL: http://svn.apache.org/viewvc?rev=1076637&view=rev
Log:
SLING-1725 Provide new extensible operations and register existing operations as services

Added:
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostOperation.java
      - copied, changed from r991959, sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractSlingPostOperation.java
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostResponse.java   (with props)
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/HtmlResponse.java
      - copied, changed from r987838, sling/trunk/bundles/api/src/main/java/org/apache/sling/api/servlets/HtmlResponse.java
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/JSONResponse.java
      - copied, changed from r991959, sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JSONResponse.java
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/PostOperation.java   (with props)
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/PostResponse.java   (with props)
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/PostOperationProxyProvider.java   (with props)
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/HtmlPostResponseProxy.java   (with props)
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/HtmlResponseProxy.java   (with props)
    sling/trunk/bundles/servlets/post/src/main/resources/org/
    sling/trunk/bundles/servlets/post/src/main/resources/org/apache/
    sling/trunk/bundles/servlets/post/src/main/resources/org/apache/sling/
    sling/trunk/bundles/servlets/post/src/main/resources/org/apache/sling/servlets/
    sling/trunk/bundles/servlets/post/src/main/resources/org/apache/sling/servlets/post/
    sling/trunk/bundles/servlets/post/src/main/resources/org/apache/sling/servlets/post/HtmlResponse.html
      - copied unchanged from r991500, sling/trunk/bundles/api/src/main/resources/org/apache/sling/api/servlets/HtmlResponse.html
    sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/JsonResponseTest.java
      - copied, changed from r991959, sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/helper/JsonResponseTest.java
Removed:
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JSONResponse.java
    sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/helper/JsonResponseTest.java
Modified:
    sling/trunk/bundles/servlets/post/pom.xml
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractSlingPostOperation.java
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/SlingPostConstants.java
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/SlingPostOperation.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/operations/AbstractCopyMoveOperation.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/CheckinOperation.java
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/CheckoutOperation.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
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/NopOperation.java
    sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/RequestPropertyTest.java
    sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/SlingPostServletTest.java

Modified: sling/trunk/bundles/servlets/post/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/pom.xml?rev=1076637&r1=1076636&r2=1076637&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/pom.xml (original)
+++ sling/trunk/bundles/servlets/post/pom.xml Thu Mar  3 14:25:56 2011
@@ -59,7 +59,7 @@
                 <configuration>
                     <instructions>
                         <Export-Package>
-                            org.apache.sling.servlets.post;version=2.0.6
+                            org.apache.sling.servlets.post;version=2.0.8
                         </Export-Package>
                         <Private-Package>
                             org.apache.sling.servlets.post.impl.*
@@ -148,6 +148,14 @@
             <version>1.6.0</version>
             <scope>provided</scope>
         </dependency>
+        
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr.annotations</artifactId>
+            <version>1.4.0</version>
+            <scope>provided</scope>
+        </dependency>
+
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.commons.testing</artifactId>

Copied: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostOperation.java (from r991959, sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractSlingPostOperation.java)
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostOperation.java?p2=sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostOperation.java&p1=sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractSlingPostOperation.java&r1=991959&r2=1076637&rev=1076637&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractSlingPostOperation.java (original)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostOperation.java Thu Mar  3 14:25:56 2011
@@ -35,16 +35,17 @@ import org.apache.sling.api.SlingHttpSer
 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.servlets.HtmlResponse;
 import org.apache.sling.api.wrappers.SlingRequestPaths;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Holds various states and encapsulates methods that are needed to handle a
- * post request.
+ * The <code>AbstractPostOperation</code> class is a base implementation of the
+ * {@link PostOperation} service interface providing actual implementations with
+ * useful tooling and common functionality like preparing the change logs or
+ * saving or refreshing the JCR Session.
  */
-public abstract class AbstractSlingPostOperation implements SlingPostOperation {
+public abstract class AbstractPostOperation implements PostOperation {
 
     /**
      * default log
@@ -65,12 +66,12 @@ public abstract class AbstractSlingPostO
      *            progress.
      */
     public void run(SlingHttpServletRequest request,
-                    HtmlResponse response,
+                    PostResponse response,
                     SlingPostProcessor[] processors) {
         Session session = request.getResourceResolver().adaptTo(Session.class);
-        
+
         VersioningConfiguration versionableConfiguration = getVersioningConfiguration(request);
-        
+
         try {
             // calculate the paths
             String path = getItemPath(request);
@@ -91,8 +92,10 @@ public abstract class AbstractSlingPostO
             doRun(request, response, changes);
 
             // invoke processors
-            for(int i=0; i<processors.length; i++) {
-                processors[i].process(request, changes);
+            if (processors != null) {
+                for (SlingPostProcessor processor : processors) {
+                    processor.process(request, changes);
+                }
             }
 
             Set<String> nodesToCheckin = new LinkedHashSet<String>();
@@ -102,15 +105,15 @@ public abstract class AbstractSlingPostO
                 switch ( change.getType() ) {
                     case MODIFY : response.onModified(change.getSource()); break;
                     case DELETE : response.onDeleted(change.getSource()); break;
-                    case MOVE :   response.onMoved(change.getSource(), change.getDestination()); break;
-                    case COPY :   response.onCopied(change.getSource(), change.getDestination()); break;
+                    case MOVE   : response.onMoved(change.getSource(), change.getDestination()); break;
+                    case COPY   : response.onCopied(change.getSource(), change.getDestination()); break;
                     case CREATE :
                         response.onCreated(change.getSource());
                         if (versionableConfiguration.isCheckinOnNewVersionableNode()) {
                             nodesToCheckin.add(change.getSource());
                         }
                         break;
-                    case ORDER : response.onChange("ordered", change.getSource(), change.getDestination()); break;
+                    case ORDER  : response.onChange("ordered", change.getSource(), change.getDestination()); break;
                     case CHECKOUT :
                         response.onChange("checkout", change.getSource());
                         nodesToCheckin.add(change.getSource());
@@ -152,6 +155,29 @@ public abstract class AbstractSlingPostO
 
     }
 
+    /**
+     * Actually performs the desired operation filling progress into the
+     * <code>changes</code> list and preparing and further information in the
+     * <code>response</code>.
+     * <p>
+     * The <code>response</code> comes prepared with the path, location and
+     * parent location set. Other properties are expected to be set by this
+     * implementation.
+     *
+     * @param request The <code>SlingHttpServletRequest</code> providing the
+     *            input, mostly in terms of request parameters, to the
+     *            operation.
+     * @param response The {@link PostResponse} to fill with response
+     *            information
+     * @param changes A container to add {@link Modification} instances
+     *            representing the operations done.
+     * @throws RepositoryException Maybe thrown if any error occurrs while
+     *             accessing the repository.
+     */
+    protected abstract void doRun(SlingHttpServletRequest request,
+            PostResponse response,
+            List<Modification> changes) throws RepositoryException;
+
     protected VersioningConfiguration getVersioningConfiguration(SlingHttpServletRequest request) {
         VersioningConfiguration versionableConfiguration =
             (VersioningConfiguration) request.getAttribute(VersioningConfiguration.class.getName());
@@ -192,10 +218,6 @@ public abstract class AbstractSlingPostO
         return request.getResource().getPath();
     }
 
-    protected abstract void doRun(SlingHttpServletRequest request,
-            HtmlResponse response,
-            List<Modification> changes) throws RepositoryException;
-
     /**
      * Returns an iterator on <code>Resource</code> instances addressed in the
      * {@link SlingPostConstants#RP_APPLY_TO} request parameter. If the request
@@ -410,7 +432,7 @@ public abstract class AbstractSlingPostO
     protected boolean isVersionable(Node node) throws RepositoryException {
         return node.isNodeType("mix:versionable");
     }
-    
+
     protected void checkoutIfNecessary(Node node, List<Modification> changes,
             VersioningConfiguration versioningConfiguration) throws RepositoryException {
         if (versioningConfiguration.isAutoCheckout()) {

Added: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostResponse.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostResponse.java?rev=1076637&view=auto
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostResponse.java (added)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostResponse.java Thu Mar  3 14:25:56 2011
@@ -0,0 +1,379 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.servlets.post;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * The <code>AbstractPostResponse</code> class provides a basic implementation
+ * of the {@link PostResponse} interface maintaining properties to be
+ * prepared for sending the response in an internal map.
+ */
+public abstract class AbstractPostResponse implements PostResponse {
+
+    /**
+     * Name of the title property set by {@link #setTitle(String)}
+     */
+    public static final String PN_TITLE = "title";
+
+    /**
+     * Name of the status code property set by {@link #setStatus(int, String)}
+     */
+    public static final String PN_STATUS_CODE = "status.code";
+
+    /**
+     * Name of the status message property set by {@link #setStatus(int, String)}
+     */
+    public static final String PN_STATUS_MESSAGE = "status.message";
+
+    /**
+     * Name of the location property set by {@link #setLocation(String)}
+     */
+    public static final String PN_LOCATION = "location";
+
+    /**
+     * Name of the parent location property set by {@link #setParentLocation(String)}
+     */
+    public static final String PN_PARENT_LOCATION = "parentLocation";
+
+    /**
+     * Name of the path property set by {@link #setPath(String)}
+     */
+    public static final String PN_PATH = "path";
+
+    /**
+     * Name of the referer property set by {@link #setReferer(String)}
+     */
+    public static final String PN_REFERER = "referer";
+
+    /**
+     * Name of the create status property set by {@link #setCreateRequest(boolean)}
+     */
+    public static final String PN_IS_CREATED = "isCreate";
+
+    /**
+     * Name of the error property set by {@link #setError(Throwable)}
+     */
+    public static final String PN_ERROR = "error";
+
+    /**
+     * Properties of the response
+     */
+    private final Map<String, Object> properties = new HashMap<String, Object>();
+
+    // ---------- Settings for the response ------------------------------------
+
+    /**
+     * Returns the referer as from the 'referer' request header.
+     */
+    public String getReferer() {
+        return getProperty(PN_REFERER, String.class);
+    }
+
+    /**
+     * Sets the referer property
+     */
+    public void setReferer(String referer) {
+        setProperty(PN_REFERER, referer);
+    }
+
+    /**
+     * Returns the absolute path of the item upon which the request operated.
+     * <p>
+     * If the {@link #setPath(String)} method has not been called yet, this
+     * method returns <code>null</code>.
+     */
+    public String getPath() {
+        return getProperty(PN_PATH, String.class);
+    }
+
+    /**
+     * Sets the absolute path of the item upon which the request operated.
+     */
+    public void setPath(String path) {
+        setProperty(PN_PATH, path);
+    }
+
+    /**
+     * Returns <code>true</code> if this was a create request.
+     * <p>
+     * Before calling the {@link #setCreateRequest(boolean)} method, this method
+     * always returns <code>false</code>.
+     */
+    public boolean isCreateRequest() {
+        final Boolean isCreateRequest = getProperty(PN_IS_CREATED,
+            Boolean.class);
+        return (isCreateRequest != null)
+                ? isCreateRequest.booleanValue()
+                : false;
+    }
+
+    /**
+     * Sets whether the request was a create request or not.
+     */
+    public void setCreateRequest(boolean isCreateRequest) {
+        setProperty(PN_IS_CREATED, isCreateRequest);
+    }
+
+    /**
+     * Returns the location of the modification. this is the externalized form
+     * of the current path.
+     *
+     * @return the location of the modification.
+     */
+    public String getLocation() {
+        return getProperty(PN_LOCATION, String.class);
+    }
+
+    public void setLocation(String location) {
+        setProperty(PN_LOCATION, location);
+    }
+
+    /**
+     * Returns the parent location of the modification. this is the externalized
+     * form of the parent node of the current path.
+     *
+     * @return the location of the modification.
+     */
+    public String getParentLocation() {
+        return getProperty(PN_PARENT_LOCATION, String.class);
+    }
+
+    public void setParentLocation(String parentLocation) {
+        setProperty(PN_PARENT_LOCATION, parentLocation);
+    }
+
+    /**
+     * Sets the title of the response message
+     *
+     * @param title the title
+     */
+    public void setTitle(String title) {
+        setProperty(PN_TITLE, title);
+    }
+
+    /**
+     * sets the response status code properties
+     *
+     * @param code the code
+     * @param message the message
+     */
+    public void setStatus(int code, String message) {
+        setProperty(PN_STATUS_CODE, code);
+        setProperty(PN_STATUS_MESSAGE, message);
+    }
+
+    /**
+     * Returns the status code of this instance. If the status code has never
+     * been set by calling the {@link #setStatus(int, String)} method, the
+     * status code is determined by checking if there was an error. If there was
+     * an error, the response is assumed to be unsuccessful and 500 is returned.
+     * If there is no error, the response is assumed to be successful and 200 is
+     * returned.
+     */
+    public int getStatusCode() {
+        Integer status = getProperty(PN_STATUS_CODE, Integer.class);
+        if (status == null) {
+            if (getError() != null) {
+                // if there was an error
+                status = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
+            } else {
+                status = HttpServletResponse.SC_OK;
+            }
+        }
+        return status;
+    }
+
+    public String getStatusMessage() {
+        return getProperty(PN_STATUS_MESSAGE, String.class);
+    }
+
+    /**
+     * Returns any recorded error or <code>null</code>
+     *
+     * @return an error or <code>null</code>
+     */
+    public Throwable getError() {
+        return getProperty(PN_ERROR, Throwable.class);
+    }
+
+    public void setError(Throwable error) {
+        setProperty(PN_ERROR, error);
+    }
+
+    /**
+     * Returns <code>true</code> if no {@link #getError() error} is set and if
+     * the {@link #getStatusCode() status code} is one of the 2xx codes.
+     */
+    public boolean isSuccessful() {
+        return getError() == null && (getStatusCode() / 100) == 2;
+    }
+
+    // ---------- ChangeLog ----------------------------------------------------
+
+    /**
+     * Records a 'modified' change
+     *
+     * @param path path of the item that was modified
+     */
+    public void onModified(String path) {
+        onChange("modified", path);
+    }
+
+    /**
+     * Records a 'created' change
+     *
+     * @param path path of the item that was created
+     */
+    public void onCreated(String path) {
+        onChange("created", path);
+    }
+
+    /**
+     * Records a 'deleted' change
+     *
+     * @param path path of the item that was deleted
+     */
+    public void onDeleted(String path) {
+        if (path != null) {
+            onChange("deleted", path);
+        }
+    }
+
+    /**
+     * Records a 'moved' change.
+     * <p/>
+     * Note: the moved change only records the basic move command. the implied
+     * changes on the moved properties and sub nodes are not recorded.
+     *
+     * @param srcPath source path of the node that was moved
+     * @param dstPath destination path of the node that was moved.
+     */
+    public void onMoved(String srcPath, String dstPath) {
+        onChange("moved", srcPath, dstPath);
+    }
+
+    /**
+     * Records a 'copied' change.
+     * <p/>
+     * Note: the copy change only records the basic copy command. the implied
+     * changes on the copied properties and sub nodes are not recorded.
+     *
+     * @param srcPath source path of the node that was copied
+     * @param dstPath destination path of the node that was copied.
+     */
+    public void onCopied(String srcPath, String dstPath) {
+        onChange("copied", srcPath, dstPath);
+    }
+
+
+    /**
+     * prepares the response properties
+     */
+    private void prepare(final HttpServletResponse response, final boolean setStatus) {
+        String path = getPath();
+        if (getProperty(PN_STATUS_CODE) == null) {
+            if (getError() != null) {
+                setStatus(500, getError().toString());
+                setTitle("Error while processing " + path);
+            } else {
+                if (isCreateRequest()) {
+                    setStatus(201, "Created");
+                    setTitle("Content created " + path);
+                } else {
+                    setStatus(200, "OK");
+                    setTitle("Content modified " + path);
+                }
+            }
+        }
+
+        String referer = getReferer();
+        if (referer == null) {
+            referer = "";
+        }
+        setReferer(referer);
+
+        if (setStatus) {
+            Object status = getProperty(PN_STATUS_CODE);
+            if (status instanceof Number) {
+                int statusCode = ((Number) status).intValue();
+                response.setStatus(statusCode);
+
+                // special treatment of 201/CREATED: Requires Location
+                if (statusCode == HttpServletResponse.SC_CREATED) {
+                    response.setHeader("Location", getLocation());
+                }
+            }
+        }
+
+    }
+
+    /**
+     * Sets a generic response property with the given
+     *
+     * @param name name of the property
+     * @param value value of the property
+     */
+    protected void setProperty(String name, Object value) {
+        properties.put(name, value);
+    }
+
+    /**
+     * Returns the generic response property with the given name and type or
+     * <code>null</code> if no such property exists or the property is not of
+     * the requested type.
+     */
+    @SuppressWarnings("unchecked")
+    protected <Type> Type getProperty(String name, Class<Type> type) {
+        Object value = getProperty(name);
+        if (type.isInstance(value)) {
+            return (Type) value;
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns the generic response property with the given name and type or
+     * <code>null</code> if no such property exists.
+     */
+    protected Object getProperty(String name) {
+        return properties.get(name);
+    }
+
+    protected abstract void doSend(HttpServletResponse response) throws IOException;
+
+    /**
+     * Writes the response to the given writer and replaces all ${var} patterns
+     * by the value of the respective property. if the property is not defined
+     * the pattern is not modified.
+     *
+     * @param response to send to
+     * @param setStatus whether to set the status code on the response
+     * @throws IOException if an i/o exception occurs
+     */
+    public final void send(HttpServletResponse response, boolean setStatus)
+            throws IOException {
+        prepare(response, setStatus);
+        doSend(response);
+    }
+
+}
\ No newline at end of file

Propchange: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostResponse.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractPostResponse.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractSlingPostOperation.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractSlingPostOperation.java?rev=1076637&r1=1076636&r2=1076637&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractSlingPostOperation.java (original)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractSlingPostOperation.java Thu Mar  3 14:25:56 2011
@@ -16,484 +16,68 @@
  */
 package org.apache.sling.servlets.post;
 
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
 import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.Set;
 
-import javax.jcr.AccessDeniedException;
-import javax.jcr.Item;
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
 import javax.jcr.RepositoryException;
-import javax.jcr.Session;
 
 import org.apache.sling.api.SlingHttpServletRequest;
-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.servlets.HtmlResponse;
-import org.apache.sling.api.wrappers.SlingRequestPaths;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.sling.servlets.post.impl.helper.HtmlPostResponseProxy;
+import org.apache.sling.servlets.post.impl.helper.HtmlResponseProxy;
 
 /**
- * Holds various states and encapsulates methods that are needed to handle a
- * post request.
+ * The <code>AbstractSlingPostOperation</code> is the abstract base class
+ * implementation of the {@link SlingPostOperation} interface extending the new
+ * {@link AbstractPostOperation}.
+ * <p>
+ * This class exists for backwards compatibility. Existing implementations are
+ * advised to migrate to the new {@link AbstractPostOperation}.
+ *
+ * @deprecated as of 2.0.8 (Bundle version 2.2.0) and replaced by
+ *             {@link AbstractPostOperation}.
  */
-public abstract class AbstractSlingPostOperation implements SlingPostOperation {
+public abstract class AbstractSlingPostOperation extends AbstractPostOperation
+        implements SlingPostOperation {
 
     /**
-     * default log
-     */
-    protected final Logger log = LoggerFactory.getLogger(getClass());
-
-    /**
-     * Prepares and finalizes the actual operation. Preparation encompasses
-     * 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)}
-     * 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
-     *            progress.
-     */
-    public void run(SlingHttpServletRequest request,
-                    HtmlResponse response,
-                    SlingPostProcessor[] processors) {
-        Session session = request.getResourceResolver().adaptTo(Session.class);
-
-        VersioningConfiguration versionableConfiguration = getVersioningConfiguration(request);
-
-        try {
-            // calculate the paths
-            String path = getItemPath(request);
-            path = removeAndValidateWorkspace(path, session);
-            response.setPath(path);
-
-            // location
-            response.setLocation(externalizePath(request, path));
-
-            // parent location
-            path = ResourceUtil.getParent(path);
-            if (path != null) {
-                response.setParentLocation(externalizePath(request, path));
-            }
-
-            final List<Modification> changes = new ArrayList<Modification>();
-
-            doRun(request, response, changes);
-
-            // invoke processors
-            for(int i=0; i<processors.length; i++) {
-                processors[i].process(request, changes);
-            }
-
-            Set<String> nodesToCheckin = new LinkedHashSet<String>();
-
-            // set changes on html response
-            for(Modification change : changes) {
-                switch ( change.getType() ) {
-                    case MODIFY : response.onModified(change.getSource()); break;
-                    case DELETE : response.onDeleted(change.getSource()); break;
-                    case MOVE :   response.onMoved(change.getSource(), change.getDestination()); break;
-                    case COPY :   response.onCopied(change.getSource(), change.getDestination()); break;
-                    case CREATE :
-                        response.onCreated(change.getSource());
-                        if (versionableConfiguration.isCheckinOnNewVersionableNode()) {
-                            nodesToCheckin.add(change.getSource());
-                        }
-                        break;
-                    case ORDER : response.onChange("ordered", change.getSource(), change.getDestination()); break;
-                    case CHECKOUT :
-                        response.onChange("checkout", change.getSource());
-                        nodesToCheckin.add(change.getSource());
-                        break;
-                    case CHECKIN :
-                        response.onChange("checkin", change.getSource());
-                        nodesToCheckin.remove(change.getSource());
-                        break;
-                }
-            }
-            if (session.hasPendingChanges()) {
-                session.save();
-            }
-
-            if (!isSkipCheckin(request)) {
-                // now do the checkins
-                for(String checkinPath : nodesToCheckin) {
-                    if (checkin(session, checkinPath)) {
-                        response.onChange("checkin", checkinPath);
-                    }
-                }
-            }
-
-        } catch ( AccessDeniedException e ) {
-            log.error("Access Denied {} ",e.getMessage());
-            log.debug("Access Denied Cause ", e);
-            response.setError(e);
-        } catch (Exception e) {
-
-            log.error("Exception during response processing.", e);
-            response.setError(e);
-
-        } finally {
-            try {
-                if (session.hasPendingChanges()) {
-                    session.refresh(false);
-                }
-            } catch (RepositoryException e) {
-                log.warn("RepositoryException in finally block: {}",
-                    e.getMessage(), e);
-            }
-        }
-
-    }
-
-    protected VersioningConfiguration getVersioningConfiguration(SlingHttpServletRequest request) {
-        VersioningConfiguration versionableConfiguration =
-            (VersioningConfiguration) request.getAttribute(VersioningConfiguration.class.getName());
-        return versionableConfiguration != null ? versionableConfiguration : new VersioningConfiguration();
-    }
-
-    protected boolean isSkipCheckin(SlingHttpServletRequest request) {
-        return !getVersioningConfiguration(request).isAutoCheckin();
-    }
-
-    /**
-     * Remove the workspace name, if any, from the start of the path and validate that the
-     * session's workspace name matches the path workspace name.
+     * @param request
+     * @param response
+     * @param changes
+     * @throws RepositoryException
      */
-    protected String removeAndValidateWorkspace(String path, Session session) throws RepositoryException {
-        final int wsSepPos = path.indexOf(":/");
-        if (wsSepPos != -1) {
-            final String workspaceName = path.substring(0, wsSepPos);
-            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;
-        }
-    }
-
-
-    /**
-     * Returns the path of the resource of the request as the item path.
-     * <p>
-     * This method may be overwritten by extension if the operation has
-     * different requirements on path processing.
-     */
-    protected String getItemPath(SlingHttpServletRequest request) {
-        return request.getResource().getPath();
-    }
-
     protected abstract void doRun(SlingHttpServletRequest request,
-            HtmlResponse response,
-            List<Modification> changes) throws RepositoryException;
-
-    /**
-     * Returns an iterator on <code>Resource</code> instances addressed in the
-     * {@link SlingPostConstants#RP_APPLY_TO} request parameter. If the request
-     * parameter is not set, <code>null</code> is returned. If the parameter
-     * is set with valid resources an empty iterator is returned. Any resources
-     * addressed in the {@link SlingPostConstants#RP_APPLY_TO} parameter is
-     * ignored.
-     *
-     * @param request The <code>SlingHttpServletRequest</code> object used to
-     *            get the {@link SlingPostConstants#RP_APPLY_TO} parameter.
-     * @return The iterator of resources listed in the parameter or
-     *         <code>null</code> if the parameter is not set in the request.
-     */
-    protected Iterator<Resource> getApplyToResources(
-            SlingHttpServletRequest request) {
-
-        String[] applyTo = request.getParameterValues(SlingPostConstants.RP_APPLY_TO);
-        if (applyTo == null) {
-            return null;
-        }
-
-        return new ApplyToIterator(request, applyTo);
-    }
-
-    /**
-     * Returns an external form of the given path prepending the context path
-     * and appending a display extension.
-     *
-     * @param path the path to externalize
-     * @return the url
-     */
-    protected final String externalizePath(SlingHttpServletRequest request,
-            String path) {
-        StringBuffer ret = new StringBuffer();
-        ret.append(SlingRequestPaths.getContextPath(request));
-        ret.append(request.getResourceResolver().map(path));
-
-        // append optional extension
-        String ext = request.getParameter(SlingPostConstants.RP_DISPLAY_EXTENSION);
-        if (ext != null && ext.length() > 0) {
-            if (ext.charAt(0) != '.') {
-                ret.append('.');
-            }
-            ret.append(ext);
-        }
-
-        return ret.toString();
-    }
-
-    /**
-     * Resolves the given path with respect to the current root path.
-     *
-     * @param relPath the path to resolve
-     * @return the given path if it starts with a '/'; a resolved path
-     *         otherwise.
-     */
-    protected final String resolvePath(String absPath, String relPath) {
-        if (relPath.startsWith("/")) {
-            return relPath;
-        }
-        return absPath + "/" + relPath;
-    }
+            HtmlResponse response, List<Modification> changes)
+            throws RepositoryException;
 
     /**
-     * Returns true if any of the request parameters starts with
-     * {@link SlingPostConstants#ITEM_PREFIX_RELATIVE_CURRENT <code>./</code>}.
-     * In this case only parameters starting with either of the prefixes
-     * {@link SlingPostConstants#ITEM_PREFIX_RELATIVE_CURRENT <code>./</code>},
-     * {@link SlingPostConstants#ITEM_PREFIX_RELATIVE_PARENT <code>../</code>}
-     * and {@link SlingPostConstants#ITEM_PREFIX_ABSOLUTE <code>/</code>} are
-     * considered as providing content to be stored. Otherwise all parameters
-     * not starting with the command prefix <code>:</code> are considered as
-     * parameters to be stored.
+     * Implementation of the
+     * {@link AbstractPostOperation#doRun(SlingHttpServletRequest, PostResponse, List)}
+     * method calling our own
+     * {@link #run(SlingHttpServletRequest, HtmlResponse, SlingPostProcessor[])}
+     * meethod with a proxy for the Sling API <code>HtmlResponse</code>.
      */
-    protected final boolean requireItemPathPrefix(
-            SlingHttpServletRequest request) {
-
-        boolean requirePrefix = false;
-
-        Enumeration<?> names = request.getParameterNames();
-        while (names.hasMoreElements() && !requirePrefix) {
-            String name = (String) names.nextElement();
-            requirePrefix = name.startsWith(SlingPostConstants.ITEM_PREFIX_RELATIVE_CURRENT);
-        }
-
-        return requirePrefix;
-    }
-
-    /**
-     * Returns <code>true</code> if the <code>name</code> starts with either
-     * of the prefixes
-     * {@link SlingPostConstants#ITEM_PREFIX_RELATIVE_CURRENT <code>./</code>},
-     * {@link SlingPostConstants#ITEM_PREFIX_RELATIVE_PARENT <code>../</code>}
-     * and {@link SlingPostConstants#ITEM_PREFIX_ABSOLUTE <code>/</code>}.
-     */
-    protected boolean hasItemPathPrefix(String name) {
-        return name.startsWith(SlingPostConstants.ITEM_PREFIX_ABSOLUTE)
-            || name.startsWith(SlingPostConstants.ITEM_PREFIX_RELATIVE_CURRENT)
-            || name.startsWith(SlingPostConstants.ITEM_PREFIX_RELATIVE_PARENT);
-    }
-
-    /**
-     * Orders the given node according to the specified command. The following
-     * syntax is supported: <xmp> | first | before all child nodes | before A |
-     * before child node A | after A | after child node A | last | after all
-     * nodes | N | at a specific position, N being an integer </xmp>
-     *
-     * @param item node to order
-     * @throws RepositoryException if an error occurs
-     */
-    protected void orderNode(SlingHttpServletRequest request, Item item,
-            List<Modification> changes) throws RepositoryException {
-
-        String command = request.getParameter(SlingPostConstants.RP_ORDER);
-        if (command == null || command.length() == 0) {
-            // nothing to do
-            return;
-        }
-
-        if (!item.isNode()) {
-            return;
-        }
-
-        Node parent = item.getParent();
-
-        String next = null;
-        if (command.equals(SlingPostConstants.ORDER_FIRST)) {
-
-            next = parent.getNodes().nextNode().getName();
-
-        } else if (command.equals(SlingPostConstants.ORDER_LAST)) {
-
-            next = "";
-
-        } else if (command.startsWith(SlingPostConstants.ORDER_BEFORE)) {
-
-            next = command.substring(SlingPostConstants.ORDER_BEFORE.length());
-
-        } else if (command.startsWith(SlingPostConstants.ORDER_AFTER)) {
-
-            String name = command.substring(SlingPostConstants.ORDER_AFTER.length());
-            NodeIterator iter = parent.getNodes();
-            while (iter.hasNext()) {
-                Node n = iter.nextNode();
-                if (n.getName().equals(name)) {
-                    if (iter.hasNext()) {
-                        next = iter.nextNode().getName();
-                    } else {
-                        next = "";
-                    }
-                }
-            }
-
-        } else {
-            // check for integer
-            try {
-                // 01234
-                // abcde move a -> 2 (above 3)
-                // bcade move a -> 1 (above 1)
-                // bacde
-                int newPos = Integer.parseInt(command);
-                next = "";
-                NodeIterator iter = parent.getNodes();
-                while (iter.hasNext() && newPos >= 0) {
-                    Node n = iter.nextNode();
-                    if (n.getName().equals(item.getName())) {
-                        // if old node is found before index, need to
-                        // inc index
-                        newPos++;
-                    }
-                    if (newPos == 0) {
-                        next = n.getName();
-                        break;
-                    }
-                    newPos--;
-                }
-            } catch (NumberFormatException e) {
-                throw new IllegalArgumentException(
-                    "provided node ordering command is invalid: " + command);
-            }
-        }
-
-        if (next != null) {
-            if (next.equals("")) {
-                next = null;
-            }
-            parent.orderBefore(item.getName(), next);
-            changes.add(Modification.onOrder(item.getPath(), next));
-            if (log.isDebugEnabled()) {
-                log.debug("Node {} moved '{}'", item.getPath(), command);
-            }
-        } else {
-            throw new IllegalArgumentException(
-                "provided node ordering command is invalid: " + command);
-        }
-    }
-
-    protected Node findVersionableAncestor(Node node)
+    protected void doRun(SlingHttpServletRequest request,
+            PostResponse response, List<Modification> changes)
             throws RepositoryException {
-        try {
-            while (!isVersionable(node)) {
-                node = node.getParent();
-            }
-            return node;
-        } catch (AccessDeniedException ade) {
-            // not allowed to access parent, assume no versionable ancestor
-        } catch (ItemNotFoundException e) {
-            // current node is root but not versionable, assume no vers. anc.
-        }
-
-        return null;
-    }
-
-    protected boolean isVersionable(Node node) throws RepositoryException {
-        return node.isNodeType("mix:versionable");
-    }
-
-    protected void checkoutIfNecessary(Node node, List<Modification> changes,
-            VersioningConfiguration versioningConfiguration) throws RepositoryException {
-        if (versioningConfiguration.isAutoCheckout()) {
-            Node versionableNode = findVersionableAncestor(node);
-            if (versionableNode != null) {
-                if (!versionableNode.isCheckedOut()) {
-                    versionableNode.checkout();
-                    changes.add(Modification.onCheckout(versionableNode.getPath()));
-                }
-            }
-        }
+        final HtmlResponse htmlResponseProxy = (response instanceof HtmlPostResponseProxy)
+                ? ((HtmlPostResponseProxy) response).getHtmlResponse()
+                : new HtmlResponseProxy(response);
+        doRun(request, htmlResponseProxy, changes);
     }
 
-    private boolean checkin(Session session, String path) throws RepositoryException {
-        Item item = session.getItem(path);
-        if (item instanceof Node) {
-            Node node = (Node) item;
-            if (node.isCheckedOut() && isVersionable(node)) {
-                node.checkin();
-                return true;
-            }
-        }
-        return false;
+    /**
+     * Implementation of the
+     * {@link SlingPostOperation#run(SlingHttpServletRequest, HtmlResponse, SlingPostProcessor[])}
+     * API method calling the
+     * {@link PostOperation#run(SlingHttpServletRequest, PostResponse, SlingPostProcessor[])}
+     * with a proxy around the Sling API <code>HtmlResponse</code> provided.
+     */
+    public void run(SlingHttpServletRequest request, HtmlResponse response,
+            SlingPostProcessor[] processors) {
+        final PostResponse postResponseProxy = new HtmlPostResponseProxy(
+            response);
+        run(request, postResponseProxy, processors);
     }
 
-    private static class ApplyToIterator implements Iterator<Resource> {
-
-        private final ResourceResolver resolver;
-        private final Resource baseResource;
-        private final String[] paths;
-
-        private int pathIndex;
-
-        private Resource nextResource;
-
-        ApplyToIterator(SlingHttpServletRequest request, String[] paths) {
-            this.resolver = request.getResourceResolver();
-            this.baseResource = request.getResource();
-            this.paths = paths;
-            this.pathIndex = 0;
-
-            nextResource = seek();
-        }
-
-        public boolean hasNext() {
-            return nextResource != null;
-        }
-
-        public Resource next() {
-            if (!hasNext()) {
-                throw new NoSuchElementException();
-            }
-
-            Resource result = nextResource;
-            nextResource = seek();
-
-            return result;
-        }
-
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-
-        private Resource seek() {
-            while (pathIndex < paths.length) {
-                String path = paths[pathIndex];
-                pathIndex++;
-
-                Resource res = resolver.getResource(baseResource, path);
-                if (res != null) {
-                    return res;
-                }
-            }
-
-            // no more elements in the array
-            return null;
-        }
-    }
 }
\ No newline at end of file

Copied: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/HtmlResponse.java (from r987838, sling/trunk/bundles/api/src/main/java/org/apache/sling/api/servlets/HtmlResponse.java)
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/HtmlResponse.java?p2=sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/HtmlResponse.java&p1=sling/trunk/bundles/api/src/main/java/org/apache/sling/api/servlets/HtmlResponse.java&r1=987838&r2=1076637&rev=1076637&view=diff
==============================================================================
--- sling/trunk/bundles/api/src/main/java/org/apache/sling/api/servlets/HtmlResponse.java (original)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/HtmlResponse.java Thu Mar  3 14:25:56 2011
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sling.api.servlets;
+package org.apache.sling.servlets.post;
 
 import java.io.BufferedReader;
 import java.io.IOException;
@@ -22,72 +22,22 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
 import java.io.Writer;
-import java.util.HashMap;
-import java.util.Map;
-
 import javax.servlet.http.HttpServletResponse;
 
 /**
- * Generator for a HTML status response that displays the changes made in a post
- * request. see <a href="HtmlResponse.html">HtmlResponse.html</a> for the
- * format.
+ * The <code>HtmlResponse</code> is an {@link AbstractPostResponse} preparing
+ * the response in HTML (actually XHTML) such that it can be interpreted
+ * as a plain response in a browser or as XML response in an Ajax request.
  */
-public class HtmlResponse {
-
-    /**
-     * some human readable title like: 200 Created /foo/bar
-     */
-    public static final String PN_TITLE = "title";
-
-    /**
-     * status code. more or less http response status codes
-     */
-    public static final String PN_STATUS_CODE = "status.code";
-
-    /**
-     * some human readable status message
-     */
-    public static final String PN_STATUS_MESSAGE = "status.message";
-
-    /**
-     * externally mapped location url of the modified path
-     */
-    public static final String PN_LOCATION = "location";
-
-    /**
-     * externally mapped location url of the parent of the modified path
-     */
-    public static final String PN_PARENT_LOCATION = "parentLocation";
-
-    /**
-     * the path of the modified item. this is usually the addressed resource or
-     * in case of a creation request (eg: /foo/*) the path of the newly created
-     * node.
-     */
-    public static final String PN_PATH = "path";
-
-    /**
-     * the referrer of the request
-     */
-    public static final String PN_REFERER = "referer";
+public class HtmlResponse extends AbstractPostResponse {
 
     /**
-     * Indicating whether request processing created new data. This property
-     * is initialized to <code>false</code> and may be changed by calling
-     * the {@link #setCreateRequest(boolean)} method.
+     * Name of the property into which the change log is gathered to be
+     * sent back by the {@link #doSend(HttpServletResponse)} method. This
+     * property is only sent before replacing all variables in the HTML
+     * response remplate.
      */
-    public static final String PN_IS_CREATED = "isCreate";
-
-    /**
-     * human readable changelog
-     */
-    public static final String PN_CHANGE_LOG = "changeLog";
-
-    /**
-     * The Throwable caught while processing the request. This property is not
-     * set unless the {@link #setError(Throwable)} method is called.
-     */
-    public static final String PN_ERROR = "error";
+    private static final String PN_CHANGE_LOG = "changeLog";
 
     /**
      * name of the html template
@@ -100,237 +50,25 @@ public class HtmlResponse {
     private final StringBuffer changes = new StringBuffer();
 
     /**
-     * Properties of the response
-     */
-    private final Map<String, Object> properties = new HashMap<String, Object>();
-
-    /**
-     * Creates a new html response with default settings, which is
-     * <code>null</code> for almost all properties except the
-     * {@link #isCreateRequest()} which defaults to <code>false</code>.
-     */
-    public HtmlResponse() {
-        setCreateRequest(false);
-    }
-
-    // ---------- Settings for the response ------------------------------------
-
-    /**
-     * Returns the referer as from the 'referer' request header.
-     */
-    public String getReferer() {
-        return getProperty(PN_REFERER, String.class);
-    }
-
-    /**
-     * Sets the referer property
-     */
-    public void setReferer(String referer) {
-        setProperty(PN_REFERER, referer);
-    }
-
-    /**
-     * Returns the absolute path of the item upon which the request operated.
-     * <p>
-     * If the {@link #setPath(String)} method has not been called yet, this
-     * method returns <code>null</code>.
-     */
-    public String getPath() {
-        return getProperty(PN_PATH, String.class);
-    }
-
-    /**
-     * Sets the absolute path of the item upon which the request operated.
-     */
-    public void setPath(String path) {
-        setProperty(PN_PATH, path);
-    }
-
-    /**
-     * Returns <code>true</code> if this was a create request.
-     * <p>
-     * Before calling the {@link #setCreateRequest(boolean)} method, this method
-     * always returns <code>false</code>.
-     */
-    public boolean isCreateRequest() {
-        return getProperty(PN_IS_CREATED, Boolean.class);
-    }
-
-    /**
-     * Sets whether the request was a create request or not.
-     */
-    public void setCreateRequest(boolean isCreateRequest) {
-        setProperty(PN_IS_CREATED, isCreateRequest);
-    }
-
-    /**
-     * Returns the location of the modification. this is the externalized form
-     * of the current path.
-     *
-     * @return the location of the modification.
-     */
-    public String getLocation() {
-        return getProperty(PN_LOCATION, String.class);
-    }
-
-    public void setLocation(String location) {
-        setProperty(PN_LOCATION, location);
-    }
-
-    /**
-     * Returns the parent location of the modification. this is the externalized
-     * form of the parent node of the current path.
-     *
-     * @return the location of the modification.
-     */
-    public String getParentLocation() {
-        return getProperty(PN_PARENT_LOCATION, String.class);
-    }
-
-    public void setParentLocation(String parentLocation) {
-        setProperty(PN_PARENT_LOCATION, parentLocation);
-    }
-
-    /**
-     * Sets the title of the response message
-     *
-     * @param title the title
-     */
-    public void setTitle(String title) {
-        setProperty(PN_TITLE, title);
-    }
-
-    /**
-     * sets the response status code properties
-     *
-     * @param code the code
-     * @param message the message
-     */
-    public void setStatus(int code, String message) {
-        setProperty(PN_STATUS_CODE, code);
-        setProperty(PN_STATUS_MESSAGE, message);
-    }
-
-    /**
-     * Returns the status code of this instance. If the status code has never
-     * been set by calling the {@link #setStatus(int, String)} method, the
-     * status code is determined by checking if there was an error.  If there
-     * was an error, the response is assumed to be unsuccessful and 500 is returned.
-     * If there is no error, the response is assumed to be successful and 200 is returned.
-     */
-    public int getStatusCode() {
-        Integer status = getProperty(PN_STATUS_CODE, Integer.class);
-        if (status == null) {
-        	if (getError() != null) {
-        		//if there was an error
-        		status = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
-        	} else {
-        		status = HttpServletResponse.SC_OK;
-        	}
-        }
-        return status;
-    }
-
-    public String getStatusMessage() {
-        return getProperty(PN_STATUS_MESSAGE, String.class);
-    }
-
-    /**
-     * Returns any recorded error or <code>null</code>
-     *
-     * @return an error or <code>null</code>
-     */
-    public Throwable getError() {
-        return getProperty(PN_ERROR, Throwable.class);
-    }
-
-    public void setError(Throwable error) {
-        setProperty(PN_ERROR, error);
-    }
-
-    /**
-     * Returns <code>true</code> if no {@link #getError() error} is set and if
-     * the {@link #getStatusCode() status code} is one of the 2xx codes.
-     */
-    public boolean isSuccessful() {
-        return getError() == null && (getStatusCode() / 100) == 2;
-    }
-
-    // ---------- ChangeLog ----------------------------------------------------
-
-    /**
-     * Records a 'modified' change
-     *
-     * @param path path of the item that was modified
-     */
-    public void onModified(String path) {
-        onChange("modified", path);
-    }
-
-    /**
-     * Records a 'created' change
-     *
-     * @param path path of the item that was created
-     */
-    public void onCreated(String path) {
-        onChange("created", path);
-    }
-
-    /**
-     * Records a 'deleted' change
-     *
-     * @param path path of the item that was deleted
-     */
-    public void onDeleted(String path) {
-        if (path != null) {
-            onChange("deleted", path);
-        }
-    }
-
-    /**
-     * Records a 'moved' change. <p/> Note: the moved change only records the
-     * basic move command. the implied changes on the moved properties and sub
-     * nodes are not recorded.
-     *
-     * @param srcPath source path of the node that was moved
-     * @param dstPath destination path of the node that was moved.
-     */
-    public void onMoved(String srcPath, String dstPath) {
-        onChange("moved", srcPath, dstPath);
-    }
-
-    /**
-     * Records a 'copied' change. <p/> Note: the copy change only records the
-     * basic copy command. the implied changes on the copied properties and sub
-     * nodes are not recorded.
-     *
-     * @param srcPath source path of the node that was copied
-     * @param dstPath destination path of the node that was copied.
-     */
-    public void onCopied(String srcPath, String dstPath) {
-        onChange("copied", srcPath, dstPath);
-    }
-
-    /**
      * Records a generic change of the given <code>type</code>.
      * <p>
      * The change is added to the internal list of changes with the syntax of a
      * method call, where the <code>type</code> is the method name and the
      * <code>arguments</code> are the string arguments to the method enclosed in
      * double quotes. For example, the the call
-     * 
+     *
      * <pre>
      * onChange(&quot;sameple&quot;, &quot;arg1&quot;, &quot;arg2&quot;);
      * </pre>
-     * 
+     *
      * is aded as
-     * 
+     *
      * <pre>
      * sample(&quot;arg1&quot;, &quot;arg2&quot;)
      * </pre>
-     * 
+     *
      * to the internal list of changes.
-     * 
+     *
      * @param type The type of the modification
      * @param arguments The arguments to the modifications
      */
@@ -350,71 +88,6 @@ public class HtmlResponse {
     // ---------- Response Generation ------------------------------------------
 
     /**
-     * prepares the response properties
-     */
-    private void prepare() {
-        String path = getPath();
-        if (getProperty(PN_STATUS_CODE) == null) {
-            if (getError() != null) {
-                setStatus(500, getError().toString());
-                setTitle("Error while processing " + path);
-            } else {
-                if (isCreateRequest()) {
-                    setStatus(201, "Created");
-                    setTitle("Content created " + path);
-                } else {
-                    setStatus(200, "OK");
-                    setTitle("Content modified " + path);
-                }
-            }
-        }
-
-        String referer = getReferer();
-        if (referer == null) {
-            referer = "";
-        }
-        setReferer(referer);
-
-        // get changelog
-        changes.insert(0, "<pre>");
-        changes.append("</pre>");
-        setProperty(PN_CHANGE_LOG, changes.toString());
-    }
-
-    /**
-     * Sets a generic response property with the given
-     *
-     * @param name name of the property
-     * @param value value of the property
-     */
-    public void setProperty(String name, Object value) {
-        properties.put(name, value);
-    }
-
-    /**
-     * Returns the generic response property with the given name and type or
-     * <code>null</code> if no such property exists or the property is not of
-     * the requested type.
-     */
-    @SuppressWarnings("unchecked")
-    public <Type> Type getProperty(String name, Class<Type> type) {
-        Object value = getProperty(name);
-        if (type.isInstance(value)) {
-            return (Type) value;
-        }
-
-        return null;
-    }
-
-    /**
-     * Returns the generic response property with the given name and type or
-     * <code>null</code> if no such property exists.
-     */
-    public Object getProperty(String name) {
-        return properties.get(name);
-    }
-
-    /**
      * Writes the response to the given writer and replaces all ${var} patterns
      * by the value of the respective property. if the property is not defined
      * the pattern is not modified.
@@ -423,26 +96,17 @@ public class HtmlResponse {
      * @param setStatus whether to set the status code on the response
      * @throws IOException if an i/o exception occurs
      */
-    public void send(HttpServletResponse response, boolean setStatus)
+    protected void doSend(HttpServletResponse response)
             throws IOException {
-        prepare();
-
-        if (setStatus) {
-            Object status = getProperty(PN_STATUS_CODE);
-            if (status instanceof Number) {
-                int statusCode = ((Number) status).intValue();
-                response.setStatus(statusCode);
-
-                // special treatment of 201/CREATED: Requires Location
-                if (statusCode == HttpServletResponse.SC_CREATED) {
-                    response.setHeader("Location", getLocation());
-                }
-            }
-        }
 
         response.setContentType("text/html");
         response.setCharacterEncoding("UTF-8");
 
+        // get changelog
+        changes.insert(0, "<pre>");
+        changes.append("</pre>");
+        setProperty(PN_CHANGE_LOG, changes.toString());
+
         Writer out = response.getWriter();
         InputStream template = getClass().getResourceAsStream(TEMPLATE_NAME);
         Reader in = new BufferedReader(new InputStreamReader(template));
@@ -474,7 +138,7 @@ public class HtmlResponse {
                 case 2:
                     if (c == '}') {
                         state = 0;
-                        Object prop = properties.get(varBuffer.toString());
+                        Object prop = getProperty(varBuffer.toString());
                         if (prop != null) {
                             out.write(prop.toString());
                         }

Copied: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/JSONResponse.java (from r991959, sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JSONResponse.java)
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/JSONResponse.java?p2=sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/JSONResponse.java&p1=sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JSONResponse.java&r1=991959&r2=1076637&rev=1076637&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/helper/JSONResponse.java (original)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/JSONResponse.java Thu Mar  3 14:25:56 2011
@@ -1,23 +1,23 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *   http://www.apache.org/licenses/LICENSE-2.0
  *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
  */
+package org.apache.sling.servlets.post;
 
-package org.apache.sling.servlets.post.impl.helper;
-
-import org.apache.sling.api.servlets.HtmlResponse;
 import org.apache.sling.commons.json.JSONArray;
 import org.apache.sling.commons.json.JSONException;
 import org.apache.sling.commons.json.JSONObject;
@@ -26,18 +26,28 @@ import javax.servlet.http.HttpServletRes
 import java.io.IOException;
 
 /**
- * Represents a JSON response to be sent to the client. For backward compatibility,
- * this extends {@link org.apache.sling.api.servlets.HtmlResponse}.
+ * The <code>JSONResponse</code> is an {@link AbstractPostResponse} preparing
+ * the response in JSON.
  */
-public class JSONResponse extends HtmlResponse {
-    private JSONObject json = new JSONObject();
-    private JSONArray changes = new JSONArray();
-    private Boolean delayedIsCreateRequest;
-    static final String PROP_CHANGES = "changes";
+public class JSONResponse extends AbstractPostResponse {
+
+    public static final String RESPONSE_CONTENT_TYPE = "application/json";
+
+    // package private because it is used by the unit test
     static final String PROP_TYPE = "type";
+
+    // package private because it is used by the unit test
     static final String PROP_ARGUMENT = "argument";
-    public static final String RESPONSE_CONTENT_TYPE = "application/json";
+
+    // package private because it is used by the unit test
     static final String RESPONSE_CHARSET = "UTF-8";
+
+    private static final String PROP_CHANGES = "changes";
+
+    private JSONObject json = new JSONObject();
+
+    private JSONArray changes = new JSONArray();
+
     private Throwable error;
 
     public JSONResponse() throws JSONResponseException {
@@ -45,16 +55,13 @@ public class JSONResponse extends HtmlRe
             json = new JSONObject();
             changes = new JSONArray();
             json.put(PROP_CHANGES, changes);
-            if (delayedIsCreateRequest != null) {
-                this.setCreateRequest(this.delayedIsCreateRequest);
-            }
         } catch (Throwable e) {
             throw new JSONResponseException(e);
         }
     }
 
-    @Override
-    public void onChange(String type, String... arguments)  throws JSONResponseException {
+    public void onChange(String type, String... arguments)
+            throws JSONResponseException {
         try {
             JSONObject change = new JSONObject();
             change.put(PROP_TYPE, type);
@@ -86,22 +93,12 @@ public class JSONResponse extends HtmlRe
     }
 
     @Override
-    public void setCreateRequest(boolean isCreateRequest) {
-        if (json != null) {
-            super.setCreateRequest(isCreateRequest);
-        } else {
-            // This is called by HtmlResponse constructor, before our json object is initiated.
-            // Store this in a member variable, so we can set it from our own constructor.
-            this.delayedIsCreateRequest = isCreateRequest;
-        }
-    }
-
-    @Override
     public void setProperty(String name, Object value) {
         try {
             this.json.put(name, value);
         } catch (Throwable e) {
-            throw new JSONResponseException("Error setting JSON property '" + name + "' to '" + value + "'", e);
+            throw new JSONResponseException("Error setting JSON property '"
+                + name + "' to '" + value + "'", e);
         }
     }
 
@@ -114,50 +111,17 @@ public class JSONResponse extends HtmlRe
                 return null;
             }
         } catch (JSONException e) {
-            throw new JSONResponseException("Error getting JSON property '" + name + "'", e);
+            throw new JSONResponseException("Error getting JSON property '"
+                + name + "'", e);
         }
     }
 
-    @SuppressWarnings({"ThrowableResultOfMethodCallIgnored"})
+    @SuppressWarnings({ "ThrowableResultOfMethodCallIgnored" })
     @Override
-    public void send(HttpServletResponse response, boolean setStatus) throws IOException {
-        String path = getPath();
-        if (getProperty(PN_STATUS_CODE) == null) {
-            if (getError() != null) {
-                setStatus(500, getError().toString());
-                setTitle("Error while processing " + path);
-            } else {
-                if (isCreateRequest()) {
-                    setStatus(201, "Created");
-                    setTitle("Content created " + path);
-                } else {
-                    setStatus(200, "OK");
-                    setTitle("Content modified " + path);
-                }
-            }
-        }
+    protected void doSend(HttpServletResponse response) throws IOException {
 
-        String referer = getReferer();
-        if (referer == null) {
-            referer = "";
-        }
-        setReferer(referer);
         response.setContentType(RESPONSE_CONTENT_TYPE);
         response.setCharacterEncoding(RESPONSE_CHARSET);
-        
-        // Status code
-        if (setStatus) {
-          Object status = getProperty(PN_STATUS_CODE);
-          if (status instanceof Number) {
-              int statusCode = ((Number) status).intValue();
-              response.setStatus(statusCode);
-
-              // special treatment of 201/CREATED: Requires Location
-              if (statusCode == HttpServletResponse.SC_CREATED) {
-                  response.setHeader("Location", getLocation());
-              }
-          }
-      }
 
         try {
             json.write(response.getWriter());

Added: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/PostOperation.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/PostOperation.java?rev=1076637&view=auto
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/PostOperation.java (added)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/PostOperation.java Thu Mar  3 14:25:56 2011
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.servlets.post;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+
+/**
+ * The <code>PostOperation</code> interface defines the service API to be
+ * implemented by service providers extending the Sling POST servlet. Service
+ * providers may register OSGi services of this type to be used by the Sling
+ * default POST servlet to handle specific operations.
+ * <p>
+ * The <code>PostOperation</code> service must be registered with a
+ * {@link #PROP_OPERATION_NAME} registration property giving the name(s) of the
+ * operations supported by the service. The names will be used to find the
+ * actual operation from the {@link SlingPostConstants#RP_OPERATION
+ * <code>:operation</code>} request parameter.
+ * <p>
+ * The Sling POST servlet itself provides various operations (see the
+ * <code>OPERATION_</code> constants in the {@link SlingPostConstants}
+ * interface.These names should not be used by <code>SlingPostOperation</code>
+ * service providers.
+ * <p>
+ * This interface replaces the old {@link SlingPostOperation} service interface
+ * adding support for extensible responses by means of the {@link PostResponse}
+ * interface as well as operation postprocessing.
+ * <p>
+ * Implementors of this interface are advised to extend the
+ * {@link AbstractPostOperation} class to benefit from various precossings
+ * implemented by that abstract class.
+ */
+public interface PostOperation {
+
+    /**
+     * The name of the Sling POST operation service.
+     */
+    public static final String SERVICE_NAME = "org.apache.sling.servlets.post.PostOperation";
+
+    /**
+     * The name of the service registration property indicating the name(s) of
+     * the operation provided by the operation implementation. The value of this
+     * service property must be a single String or an array or
+     * <code>java.util.Collection</code> of Strings. If multiple strings are
+     * defined, the service is registered for all operation names.
+     */
+    public static final String PROP_OPERATION_NAME = "sling.post.operation";
+
+    /**
+     * Executes the operation provided by this service implementation. This
+     * method is called by the Sling POST servlet.
+     *
+     * @param request The <code>SlingHttpServletRequest</code> object providing
+     *            the request input for the operation.
+     * @param response The <code>HtmlResponse</code> into which the operation
+     *            steps should be recorded.
+     * @param processors The {@link SlingPostProcessor} services to be called
+     *            after applying the operation. This may be <code>null</code> if
+     *            there are none.
+     * @throws org.apache.sling.api.resource.ResourceNotFoundException May be
+     *             thrown if the operation requires an existing request
+     *             resource. If this exception is thrown the Sling POST servlet
+     *             sends back a <code>404/NOT FOUND</code> response to the
+     *             client.
+     * @throws org.apache.sling.api.SlingException May be thrown if an error
+     *             occurrs running the operation.
+     */
+    void run(SlingHttpServletRequest request, PostResponse response,
+            SlingPostProcessor[] processors);
+}

Propchange: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/PostOperation.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/PostOperation.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Added: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/PostResponse.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/PostResponse.java?rev=1076637&view=auto
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/PostResponse.java (added)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/PostResponse.java Thu Mar  3 14:25:56 2011
@@ -0,0 +1,216 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.servlets.post;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * The <code>PostResponse</code> interface defines the API of a response
+ * container which can (and should) be used by {@link PostOperation} services to
+ * prepare responses to be sent back to the client.
+ * <p>
+ * This bundle provides a preconfigured {@link HtmlResponse} and a
+ * {@link JSONResponse} implementation of this interface. Clients may extend the
+ * {@link AbstractPostResponse} class to provide their own response
+ * implementations.
+ */
+public interface PostResponse {
+
+    /**
+     * Sets the referer property
+     */
+    public void setReferer(String referer);
+
+    /**
+     * Returns the referer previously set by {@link #setReferer(String)}
+     */
+    public String getReferer();
+
+    /**
+     * Sets the absolute path of the item upon which the request operated.
+     */
+    public void setPath(String path);
+
+    /**
+     * Returns the absolute path of the item upon which the request operated.
+     * <p>
+     * If the {@link #setPath(String)} method has not been called yet, this
+     * method returns <code>null</code>.
+     */
+    public String getPath();
+
+    /**
+     * Sets whether the request was a create request or not.
+     */
+    public void setCreateRequest(boolean isCreateRequest);
+
+    /**
+     * Returns <code>true</code> if this was a create request.
+     * <p>
+     * Before calling the {@link #setCreateRequest(boolean)} method, this method
+     * always returns <code>false</code>.
+     */
+    public boolean isCreateRequest();
+
+    /**
+     * Sets the location of this modification. This is the externalized form of
+     * the {@link #getPath() current path}.
+     *
+     * @param location
+     */
+    public void setLocation(String location);
+
+    /**
+     * Returns the location of the modification.
+     * <p>
+     * If the {@link #setLocation(String)} method has not been called yet, this
+     * method returns <code>null</code>.
+     */
+    public String getLocation();
+
+    /**
+     * Sets the parent location of the modification. This is the externalized
+     * form of the parent node of the {@link #getPath() current path}.
+     */
+    public void setParentLocation(String parentLocation);
+
+    /**
+     * Returns the parent location of the modification.
+     * <p>
+     * If the {@link #setParentLocation(String)} method has not been called yet,
+     * this method returns <code>null</code>.
+     */
+    public String getParentLocation();
+
+    /**
+     * Sets the title of the response message
+     *
+     * @param title the title
+     */
+    public void setTitle(String title);
+
+    /**
+     * Sets the response status code properties
+     *
+     * @param code the code
+     * @param message the message
+     */
+    public void setStatus(int code, String message);
+
+    /**
+     * Returns the status code of this instance. If the status code has never
+     * been set by calling the {@link #setStatus(int, String)} method, the
+     * status code is determined by checking if there was an error. If there was
+     * an error, the response is assumed to be unsuccessful and 500 is returned.
+     * If there is no error, the response is assumed to be successful and 200 is
+     * returned.
+     */
+    public int getStatusCode();
+
+    /**
+     * Returns the status message or <code>null</code> if no has been set with
+     * the {@link #setStatus(int, String)} method.
+     */
+    public String getStatusMessage();
+
+    /**
+     * Sets the recorded error causing the operation to fail.
+     */
+    public void setError(Throwable error);
+
+    /**
+     * Returns any recorded error or <code>null</code>
+     *
+     * @return an error or <code>null</code>
+     */
+    public Throwable getError();
+
+    /**
+     * Returns <code>true</code> if no {@link #getError() error} is set and if
+     * the {@link #getStatusCode() status code} is one of the 2xx codes.
+     */
+    public boolean isSuccessful();
+
+    // ---------- ChangeLog ----------------------------------------------------
+
+    /**
+     * Records a 'created' change
+     *
+     * @param path path of the item that was created
+     */
+    public void onCreated(String path);
+
+    /**
+     * Records a 'modified' change
+     *
+     * @param path path of the item that was modified
+     */
+    public void onModified(String path);
+
+    /**
+     * Records a 'deleted' change
+     *
+     * @param path path of the item that was deleted
+     */
+    public void onDeleted(String path);
+
+    /**
+     * Records a 'moved' change.
+     * <p/>
+     * Note: the moved change only records the basic move command. the implied
+     * changes on the moved properties and sub nodes are not recorded.
+     *
+     * @param srcPath source path of the node that was moved
+     * @param dstPath destination path of the node that was moved.
+     */
+    public void onMoved(String srcPath, String dstPath);
+
+    /**
+     * Records a 'copied' change.
+     * <p/>
+     * Note: the copy change only records the basic copy command. the implied
+     * changes on the copied properties and sub nodes are not recorded.
+     *
+     * @param srcPath source path of the node that was copied
+     * @param dstPath destination path of the node that was copied.
+     */
+    public void onCopied(String srcPath, String dstPath);
+
+    /**
+     * Records a generic change of the given <code>type</code> with arguments.
+     *
+     * @param type The type of the modification
+     * @param arguments The arguments to the modifications
+     */
+    void onChange(String type, String... arguments);
+
+    /**
+     * Writes the response back over the provided HTTP channel. The actual
+     * format of the response is implementation dependent.
+     *
+     * @param response to send to
+     * @param setStatus whether to set the status code on the response
+     * @throws IOException if an i/o exception occurs
+     */
+    void send(HttpServletResponse response, boolean setStatus)
+            throws IOException;
+
+}
\ No newline at end of file

Propchange: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/PostResponse.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/PostResponse.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev Url

Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/SlingPostConstants.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/SlingPostConstants.java?rev=1076637&r1=1076636&r2=1076637&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/SlingPostConstants.java (original)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/SlingPostConstants.java Thu Mar  3 14:25:56 2011
@@ -58,6 +58,19 @@ public interface SlingPostConstants {
     public static final String STAR_CREATE_SUFFIX = "/*";
 
     /**
+     * Name of the predefined modify operation (value is "modify").
+     * <p>
+     * The modify operation uses the remaining request parameters to indicate
+     * nodes and properties to create.
+     * <p>
+     * The modify operation is actually chosen by the Sling POST Servlet if the
+     * request has no {@link #RP_OPERATION} request parameter.
+     *
+     * @since 2.0.6 (Bundle version 2.0.6)
+     */
+    public static final String OPERATION_MODIFY = "modify";
+
+    /**
      * Name of the predefined delete operation (value is "delete").
      * <p>
      * The delete operation requires no further request parameters and just
@@ -133,11 +146,11 @@ public interface SlingPostConstants {
 
     /**
      * Name of the predefined import operation (value is "import").
-     * 
+     *
      * <p>
-     * The import operation requires either the {@link #RP_CONTENT} and {@link #RP_CONTENT_TYPE} 
+     * The import operation requires either the {@link #RP_CONTENT} and {@link #RP_CONTENT_TYPE}
      * request parameters or the {@link #RP_CONTENT_FILE} request parameter.
-     * Finally the {@link #RP_REPLACE} parameter may be set to indicate whether 
+     * Finally the {@link #RP_REPLACE} parameter may be set to indicate whether
      * an existing item at the destination should be overwritten or not.
      */
     public static final String OPERATION_IMPORT = "import";
@@ -165,9 +178,9 @@ public interface SlingPostConstants {
      * copy or move operation is to be replaced if existing (value is
      * ":replace"). Copy or move is only possible if the destination exists if
      * the replace parameter is set to the case-insignificant value true.
-     * 
+     *
      * This request parameter is also used to indicate whether the destination node
-     * for an import operation is to be replaced if existing. The parameter value is 
+     * for an import operation is to be replaced if existing. The parameter value is
      * checked to see if it matches the case-insignificant value true.
      */
     public static final String RP_REPLACE = RP_PREFIX + "replace";
@@ -175,11 +188,11 @@ public interface SlingPostConstants {
     /**
      * Name of the request parameter indicating whether the destination for a
      * property change during an import operation is to be replaced if existing.
-     * The parameter value is checked to see if it matches the case-insignificant 
+     * The parameter value is checked to see if it matches the case-insignificant
      * value true.
      */
     public static final String RP_REPLACE_PROPERTIES = RP_PREFIX + "replaceProperties";
-    
+
     /**
      * Optional request parameter indicating the order of newly created nodes in
      * creation, copy and move operation requests (value is ":order").
@@ -394,7 +407,7 @@ public interface SlingPostConstants {
      * useful for HTML checkboxes.
      */
     public static final String SUFFIX_USE_DEFAULT_WHEN_MISSING = "@UseDefaultWhenMissing";
-    
+
     /**
      * Name of the request parameter containing the content to be imported
      * by the 'import' operation.
@@ -406,7 +419,7 @@ public interface SlingPostConstants {
      * to be imported by the 'import' operation.
      */
     public static final String RP_CONTENT_TYPE = RP_PREFIX + "contentType";
-    
+
     /**
      * Name of the request parameter containing the file to be imported
      * by the 'import' operation.
@@ -414,9 +427,9 @@ public interface SlingPostConstants {
     public static final String RP_CONTENT_FILE = RP_PREFIX + "contentFile";
 
     /**
-     * Name of the request parameter indicating whether versionable nodes should 
+     * Name of the request parameter indicating whether versionable nodes should
      * be checked in during an {@link SlingPostConstants#OPERATION_IMPORT} operation.
      */
     public static final String RP_CHECKIN = RP_PREFIX + "checkin";
-    
+
 }



Mime
View raw message