org.apache.sling.api.servlets.SlingAllMethodsServlet Maven / Gradle / Ivy
/*
* 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.api.servlets;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.servlet.ServletException;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
/**
* Helper base class for data modifying Servlets used in Sling. This class
* extends the {@link SlingSafeMethodsServlet} by support for the POST,
* PUT and DELETE methods.
*
* Implementors note: The methods in this class are all declared to throw the
* exceptions according to the intentions of the Servlet API rather than
* throwing their Sling RuntimeException counter parts. This is done to easy the
* integration with traditional servlets.
*
* @see SlingSafeMethodsServlet for more information on supporting more HTTP
* methods
*/
public class SlingAllMethodsServlet extends SlingSafeMethodsServlet {
private static final long serialVersionUID = -7960975481323952419L;
/**
* Called by the
* {@link #mayService(SlingHttpServletRequest, SlingHttpServletResponse)} method to
* handle an HTTP POST request.
*
* This default implementation reports back to the client that the method is
* not supported.
*
* Implementations of this class should overwrite this method with their
* implementation for the HTTP POST method support.
*
* @param request The HTTP request
* @param response The HTTP response
* @throws ServletException Not thrown by this implementation.
* @throws IOException If the error status cannot be reported back to the
* client.
*/
@SuppressWarnings("unused")
protected void doPost(@Nonnull SlingHttpServletRequest request,
@Nonnull SlingHttpServletResponse response) throws ServletException,
IOException {
handleMethodNotImplemented(request, response);
}
/**
* Called by the
* {@link #mayService(SlingHttpServletRequest, SlingHttpServletResponse)} method to
* handle an HTTP PUT request.
*
* This default implementation reports back to the client that the method is
* not supported.
*
* Implementations of this class should overwrite this method with their
* implementation for the HTTP PUT method support.
*
* @param request The HTTP request
* @param response The HTTP response
* @throws ServletException Not thrown by this implementation.
* @throws IOException If the error status cannot be reported back to the
* client.
*/
@SuppressWarnings("unused")
protected void doPut(@Nonnull SlingHttpServletRequest request,
@Nonnull SlingHttpServletResponse response) throws ServletException,
IOException {
handleMethodNotImplemented(request, response);
}
/**
* Called by the
* {@link #mayService(SlingHttpServletRequest, SlingHttpServletResponse)} method to
* handle an HTTP DELETE request.
*
* This default implementation reports back to the client that the method is
* not supported.
*
* Implementations of this class should overwrite this method with their
* implementation for the HTTP DELETE method support.
*
* @param request The HTTP request
* @param response The HTTP response
* @throws ServletException Not thrown by this implementation.
* @throws IOException If the error status cannot be reported back to the
* client.
*/
@SuppressWarnings("unused")
protected void doDelete(@Nonnull SlingHttpServletRequest request,
@Nonnull SlingHttpServletResponse response) throws ServletException,
IOException {
handleMethodNotImplemented(request, response);
}
/**
* Tries to handle the request by calling a Java method implemented for the
* respective HTTP request method.
*
* This implementation first calls the base class implementation and only if
* the base class cannot dispatch will try to dispatch the supported methods
* POST, PUT and DELETE and returns
* true
if any of these methods is requested. Otherwise
* false
is just returned.
*
* @param request The HTTP request
* @param response The HTTP response
* @return true
if the requested method (request.getMethod()
)
* is known. Otherwise false
is returned.
* @throws ServletException Forwarded from any of the dispatched methods
* @throws IOException Forwarded from any of the dispatched methods
*/
protected boolean mayService(@Nonnull SlingHttpServletRequest request,
@Nonnull SlingHttpServletResponse response) throws ServletException,
IOException {
// assume the method is known for now
if (super.mayService(request, response)) {
return true;
}
// assume the method is known for now
boolean methodKnown = true;
String method = request.getMethod();
if (HttpConstants.METHOD_POST.equals(method)) {
doPost(request, response);
} else if (HttpConstants.METHOD_PUT.equals(method)) {
doPut(request, response);
} else if (HttpConstants.METHOD_DELETE.equals(method)) {
doDelete(request, response);
} else {
// actually we do not know the method
methodKnown = false;
}
// return whether we actually knew the request method or not
return methodKnown;
}
/**
* Helper method called by
* {@link #doOptions(SlingHttpServletRequest, SlingHttpServletResponse)} to calculate
* the value of the Allow header sent as the response to the HTTP
* OPTIONS request.
*
* This implementation overwrites the base class implementation adding
* support for the POST, PUT and DELETE
* methods in addition to the methods returned by the base class
* implementation.
*
* @param declaredMethods The public and protected methods declared in the
* extension of this class.
* @return A StringBuffer
containing the list of HTTP methods
* supported.
*/
protected @Nonnull StringBuffer getAllowedRequestMethods(
@Nonnull Map declaredMethods) {
StringBuffer allowBuf = super.getAllowedRequestMethods(declaredMethods);
// add more method names depending on the methods found
String className = SlingAllMethodsServlet.class.getName();
if (isMethodValid(declaredMethods.get("doPost"), className)) {
allowBuf.append(", ").append(HttpConstants.METHOD_POST);
} else if (isMethodValid(declaredMethods.get("doPut"), className)) {
allowBuf.append(", ").append(HttpConstants.METHOD_PUT);
} else if (isMethodValid(declaredMethods.get("doDelete"), className)) {
allowBuf.append(", ").append(HttpConstants.METHOD_DELETE);
}
return allowBuf;
}
/**
* Returns true
if method
is not
* null
and the method is not defined in the class named by
* className
.
*
* This method may be used to make sure a method is actually overwritten and
* not just the default implementation.
*
* @param method The Method to check
* @param className The name of class assumed to contained the initial
* declaration of the method.
* @return true
if method
is not
* null
and the methods declaring class is not the
* given class.
*/
protected boolean isMethodValid(Method method, String className) {
return method != null && !method.getClass().getName().equals(className);
}
}