You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by lq...@apache.org on 2016/06/14 10:57:28 UTC
svn commit: r1748386 - in
/qpid/java/trunk/broker-plugins/management-http/src:
main/java/org/apache/qpid/server/management/plugin/
main/java/org/apache/qpid/server/management/plugin/servlet/rest/
test/java/org/apache/qpid/server/management/plugin/servl...
Author: lquack
Date: Tue Jun 14 10:57:27 2016
New Revision: 1748386
URL: http://svn.apache.org/viewvc?rev=1748386&view=rev
Log:
QPID-7124: [Java Broker] Improve parsing of REST URLs
Added:
qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RequestInfo.java
qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RequestInfoParser.java
qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/RequestInfoParserTest.java
Modified:
qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java
qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerQueryServlet.java
qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueReportServlet.java
qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/UserPreferencesServlet.java
qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostQueryServlet.java
Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java?rev=1748386&r1=1748385&r2=1748386&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java Tue Jun 14 10:57:27 2016
@@ -22,11 +22,14 @@ package org.apache.qpid.server.managemen
import java.io.IOException;
import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -204,4 +207,28 @@ public class HttpManagementUtil
{
return requestedFilename.replaceAll("[\\P{InBasic_Latin}\\\\:/\\p{Cntrl}]", "");
}
+
+ public static List<String> getPathInfoElements(final String servletPath, final String pathInfo)
+ {
+ if (pathInfo == null || pathInfo.length() == 0)
+ {
+ return Collections.emptyList();
+ }
+
+ String[] pathInfoElements = pathInfo.substring(1).split("/");
+ for (int i = 0; i < pathInfoElements.length; i++)
+ {
+ try
+ {
+ // double decode to allow slashes in object names. first decoding happens in request.getPathInfo().
+ pathInfoElements[i] = URLDecoder.decode(pathInfoElements[i], StandardCharsets.UTF_8.name());
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new IllegalArgumentException("Servlet at " + servletPath
+ + " could not decode path element: " + pathInfoElements[i], e);
+ }
+ }
+ return Arrays.asList(pathInfoElements);
+ }
}
Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java?rev=1748386&r1=1748385&r2=1748386&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java Tue Jun 14 10:57:27 2016
@@ -22,9 +22,7 @@ package org.apache.qpid.server.managemen
import java.io.IOException;
import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
-import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
@@ -321,29 +319,6 @@ public abstract class AbstractServlet ex
response.setDateHeader("Expires", 0);
}
- protected String[] getPathInfoElements(HttpServletRequest request)
- {
- String pathInfo = request.getPathInfo();
- if (pathInfo != null && pathInfo.length() > 0)
- {
- String[] pathInfoElements = pathInfo.substring(1).split("/");
- for (int i = 0; i < pathInfoElements.length; i++)
- {
- try
- {
- // double decode to allow slashes in object names. first decoding happens in request.getPathInfo().
- pathInfoElements[i] = URLDecoder.decode(pathInfoElements[i], "UTF-8");
- }
- catch (UnsupportedEncodingException e)
- {
- throw new IllegalArgumentException("REST servlet " + getServletName() + " could not decode path element: " + pathInfoElements[i], e);
- }
- }
- return pathInfoElements;
- }
- return null;
- }
-
protected void writeTypedContent(Content content, HttpServletRequest request, HttpServletResponse response) throws IOException
{
try(OutputStream os = getOutputStream(request, response))
Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerQueryServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerQueryServlet.java?rev=1748386&r1=1748385&r2=1748386&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerQueryServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerQueryServlet.java Tue Jun 14 10:57:27 2016
@@ -59,10 +59,11 @@ public class BrokerQueryServlet extends
protected String getRequestedCategory(final HttpServletRequest request)
{
- String[] pathInfoElements = getPathInfoElements(request);
- if(pathInfoElements.length == 1)
+ List<String> pathInfoElements =
+ HttpManagementUtil.getPathInfoElements(request.getServletPath(), request.getPathInfo());
+ if (pathInfoElements.size() == 1)
{
- return pathInfoElements[0];
+ return pathInfoElements.get(0);
}
return null;
}
Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueReportServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueReportServlet.java?rev=1748386&r1=1748385&r2=1748386&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueReportServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueReportServlet.java Tue Jun 14 10:57:27 2016
@@ -21,11 +21,13 @@
package org.apache.qpid.server.management.plugin.servlet.rest;
import java.io.IOException;
+import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.qpid.server.management.plugin.HttpManagementUtil;
import org.apache.qpid.server.management.plugin.report.ReportRunner;
import org.apache.qpid.server.model.Queue;
import org.apache.qpid.server.model.VirtualHost;
@@ -37,11 +39,12 @@ public class QueueReportServlet extends
IOException,
ServletException
{
- String[] pathInfoElements = getPathInfoElements(request);
- if(pathInfoElements != null && pathInfoElements.length == 3)
+ List<String> pathInfoElements =
+ HttpManagementUtil.getPathInfoElements(request.getServletPath(), request.getPathInfo());
+ if (pathInfoElements.size() == 3)
{
- Queue<?> queue = getQueueFromRequest(request);
- ReportRunner<?> reportRunner = ReportRunner.createRunner(pathInfoElements[2],request.getParameterMap());
+ Queue<?> queue = getQueueFromRequest(pathInfoElements);
+ ReportRunner<?> reportRunner = ReportRunner.createRunner(pathInfoElements.get(2),request.getParameterMap());
Object output = reportRunner.runReport(queue);
response.setContentType(reportRunner.getContentType());
if(reportRunner.isBinaryReport())
@@ -60,15 +63,14 @@ public class QueueReportServlet extends
}
- private Queue<?> getQueueFromRequest(HttpServletRequest request)
+ private Queue<?> getQueueFromRequest(final List<String> pathInfoElements)
{
- String[] pathInfoElements = getPathInfoElements(request);
- if(pathInfoElements == null || pathInfoElements.length < 2)
+ if (pathInfoElements.size() < 2)
{
throw new IllegalArgumentException("Invalid path is specified");
}
- String vhostName = pathInfoElements[0];
- String queueName = pathInfoElements[1];
+ String vhostName = pathInfoElements.get(0);
+ String queueName = pathInfoElements.get(1);
VirtualHost<?> vhost = getBroker().findVirtualHostByName(vhostName);
if (vhost == null)
Added: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RequestInfo.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RequestInfo.java?rev=1748386&view=auto
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RequestInfo.java (added)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RequestInfo.java Tue Jun 14 10:57:27 2016
@@ -0,0 +1,66 @@
+/*
+ * 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.qpid.server.management.plugin.servlet.rest;
+
+import java.util.Collections;
+import java.util.List;
+
+public class RequestInfo
+{
+ private final RequestType _type;
+ private final List<String> _modelParts;
+ private final String _operationName;
+
+ public RequestInfo(final RequestType type, final List<String> modelParts)
+ {
+ this(type, modelParts, null);
+ }
+
+ public RequestInfo(final RequestType type, final List<String> modelParts, final String operationName)
+ {
+ _type = type;
+ _operationName = operationName;
+ _modelParts = Collections.unmodifiableList(modelParts);
+ }
+
+ public RequestType getType()
+ {
+ return _type;
+ }
+
+ public List<String> getModelParts()
+ {
+ return _modelParts;
+ }
+
+ public String getOperationName()
+ {
+ if (_type != RequestType.OPERATION)
+ {
+ throw new IllegalStateException("Must not call getOperationName on non-Operation RequestInfo");
+ }
+ return _operationName;
+ }
+
+ enum RequestType
+ {
+ OPERATION, MODEL_OBJECT
+ }
+}
Added: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RequestInfoParser.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RequestInfoParser.java?rev=1748386&view=auto
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RequestInfoParser.java (added)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RequestInfoParser.java Tue Jun 14 10:57:27 2016
@@ -0,0 +1,153 @@
+/*
+ * 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.qpid.server.management.plugin.servlet.rest;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.qpid.server.management.plugin.HttpManagementUtil;
+import org.apache.qpid.server.model.ConfiguredObject;
+
+public class RequestInfoParser
+{
+ private final List<Class<? extends ConfiguredObject>> _hierarchy;
+
+ public RequestInfoParser(final Class<? extends ConfiguredObject>... hierarchy)
+ {
+ _hierarchy = Arrays.asList(hierarchy);
+ }
+
+ public RequestInfo parse(final HttpServletRequest request)
+ {
+ final String servletPath = request.getServletPath();
+ final String pathInfo = (request.getPathInfo() != null ? request.getPathInfo() : "");
+ List<String> parts = HttpManagementUtil.getPathInfoElements(servletPath, pathInfo);
+
+ final String method = request.getMethod();
+ if ("POST".equals(method))
+ {
+ return parsePost(servletPath, pathInfo, parts);
+ }
+ else if ("PUT".equals(method))
+ {
+ return parsePut(servletPath, pathInfo, parts);
+ }
+ else if ("GET".equals(method))
+ {
+ return parseGet(servletPath, pathInfo, parts);
+ }
+ else if ("DELETE".equals(method))
+ {
+ return parseDelete(servletPath, pathInfo, parts);
+ }
+ else
+ {
+ throw new IllegalArgumentException(String.format("Unexpected method type '%s' for path '%s%s'",
+ method, servletPath, pathInfo));
+ }
+ }
+
+ private RequestInfo parseDelete(final String servletPath, final String pathInfo, final List<String> parts)
+ {
+ if (parts.size() <= _hierarchy.size())
+ {
+ return new RequestInfo(RequestInfo.RequestType.MODEL_OBJECT, parts);
+ }
+ else
+ {
+ String expectedPath = buildExpectedPath(servletPath, _hierarchy);
+ throw new IllegalArgumentException(String.format("Invalid DELETE path '%s%s'. Expected: '%s'",
+ servletPath, pathInfo,
+ expectedPath));
+ }
+ }
+
+ private RequestInfo parseGet(final String servletPath, final String pathInfo, final List<String> parts)
+ {
+ if (parts.size() <= _hierarchy.size())
+ {
+ return new RequestInfo(RequestInfo.RequestType.MODEL_OBJECT, parts);
+ }
+ else if (parts.size() == _hierarchy.size() + 1)
+ {
+ return new RequestInfo(RequestInfo.RequestType.OPERATION, parts.subList(0, _hierarchy.size()),
+ parts.get(parts.size() - 1));
+ }
+ else
+ {
+ String expectedPath = buildExpectedPath(servletPath, _hierarchy);
+ throw new IllegalArgumentException(String.format("Invalid GET path '%s%s'. Expected: '%s[/<operation name>]'",
+ servletPath, pathInfo,
+ expectedPath));
+ }
+ }
+
+ private RequestInfo parsePut(final String servletPath, final String pathInfo, final List<String> parts)
+ {
+ if (parts.size() == _hierarchy.size() || parts.size() == _hierarchy.size() - 1)
+ {
+ return new RequestInfo(RequestInfo.RequestType.MODEL_OBJECT, parts);
+ }
+ else
+ {
+ String expectedPath = buildExpectedPath(servletPath, _hierarchy);
+ throw new IllegalArgumentException(String.format("Invalid PUT path '%s%s'. Expected: '%s'",
+ servletPath, pathInfo,
+ expectedPath));
+ }
+ }
+
+ private RequestInfo parsePost(final String servletPath, final String pathInfo, final List<String> parts)
+ {
+ if (parts.size() == _hierarchy.size() || parts.size() == _hierarchy.size() - 1)
+ {
+ return new RequestInfo(RequestInfo.RequestType.MODEL_OBJECT, parts);
+ }
+ else if (parts.size() == _hierarchy.size() + 1)
+ {
+ return new RequestInfo(RequestInfo.RequestType.OPERATION, parts.subList(0, _hierarchy.size()),
+ parts.get(parts.size() - 1));
+ }
+ else
+ {
+ String expectedFullPath = buildExpectedPath(servletPath, _hierarchy);
+ String expectedParentPath = buildExpectedPath(servletPath, _hierarchy.subList(0, _hierarchy.size() - 1));
+
+ throw new IllegalArgumentException(String.format("Invalid POST path '%s%s'. Expected: '%s/<operation name>'"
+ + " or '%s'",
+ servletPath, pathInfo,
+ expectedFullPath, expectedParentPath));
+ }
+ }
+
+ private String buildExpectedPath(final String servletPath, final List<Class<? extends ConfiguredObject>> hierarchy)
+ {
+ StringBuilder expectedPath = new StringBuilder(servletPath);
+ for (Class<? extends ConfiguredObject> part : hierarchy)
+ {
+ expectedPath.append("/<");
+ expectedPath.append(part.getSimpleName().toLowerCase());
+ expectedPath.append(" name>");
+ }
+ return expectedPath.toString();
+ }
+}
Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java?rev=1748386&r1=1748385&r2=1748386&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java Tue Jun 14 10:57:27 2016
@@ -98,7 +98,9 @@ public class RestServlet extends Abstrac
private final ConfiguredObjectToMapConverter _objectConverter = new ConfiguredObjectToMapConverter();
private final boolean _hierarchyInitializationRequired;
+ private volatile RequestInfoParser _requestInfoParser;
+ @SuppressWarnings("unused")
public RestServlet()
{
super();
@@ -120,6 +122,7 @@ public class RestServlet extends Abstrac
{
doInitialization();
}
+ _requestInfoParser = new RequestInfoParser(_hierarchy);
Handler.register();
}
@@ -163,21 +166,9 @@ public class RestServlet extends Abstrac
}
}
- protected Collection<ConfiguredObject<?>> getObjects(HttpServletRequest request)
+ private Collection<ConfiguredObject<?>> getObjects(HttpServletRequest request, RequestInfo requestInfo)
{
- String[] pathInfoElements = getPathInfoElements(request);
- List<String> names = new ArrayList<>();
- if(pathInfoElements != null)
- {
- if(pathInfoElements.length > _hierarchy.length)
- {
- throw new IllegalArgumentException("Too many entries in path for REST servlet "
- + getServletName() + ". Expected hierarchy length: " + _hierarchy.length
- + "; Request hierarchy length: " + pathInfoElements.length
- + "; Path Elements: " + Arrays.toString(pathInfoElements));
- }
- names.addAll(Arrays.asList(pathInfoElements));
- }
+ List<String> names = requestInfo.getModelParts();
Collection<ConfiguredObject<?>> parents = new ArrayList<>();
parents.add(getBroker());
@@ -352,13 +343,15 @@ public class RestServlet extends Abstrac
@Override
protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
+ RequestInfo requestInfo = _requestInfoParser.parse(request);
+ switch(requestInfo.getType())
{
- String[] pathInfoElements = getPathInfoElements(request);
- if (pathInfoElements != null && pathInfoElements.length == _hierarchy.length + 1)
+ case OPERATION:
{
- doOperation(request, response);
+ doOperation(requestInfo, request, response);
+ break;
}
- else
+ case MODEL_OBJECT:
{
// TODO - sort special params, everything else should act as a filter
String attachmentFilename = request.getParameter(CONTENT_DISPOSITION_ATTACHMENT_FILENAME_PARAM);
@@ -369,9 +362,9 @@ public class RestServlet extends Abstrac
setContentDispositionHeaderIfNecessary(response, attachmentFilename);
}
- Collection<ConfiguredObject<?>> allObjects = getObjects(request);
+ Collection<ConfiguredObject<?>> allObjects = getObjects(request, requestInfo);
- if (allObjects == null || allObjects.isEmpty() && isSingleObjectRequest(request))
+ if (allObjects == null || allObjects.isEmpty() && isSingleObjectRequest(requestInfo))
{
sendJsonErrorResponse(request, response, HttpServletResponse.SC_NOT_FOUND, "Not Found");
return;
@@ -474,20 +467,25 @@ public class RestServlet extends Abstrac
boolean sendCachingHeaders = attachmentFilename == null;
sendJsonResponse(extractInitialConfig && output.size() == 1 ? output.get(0) : output,
- request,
- response,
- HttpServletResponse.SC_OK,
- sendCachingHeaders);
+ request,
+ response,
+ HttpServletResponse.SC_OK,
+ sendCachingHeaders);
+ break;
+ }
+ default:
+ {
+ throw new IllegalStateException(String.format("Unexpected request type '%s' for path '%s'", requestInfo.getType(), request.getPathInfo()));
}
}
}
- private boolean isSingleObjectRequest(HttpServletRequest request)
+ private boolean isSingleObjectRequest(final RequestInfo requestInfo)
{
if (_hierarchy.length > 0)
{
- String[] pathInfoElements = getPathInfoElements(request);
- return pathInfoElements != null && pathInfoElements.length == _hierarchy.length;
+ List<String> pathInfoElements = requestInfo.getModelParts();
+ return pathInfoElements.size() == _hierarchy.length;
}
return false;
@@ -539,14 +537,13 @@ public class RestServlet extends Abstrac
{
response.setContentType("application/json");
- List<String> names = getParentNamesFromServletPath(request);
- boolean isFullObjectURL = names.size() == _hierarchy.length;
- boolean isPostToFullURL = isFullObjectURL && "POST".equalsIgnoreCase(request.getMethod());
- final String[] pathInfoElements = getPathInfoElements(request);
- boolean isOperation = pathInfoElements != null && pathInfoElements.length == _hierarchy.length + 1 && isPostToFullURL;
+ RequestInfo requestInfo = _requestInfoParser.parse(request);
+ switch(requestInfo.getType())
{
- if(!isOperation)
+ case MODEL_OBJECT:
{
+ List<String> names = requestInfo.getModelParts();
+ boolean isFullObjectURL = names.size() == _hierarchy.length;
Map<String, Object> providedObject = getRequestProvidedObject(request);
if (names.isEmpty() && _hierarchy.length == 0)
{
@@ -578,7 +575,7 @@ public class RestServlet extends Abstrac
response.setStatus(HttpServletResponse.SC_OK);
return;
}
- else if (isPostToFullURL)
+ else if ("POST".equalsIgnoreCase(request.getMethod()))
{
sendJsonErrorResponse(request, response, HttpServletResponse.SC_NOT_FOUND, "Object with "
+ (providedObject.containsKey(
@@ -596,20 +593,25 @@ public class RestServlet extends Abstrac
}
response.setHeader("Location", requestURL.toString());
response.setStatus(HttpServletResponse.SC_CREATED);
+ break;
}
- else
+ case OPERATION:
+ {
+ doOperation(requestInfo, request, response);
+ break;
+ }
+ default:
{
- doOperation(request, response);
+ throw new IllegalStateException(String.format("Unexpected request type '%s' for path '%s'", requestInfo.getType(), request.getPathInfo()));
}
}
}
- private void doOperation(final HttpServletRequest request,
+ private void doOperation(final RequestInfo requestInfo, final HttpServletRequest request,
final HttpServletResponse response) throws IOException, ServletException
{
ConfiguredObject<?> subject;
- final List<String> names = getParentNamesFromServletPath(request);
- final String[] pathInfoElements = getPathInfoElements(request);
+ final List<String> names = requestInfo.getModelParts();
if (names.isEmpty() && _hierarchy.length == 0)
{
@@ -636,12 +638,12 @@ public class RestServlet extends Abstrac
HttpServletResponse.SC_NOT_FOUND,
getConfiguredClass().getSimpleName()
+ " '"
- + pathInfoElements[pathInfoElements.length - 2]
+ + names.get(names.size() - 1)
+ "' not found.");
return;
}
}
- String operationName = pathInfoElements[pathInfoElements.length - 1];
+ String operationName = requestInfo.getOperationName();
final Map<String, ConfiguredObjectOperation<?>> availableOperations =
getBroker().getModel().getTypeRegistry().getOperations(subject.getClass());
ConfiguredObjectOperation operation = availableOperations.get(operationName);
@@ -865,40 +867,6 @@ public class RestServlet extends Abstrac
return parents;
}
- private List<String> getParentNamesFromServletPath(HttpServletRequest request)
- {
- List<String> names = new ArrayList<>();
- String[] pathInfoElements = getPathInfoElements(request);
- if (pathInfoElements != null)
- {
- if (!(pathInfoElements.length == _hierarchy.length ||
- (_hierarchy.length > 0 && pathInfoElements.length == _hierarchy.length - 1)))
- {
- if(pathInfoElements.length == _hierarchy.length + 1)
- {
- names.addAll(Arrays.asList(pathInfoElements).subList(0,pathInfoElements.length-1));
- }
- else
- {
- throw new IllegalArgumentException(
- "Either parent path or full object path must be specified on object creation."
- + " Full object path must be specified on object update. "
- + "Found "
- + names
- + " of size "
- + names.size()
- + " expecting "
- + _hierarchy.length);
- }
- }
- else
- {
- names.addAll(Arrays.asList(pathInfoElements));
- }
- }
- return names;
- }
-
private Map<String, Object> getRequestProvidedObject(HttpServletRequest request) throws IOException, ServletException
{
Map<String, Object> providedObject;
@@ -1044,22 +1012,22 @@ public class RestServlet extends Abstrac
@Override
protected void doDeleteWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
- {
- Collection<ConfiguredObject<?>> allObjects = getObjects(request);
- if(allObjects != null)
- {
- for (ConfiguredObject o : allObjects)
- {
- o.delete();
- }
+ RequestInfo requestInfo = _requestInfoParser.parse(request);
- sendCachingHeadersOnResponse(response);
- response.setStatus(HttpServletResponse.SC_OK);
- }
- else
+ Collection<ConfiguredObject<?>> allObjects = getObjects(request, requestInfo);
+ if(allObjects != null)
+ {
+ for (ConfiguredObject o : allObjects)
{
- sendJsonErrorResponse(request, response, HttpServletResponse.SC_NOT_FOUND, "Not Found");
+ o.delete();
}
+
+ sendCachingHeadersOnResponse(response);
+ response.setStatus(HttpServletResponse.SC_OK);
+ }
+ else
+ {
+ sendJsonErrorResponse(request, response, HttpServletResponse.SC_NOT_FOUND, "Not Found");
}
}
Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/UserPreferencesServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/UserPreferencesServlet.java?rev=1748386&r1=1748385&r2=1748386&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/UserPreferencesServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/UserPreferencesServlet.java Tue Jun 14 10:57:27 2016
@@ -38,6 +38,7 @@ import javax.servlet.http.HttpServletRes
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.qpid.server.management.plugin.HttpManagementUtil;
import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.PreferencesProvider;
@@ -52,14 +53,15 @@ public class UserPreferencesServlet exte
protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException,
ServletException
{
- String[] pathElements = getPathInfoElements(request);
- if (pathElements != null && pathElements.length > 1)
+ List<String> pathElements =
+ HttpManagementUtil.getPathInfoElements(request.getServletPath(), request.getPathInfo());
+ if (pathElements.size() > 1)
{
- getUserPreferences(pathElements[0], pathElements[1], request, response);
+ getUserPreferences(pathElements.get(0), pathElements.get(1), request, response);
}
else
{
- getUserList(pathElements, request, response);
+ getUserList(pathElements.toArray(new String[pathElements.size()]), request, response);
}
}
Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostQueryServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostQueryServlet.java?rev=1748386&r1=1748385&r2=1748386&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostQueryServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostQueryServlet.java Tue Jun 14 10:57:27 2016
@@ -41,12 +41,16 @@ public class VirtualHostQueryServlet ext
@Override
protected VirtualHost<?> getParent(final HttpServletRequest request)
{
- final String[] path = getPathInfoElements(request);
+ final List<String>
+ path = HttpManagementUtil.getPathInfoElements(request.getServletPath(), request.getPathInfo());
final Broker<?> broker = HttpManagementUtil.getBroker(request.getServletContext());
- VirtualHostNode<?> vhn = broker.getChildByName(VirtualHostNode.class, path[0]);
- if(vhn != null)
+ if (path.size() == 3)
{
- return vhn.getChildByName(VirtualHost.class, path[1]);
+ VirtualHostNode<?> vhn = broker.getChildByName(VirtualHostNode.class, path.get(0));
+ if (vhn != null)
+ {
+ return vhn.getChildByName(VirtualHost.class, path.get(1));
+ }
}
return null;
}
@@ -80,10 +84,11 @@ public class VirtualHostQueryServlet ext
protected String getRequestedCategory(final HttpServletRequest request)
{
- String[] pathInfoElements = getPathInfoElements(request);
- if(pathInfoElements.length == 3)
+ List<String> pathInfoElements =
+ HttpManagementUtil.getPathInfoElements(request.getServletPath(), request.getPathInfo());
+ if (pathInfoElements.size() == 3)
{
- return pathInfoElements[2];
+ return pathInfoElements.get(2);
}
return null;
}
Added: qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/RequestInfoParserTest.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/RequestInfoParserTest.java?rev=1748386&view=auto
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/RequestInfoParserTest.java (added)
+++ qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/RequestInfoParserTest.java Tue Jun 14 10:57:27 2016
@@ -0,0 +1,325 @@
+/*
+ * 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.qpid.server.management.plugin.servlet.rest;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Collections;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.model.VirtualHostNode;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class RequestInfoParserTest extends QpidTestCase
+{
+ private HttpServletRequest _request = mock(HttpServletRequest.class);
+
+ public void testGetNoHierarchy()
+ {
+ RequestInfoParser parser = new RequestInfoParser();
+
+ configureRequest("GET", "servletPath", null);
+
+ RequestInfo info = parser.parse(_request);
+
+ assertEquals("Unexpected request type", RequestInfo.RequestType.MODEL_OBJECT, info.getType());
+ assertEquals("Unexpected model parts", Collections.emptyList(), info.getModelParts());
+ }
+
+ public void testGetWithHierarchy()
+ {
+ RequestInfoParser parser = new RequestInfoParser(VirtualHostNode.class, VirtualHost.class);
+
+ final String vhnName = "testVHNName";
+ final String vhName = "testVHName";
+ final String pathInfo = "/" + vhnName + "/" + vhName;
+
+ configureRequest("GET", "servletPath", pathInfo);
+
+ RequestInfo info = parser.parse(_request);
+
+ assertEquals("Unexpected request type", RequestInfo.RequestType.MODEL_OBJECT, info.getType());
+ assertEquals("Unexpected model parts", Arrays.asList(vhnName, vhName), info.getModelParts());
+ }
+
+ public void testGetParent()
+ {
+ RequestInfoParser parser = new RequestInfoParser(VirtualHostNode.class, VirtualHost.class);
+ final String vhnName = "testVHNName";
+ configureRequest("GET", "servletPath", "/" + vhnName);
+
+ RequestInfo info = parser.parse(_request);
+
+ assertEquals("Unexpected request type", RequestInfo.RequestType.MODEL_OBJECT, info.getType());
+ assertEquals("Unexpected model parts", Arrays.asList(vhnName), info.getModelParts());
+ }
+
+ public void testGetTooManyParts()
+ {
+ RequestInfoParser parser = new RequestInfoParser(VirtualHostNode.class);
+
+ try
+ {
+ configureRequest("GET", "servletPath", "/testVHNName/testOp/invalidAdditionalPart");
+
+ parser.parse(_request);
+ fail("Expected exception");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // pass
+ }
+ }
+
+ public void testGetOperation()
+ {
+ doOperationTest("GET");
+ }
+
+ public void testPostToParent()
+ {
+ RequestInfoParser parser = new RequestInfoParser(VirtualHostNode.class, VirtualHost.class);
+
+ final String vhnName = "testVHNName";
+ final String pathInfo = "/" + vhnName;
+
+ configureRequest("POST", "servletPath", pathInfo);
+
+ RequestInfo info = parser.parse(_request);
+
+ assertEquals("Unexpected request type", RequestInfo.RequestType.MODEL_OBJECT, info.getType());
+ assertEquals("Unexpected model parts", Arrays.asList(vhnName), info.getModelParts());
+ }
+
+
+ public void testPostToObject()
+ {
+ RequestInfoParser parser = new RequestInfoParser(VirtualHostNode.class, VirtualHost.class);
+
+ final String vhnName = "testVHNName";
+ final String vhName = "testVHName";
+ final String pathInfo = "/" + vhnName + "/" + vhName;
+
+ configureRequest("POST", "servletPath", pathInfo);
+
+ RequestInfo info = parser.parse(_request);
+
+ assertEquals("Unexpected request type", RequestInfo.RequestType.MODEL_OBJECT, info.getType());
+ assertEquals("Unexpected model parts", Arrays.asList(vhnName, vhName), info.getModelParts());
+ }
+
+ public void testPostTooFewParts()
+ {
+ RequestInfoParser parser = new RequestInfoParser(VirtualHostNode.class, VirtualHost.class, Queue.class);
+
+ try
+ {
+ configureRequest("POST", "servletPath", "/testVHNName");
+
+ parser.parse(_request);
+ fail("Expected exception");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // pass
+ }
+ }
+
+ public void testPostTooManyParts()
+ {
+ RequestInfoParser parser = new RequestInfoParser(VirtualHostNode.class, VirtualHost.class, Queue.class);
+
+ try
+ {
+ configureRequest("POST", "servletPath", "/testVHNName/testVNName/testQueue/testOp/testUnknown");
+
+ parser.parse(_request);
+ fail("Expected exception");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // pass
+ }
+ }
+
+ public void testPostOperation()
+ {
+ doOperationTest("POST");
+ }
+
+ public void testPutToObject()
+ {
+ RequestInfoParser parser = new RequestInfoParser(VirtualHostNode.class, VirtualHost.class);
+
+ final String vhnName = "testVHNName";
+ final String vhName = "testVHName";
+ final String pathInfo = "/" + vhnName + "/" + vhName;
+
+ configureRequest("PUT", "servletPath", pathInfo);
+
+ RequestInfo info = parser.parse(_request);
+
+ assertEquals("Unexpected request type", RequestInfo.RequestType.MODEL_OBJECT, info.getType());
+ assertEquals("Unexpected model parts", Arrays.asList(vhnName, vhName), info.getModelParts());
+ }
+
+ public void testPutToParent()
+ {
+ RequestInfoParser parser = new RequestInfoParser(VirtualHostNode.class, VirtualHost.class, Queue.class);
+
+ final String vhnName = "testVHNName";
+ final String vhName = "testVHName";
+ configureRequest("PUT", "servletPath", "/" + vhnName + "/" + vhName);
+
+ RequestInfo info = parser.parse(_request);
+
+ assertEquals("Unexpected request type", RequestInfo.RequestType.MODEL_OBJECT, info.getType());
+ assertEquals("Unexpected model parts", Arrays.asList(vhnName, vhName), info.getModelParts());
+ }
+
+ public void testPutTooFewParts()
+ {
+ RequestInfoParser parser = new RequestInfoParser(VirtualHostNode.class, VirtualHost.class, Queue.class);
+
+ try
+ {
+ configureRequest("PUT", "servletPath", "/testVHNName");
+
+ parser.parse(_request);
+ fail("Expected exception");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // pass
+ }
+ }
+
+ public void testPutTooManyParts()
+ {
+ RequestInfoParser parser = new RequestInfoParser(VirtualHostNode.class, VirtualHost.class, Queue.class);
+
+ try
+ {
+ configureRequest("PUT", "servletPath", "/testVHNName/testVNName/testQueue/testUnknown");
+
+ parser.parse(_request);
+ fail("Expected exception");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // pass
+ }
+ }
+
+ public void testDeleteObject()
+ {
+ RequestInfoParser parser = new RequestInfoParser(VirtualHostNode.class, VirtualHost.class);
+
+ final String vhnName = "testVHNName";
+ final String vhName = "testVHName";
+ final String pathInfo = "/" + vhnName + "/" + vhName;
+
+ configureRequest("DELETE", "servletPath", pathInfo);
+
+ RequestInfo info = parser.parse(_request);
+
+ assertEquals("Unexpected request type", RequestInfo.RequestType.MODEL_OBJECT, info.getType());
+ assertEquals("Unexpected model parts", Arrays.asList(vhnName, vhName), info.getModelParts());
+ }
+
+
+ public void testDeleteParent()
+ {
+ RequestInfoParser parser = new RequestInfoParser(VirtualHostNode.class, VirtualHost.class, Queue.class);
+
+ final String vhnName = "testVHNName";
+ final String vhName = "testVHName";
+ configureRequest("DELETE", "servletPath", "/" + vhnName + "/" + vhName);
+
+ RequestInfo info = parser.parse(_request);
+
+ assertEquals("Unexpected request type", RequestInfo.RequestType.MODEL_OBJECT, info.getType());
+ assertEquals("Unexpected model parts", Arrays.asList(vhnName, vhName), info.getModelParts());
+ }
+
+ public void testDeleteTooManyParts()
+ {
+ RequestInfoParser parser = new RequestInfoParser(VirtualHostNode.class, VirtualHost.class, Queue.class);
+
+ try
+ {
+ configureRequest("DELETE", "servletPath", "/testVHNName/testVNName/testQueue/testUnknown");
+
+ parser.parse(_request);
+ fail("Expected exception");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // pass
+ }
+ }
+
+ public void testParseWithURLEncodedName() throws UnsupportedEncodingException
+ {
+ RequestInfoParser parser = new RequestInfoParser(VirtualHostNode.class);
+ final String vhnName = "vhnName/With/slashes?and&other/stuff";
+ final String encodedVHNName = URLEncoder.encode(vhnName, StandardCharsets.UTF_8.name());
+
+ configureRequest("GET", "servletPath", "/" + encodedVHNName);
+
+ RequestInfo info = parser.parse(_request);
+
+ assertEquals("Unexpected request type", RequestInfo.RequestType.MODEL_OBJECT, info.getType());
+ assertEquals("Unexpected model parts", Arrays.asList(vhnName), info.getModelParts());
+ }
+
+ private void configureRequest(final String method,
+ final String servletPath,
+ final String pathInfo)
+ {
+ when(_request.getServletPath()).thenReturn(servletPath);
+ when(_request.getPathInfo()).thenReturn(pathInfo);
+ when(_request.getMethod()).thenReturn(method);
+ }
+
+ private void doOperationTest(final String method)
+ {
+ RequestInfoParser parser = new RequestInfoParser(VirtualHostNode.class);
+ final String vhnName = "testVHNName";
+ final String operationName = "testOperation";
+ final String pathInfo = "/" + vhnName + "/" + operationName;
+
+ configureRequest(method, "servletPath", pathInfo);
+
+ RequestInfo info = parser.parse(_request);
+
+ assertEquals("Unexpected request type", RequestInfo.RequestType.OPERATION, info.getType());
+ assertEquals("Unexpected model parts", Arrays.asList(vhnName), info.getModelParts());
+ assertEquals("Unexpected operation name", operationName, info.getOperationName());
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org