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