Author: justin
Date: Tue Dec 13 15:46:36 2016
New Revision: 1774040

URL: http://svn.apache.org/viewvc?rev=1774040&view=rev
Log:
SLING-6187 - implement requiredPostProcessors parameter

Modified:
    
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/SlingPostServlet.java
    
sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/SlingPostServletTest.java
    
sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/helper/MockSlingHttpServlet3Response.java

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=1774040&r1=1774039&r2=1774040&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
 Tue Dec 13 15:46:36 2016
@@ -20,6 +20,7 @@ import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.Iterator;
@@ -138,6 +139,10 @@ public class SlingPostServlet extends Sl
 
     private static final String PARAM_AUTO_CHECKIN = ":autoCheckin";
 
+    private static final String PARAM_REQUIRED_POST_PROCESSORS = 
":requiredPostProcessors";
+
+    private static final String PROP_POST_PROCESSOR_NAME = 
"postProcessor.name";
+
     private static final String DEFAULT_IGNORED_PARAMETER_NAME_PATTERN = 
"j_.*";
 
     @Property(value = DEFAULT_IGNORED_PARAMETER_NAME_PATTERN)
@@ -158,6 +163,9 @@ public class SlingPostServlet extends Sl
     /** Cached list of post processors, used during request processing. */
     private SlingPostProcessor[] cachedPostProcessors = new 
SlingPostProcessor[0];
 
+    /** Cached list of post processor names, used during request processing. */
+    private String[] cachedPostProcessorNames = new String[0];
+
     /** Sorted list of node name generator holders. */
     private final List<NodeNameGeneratorHolder> nodeNameGenerators = new 
ArrayList<NodeNameGeneratorHolder>();
 
@@ -198,19 +206,25 @@ public class SlingPostServlet extends Sl
                 "Invalid operation specified for POST request");
 
         } else {
-            request.getRequestProgressTracker().log(
-                    "Calling PostOperation: {0}", 
operation.getClass().getName());
             final SlingPostProcessor[] processors = this.cachedPostProcessors;
-            try {
-                operation.run(request, htmlResponse, processors);
-            } catch (ResourceNotFoundException rnfe) {
-                htmlResponse.setStatus(HttpServletResponse.SC_NOT_FOUND,
-                    rnfe.getMessage());
-            } catch (final Exception exception) {
-                log.warn("Exception while handling POST "
-                    + request.getResource().getPath() + " with "
-                    + operation.getClass().getName(), exception);
-                htmlResponse.setError(exception);
+            final String[] processorNames = this.cachedPostProcessorNames;
+            if (checkPostProcessors(request, processorNames)) {
+                request.getRequestProgressTracker().log(
+                        "Calling PostOperation: {0}", 
operation.getClass().getName());
+                try {
+                    operation.run(request, htmlResponse, processors);
+                } catch (ResourceNotFoundException rnfe) {
+                    htmlResponse.setStatus(HttpServletResponse.SC_NOT_FOUND,
+                        rnfe.getMessage());
+                } catch (final Exception exception) {
+                    log.warn("Exception while handling POST "
+                        + request.getResource().getPath() + " with "
+                        + operation.getClass().getName(), exception);
+                    htmlResponse.setError(exception);
+                }
+            } else {
+                htmlResponse.setStatus(HttpServletResponse.SC_NOT_IMPLEMENTED,
+                        "At least one of the expected PostProcessors was not 
available.");
             }
 
         }
@@ -260,13 +274,13 @@ public class SlingPostServlet extends Sl
     /**
      * Creates an instance of a PostResponse.
      * @param req The request being serviced
-     * @return a {@link 
org.apache.sling.servlets.post.impl.helper.JSONResponse} if any of these 
conditions are true:
+     * @return a {@link org.apache.sling.servlets.post.JSONResponse} if any of 
these conditions are true:
      * <ul>
      *   <li> the request has an <code>Accept</code> header of 
<code>application/json</code></li>
      *   <li>the request is a JSON POST request (see SLING-1172)</li>
      *   <li>the request has a request parameter 
<code>:accept=application/json</code></li>
      * </ul>
-     * or a {@link org.apache.sling.api.servlets.PostResponse} otherwise
+     * or a {@link org.apache.sling.servlets.post.PostResponse} otherwise
      */
     PostResponse createPostResponse(final SlingHttpServletRequest req) {
         for (final PostResponseCreator creator : cachedPostResponseCreators) {
@@ -531,6 +545,7 @@ public class SlingPostServlet extends Sl
         final PostProcessorHolder pph = new PostProcessorHolder();
         pph.processor = processor;
         pph.ranking = 
OsgiUtil.toInteger(properties.get(Constants.SERVICE_RANKING), 0);
+        pph.name = OsgiUtil.toString(properties.get(PROP_POST_PROCESSOR_NAME), 
null);
 
         synchronized ( this.postProcessors ) {
             int index = 0;
@@ -569,12 +584,15 @@ public class SlingPostServlet extends Sl
      */
     private void updatePostProcessorCache() {
         final SlingPostProcessor[] localCache = new 
SlingPostProcessor[this.postProcessors.size()];
+        final String[] localNameCache = new String[this.postProcessors.size()];
         int index = 0;
         for(final PostProcessorHolder current : this.postProcessors) {
             localCache[index] = current.processor;
+            localNameCache[index] = current.name != null ? current.name : 
current.processor.getClass().getSimpleName();
             index++;
         }
         this.cachedPostProcessors = localCache;
+        this.cachedPostProcessorNames = localNameCache;
     }
 
     /**
@@ -726,8 +744,34 @@ public class SlingPostServlet extends Sl
         return cfg;
     }
 
+    private boolean checkPostProcessors(SlingHttpServletRequest request, 
String[] processorNames) {
+        String param = request.getParameter(PARAM_REQUIRED_POST_PROCESSORS);
+        if (param == null) {
+            return true;
+        } else {
+            List<String> requiredPostProcessors = new 
ArrayList<String>(Arrays.asList(param.split(",")));
+            Iterator<String> iterator = requiredPostProcessors.iterator();
+            while (iterator.hasNext()) {
+                String requiredPostProcessor = iterator.next();
+                for (String name : processorNames) {
+                    if (name.equals(requiredPostProcessor)) {
+                        iterator.remove();
+                        break;
+                    }
+                }
+            }
+            if (!requiredPostProcessors.isEmpty()) {
+                log.warn("Some required post processors were not available: 
{}", requiredPostProcessors);
+                return false;
+            } else {
+                return true;
+            }
+        }
+    }
+
     private static final class PostProcessorHolder {
         public SlingPostProcessor processor;
+        public String name;
         public int ranking;
     }
 

Modified: 
sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/SlingPostServletTest.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/SlingPostServletTest.java?rev=1774040&r1=1774039&r2=1774040&view=diff
==============================================================================
--- 
sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/SlingPostServletTest.java
 (original)
+++ 
sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/SlingPostServletTest.java
 Tue Dec 13 15:46:36 2016
@@ -20,20 +20,35 @@ package org.apache.sling.servlets.post.i
 
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
+import java.net.URL;
 import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
 import java.util.StringTokenizer;
 
 import junit.framework.TestCase;
 
 import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.commons.testing.osgi.MockBundle;
+import org.apache.sling.commons.testing.osgi.MockComponentContext;
 import org.apache.sling.commons.testing.sling.MockSlingHttpServletRequest;
 import org.apache.sling.servlets.post.HtmlResponse;
 import org.apache.sling.servlets.post.JSONResponse;
+import org.apache.sling.servlets.post.Modification;
+import org.apache.sling.servlets.post.PostOperation;
 import org.apache.sling.servlets.post.PostResponse;
 import org.apache.sling.servlets.post.SlingPostConstants;
+import org.apache.sling.servlets.post.SlingPostOperation;
+import org.apache.sling.servlets.post.SlingPostProcessor;
 import org.apache.sling.servlets.post.impl.helper.MediaRangeList;
 import org.apache.sling.servlets.post.impl.helper.MockSlingHttpServlet3Request;
 import 
org.apache.sling.servlets.post.impl.helper.MockSlingHttpServlet3Response;
+import org.osgi.framework.Constants;
 
 public class SlingPostServletTest extends TestCase {
     
@@ -43,6 +58,38 @@ public class SlingPostServletTest extend
     protected void setUp() throws Exception {
         super.setUp();
         servlet = new SlingPostServlet();
+        MockBundle bundle = new MockBundle(1) {
+            @Override
+            public Dictionary<String, String> getHeaders() {
+                Hashtable<String, String> headers = new Hashtable<String, 
String>();
+                headers.put(Constants.BUNDLE_VENDOR, "test");
+                return headers;
+            }
+
+            @Override
+            public Dictionary<String, String> getHeaders(String locale) {
+                return getHeaders();
+            }
+
+            @Override
+            public Enumeration<URL> findEntries(String path, String 
filePattern, boolean recurse) {
+                return null;
+            }
+
+            @Override
+            public Enumeration<String> getEntryPaths(String path) {
+                return null;
+            }
+
+            @Override
+            public Enumeration<URL> getResources(String name) {
+                return null;
+            }
+        };
+        MockComponentContext componentContext = new 
MockComponentContext(bundle);
+        Map<String, Object> props = new HashMap<String, Object>();
+        props.put("servlet.post.dateFormats", new String[] { "EEE MMM dd yyyy 
HH:mm:ss 'GMT'Z" });
+        servlet.activate(componentContext, props);
     }
 
     public void testIsSetStatus() {
@@ -102,6 +149,109 @@ public class SlingPostServletTest extend
         testRedirection("/", "/fred/abc", 
"file://c:\\Users\\workspace\\test.java", null);
     }
 
+    public void testNonExistingOperation() throws Exception {
+        MockSlingHttpServletRequest request = new 
MockSlingHttpServlet3Request(null, null, null, null, null) {
+            @Override
+            public String getParameter(String name) {
+                if (name.equals(SlingPostConstants.RP_OPERATION)) {
+                    return "doesntexist";
+                }
+                return null;
+            }
+        };
+        MockSlingHttpServlet3Response response = new 
MockSlingHttpServlet3Response();
+        servlet.doPost(request, response);
+        assertEquals(500, response.getStatus());
+    }
+
+    public void testNonExistingPostProcessor() throws Exception {
+        servlet.bindPostOperation(new PostOperation() {
+            @Override
+            public void run(SlingHttpServletRequest request, PostResponse 
response, SlingPostProcessor[] processors) {
+                // noop
+            }
+        }, Collections.<String, 
Object>singletonMap(SlingPostOperation.PROP_OPERATION_NAME, "noop"));
+
+        MockSlingHttpServletRequest request = new 
MockSlingHttpServlet3Request(null, null, null, null, null) {
+            @Override
+            public String getParameter(String name) {
+                if (name.equals(SlingPostConstants.RP_OPERATION)) {
+                    return "noop";
+                } else if (name.equals(":requiredPostProcessors")) {
+                    return "doesntexist";
+                }
+                return null;
+            }
+        };
+        MockSlingHttpServlet3Response response = new 
MockSlingHttpServlet3Response();
+        servlet.doPost(request, response);
+        assertEquals(501, response.getStatus());
+    }
+
+
+
+    public void testNonExistingPostProcessorWithMultipleRequired() throws 
Exception {
+        servlet.bindPostOperation(new PostOperation() {
+            @Override
+            public void run(SlingHttpServletRequest request, PostResponse 
response, SlingPostProcessor[] processors) {
+                // noop
+            }
+        }, Collections.<String, 
Object>singletonMap(SlingPostOperation.PROP_OPERATION_NAME, "noop"));
+
+        servlet.bindPostProcessor(new SlingPostProcessor() {
+            @Override
+            public void process(SlingHttpServletRequest request, 
List<Modification> changes) throws Exception {
+                // noop
+            }
+        }, Collections.<String, Object>singletonMap("postProcessor.name", 
"noop"));
+
+        MockSlingHttpServletRequest request = new 
MockSlingHttpServlet3Request(null, null, null, null, null) {
+            @Override
+            public String getParameter(String name) {
+                if (name.equals(SlingPostConstants.RP_OPERATION)) {
+                    return "noop";
+                } else if (name.equals(":requiredPostProcessors")) {
+                    return "noop,doesntexist";
+                }
+                return null;
+            }
+        };
+        MockSlingHttpServlet3Response response = new 
MockSlingHttpServlet3Response();
+        servlet.doPost(request, response);
+        assertEquals(501, response.getStatus());
+    }
+
+    public void testRequiredPostProcessor() throws Exception {
+        servlet.bindPostOperation(new PostOperation() {
+            @Override
+            public void run(SlingHttpServletRequest request, PostResponse 
response, SlingPostProcessor[] processors) {
+                // noop
+            }
+        }, Collections.<String, 
Object>singletonMap(SlingPostOperation.PROP_OPERATION_NAME, "noop"));
+
+        servlet.bindPostProcessor(new SlingPostProcessor() {
+            @Override
+            public void process(SlingHttpServletRequest request, 
List<Modification> changes) throws Exception {
+                // noop
+            }
+        }, Collections.<String, Object>singletonMap("postProcessor.name", 
"noop"));
+
+        MockSlingHttpServletRequest request = new 
MockSlingHttpServlet3Request(null, null, null, null, null) {
+            @Override
+            public String getParameter(String name) {
+                if (name.equals(SlingPostConstants.RP_OPERATION)) {
+                    return "noop";
+                } else if (name.equals(":requiredPostProcessors")) {
+                    return "noop";
+                }
+                return null;
+            }
+        };
+        MockSlingHttpServlet3Response response = new 
MockSlingHttpServlet3Response();
+        servlet.doPost(request, response);
+        assertEquals(200, response.getStatus());
+    }
+
     private void testRedirection(String requestPath, String resourcePath, 
String redirect, String expected) 
             throws Exception {
         RedirectServletResponse resp = new RedirectServletResponse();

Modified: 
sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/helper/MockSlingHttpServlet3Response.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/helper/MockSlingHttpServlet3Response.java?rev=1774040&r1=1774039&r2=1774040&view=diff
==============================================================================
--- 
sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/helper/MockSlingHttpServlet3Response.java
 (original)
+++ 
sling/trunk/bundles/servlets/post/src/test/java/org/apache/sling/servlets/post/impl/helper/MockSlingHttpServlet3Response.java
 Tue Dec 13 15:46:36 2016
@@ -24,9 +24,22 @@ import java.util.Collection;
  * When MockSlingHttpServletResponse supports Servlet 3 correctly, delete this 
class.
  */
 public class MockSlingHttpServlet3Response extends 
MockSlingHttpServletResponse {
+
+    private int status = 200;
+
+    @Override
+    public void setStatus(int status) {
+        this.status = status;
+    }
+
+    @Override
+    public void setStatus(int i, String s) {
+        setStatus(i);
+    }
+
     @Override
     public int getStatus() {
-        return 0;
+        return status;
     }
 
     @Override


Reply via email to