All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.restlet.Handler Maven / Gradle / Ivy

Go to download

This OSGi bundle wraps org.restlet, and com.noelios.restlet ${pkgVersion} jar files.

The newest version!
/**
 * Copyright 2005-2008 Noelios Technologies.
 * 
 * The contents of this file are subject to the terms of the following open
 * source licenses: LGPL 3.0 or LGPL 2.1 or CDDL 1.0 (the "Licenses"). You can
 * select the license that you prefer but you may not use this file except in
 * compliance with one of these Licenses.
 * 
 * You can obtain a copy of the LGPL 3.0 license at
 * http://www.gnu.org/licenses/lgpl-3.0.html
 * 
 * You can obtain a copy of the LGPL 2.1 license at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 * 
 * You can obtain a copy of the CDDL 1.0 license at
 * http://www.sun.com/cddl/cddl.html
 * 
 * See the Licenses for the specific language governing permissions and
 * limitations under the Licenses.
 * 
 * Alternatively, you can obtain a royaltee free commercial license with less
 * limitations, transferable or non-transferable, directly at
 * http://www.noelios.com/products/restlet-engine
 * 
 * Restlet is a registered trademark of Noelios Technologies.
 */

package org.restlet;

import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.restlet.data.Form;
import org.restlet.data.Method;
import org.restlet.data.Reference;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.data.Status;
import org.restlet.util.Template;

/**
 * Final handler of calls typically created by Finders. Handler instances allow
 * the processing of a call in a thread-safe context. This is different from the
 * Uniform subclasses like Restlet, Filter and Router which can be invoked by
 * multiple threads at the same time. However, as they offer a rather low-level
 * API and its subclass {@link org.restlet.resource.Resource} is often preferred
 * for concrete handlers.
*
* This class exposes a different set of handle*() and allow*() Java methods for * each type of Uniform method supported by your handler. It has a predefined * set for common methods like GET, POST, PUT, DELETE, HEAD and OPTIONS. * Extension methods like MOVE or PATCH are automatically supported using Java * introspection. The actual dispatching of the call to those methods is * dynamically done by the {@link org.restlet.Finder} class.
*
* The HEAD method has a default implementation based on the GET method and the * OPTIONS method automatically updates the list of allowed methods in the * response, as required by the HTTP specification.
*
* Also, you can declare which REST methods are allowed by your Handler by * overiding the matching allow*() method. By default, allowOptions() returns * true, but all other allow*() methods will return false. Therefore, if you * want to accept MOVE method calls, just override allowMove() and return true. * Again, the invoking Finder will be able to detect this method and know * whether or not your Handler should be invoked. It is also used by the * handleOptions() method to return the list of allowed methods.
*
* Concurrency note: typically created by Finders, Handler instances are the * final handlers of requests. Unlike the other processors in the Restlet chain, * a Handler instance is not reused by several calls and is only invoked by one * thread. Therefore, it doesn't have to be thread-safe.
* * @see org.restlet.Finder * @author Jerome Louvel */ public abstract class Handler { /** * Workaround limitation in Java reflection. * * @param method * The method to invoke, potentially in a protected class * @return The equivalent method in a public ancestor class. * @throws NoSuchMethodException * @see Bug * #4071957 */ private static java.lang.reflect.Method getAncestorMethod( java.lang.reflect.Method method) throws NoSuchMethodException { while (!java.lang.reflect.Modifier.isPublic(method.getDeclaringClass() .getModifiers())) { method = method.getDeclaringClass().getSuperclass().getMethod( method.getName(), method.getParameterTypes()); } return method; } /** The parent context. */ private Context context; /** The handled request. */ private Request request; /** The returned response. */ private Response response; /** * Special constructor used by IoC frameworks. Note that the init() method * MUST be invoked right after the creation of the handler in order to keep * a behavior consistent with the normal three arguments constructor. */ public Handler() { } /** * Normal constructor. * * @param context * The parent context. * @param request * The request to handle. * @param response * The response to return. */ public Handler(Context context, Request request, Response response) { this.context = context; this.request = request; this.response = response; } /** * Indicates if DELETE calls are allowed. The default value is false. * * @return True if the method is allowed. */ public boolean allowDelete() { return false; } /** * Indicates if GET calls are allowed. The default value is false. * * @return True if the method is allowed. */ public boolean allowGet() { return false; } /** * Indicates if HEAD calls are allowed. The default behavior is to call * allowGet(). * * @return True if the method is allowed. */ public boolean allowHead() { return allowGet(); } /** * Indicates if OPTIONS calls are allowed. The default value is true. * * @return True if the method is allowed. */ public boolean allowOptions() { return true; } /** * Indicates if POST calls are allowed. The default value is false. * * @return True if the method is allowed. */ public boolean allowPost() { return false; } /** * Indicates if PUT calls are allowed. The default value is false. * * @return True if the method is allowed. */ public boolean allowPut() { return false; } /** * Generates a reference based on a template URI. Note that you can leverage * all the variables defined in the Template class as they will be resolved * using the resource's request and response properties. * * @param uriTemplate * The URI template to use for generation. * @return The generated reference. */ public Reference generateRef(String uriTemplate) { final Template tplt = new Template(uriTemplate); tplt.setLogger(getLogger()); return new Reference(tplt.format(getRequest(), getResponse())); } /** * Returns the set of allowed methods. * * @return The set of allowed methods. */ public Set getAllowedMethods() { final Set result = new HashSet(); updateAllowedMethods(result); return result; } /** * Returns the parent application if it exists, or null. * * @return The parent application if it exists, or null. */ public Application getApplication() { return Application.getCurrent(); } /** * Returns the context. * * @return The context. */ public Context getContext() { return (this.context != null) ? this.context : Context.getCurrent(); } /** * Returns the logger to use. * * @return The logger to use. */ public Logger getLogger() { return (getContext() != null) ? getContext().getLogger() : Context .getCurrentLogger(); } /** * Returns the optional matrix of the request's target resource reference as * a form (series of parameters). * * @return The parsed query. * @see Reference#getMatrixAsForm() */ public Form getMatrix() { return getRequest().getResourceRef().getMatrixAsForm(); } /** * Returns the parsed query of the request's target resource reference as a * form (series of parameters). * * @return The parsed query. * @see Reference#getQueryAsForm() */ public Form getQuery() { return getRequest().getResourceRef().getQueryAsForm(); } /** * Returns the request. * * @return the request. */ public Request getRequest() { return this.request; } /** * Returns the response. * * @return the response. */ public Response getResponse() { return this.response; } /** * Handles a DELETE call. The default behavior, to be overriden by * subclasses, is to set the status to {@link Status#SERVER_ERROR_INTERNAL}. */ public void handleDelete() { getResponse().setStatus(Status.SERVER_ERROR_INTERNAL); } /** * Handles a GET call. The default behavior, to be overriden by subclasses, * is to set the status to {@link Status#SERVER_ERROR_INTERNAL}. */ public void handleGet() { getResponse().setStatus(Status.SERVER_ERROR_INTERNAL); } /** * Handles a HEAD call. The default behavior is to invoke the handleGet() * method. This is the expected behavior of the HTTP 1.1 specification for * example. Note that the server connectors will take care of never sending * back to the client the response entity bodies. */ public void handleHead() { handleGet(); } /** * Handles an OPTIONS call introspecting the target resource (as provided by * the 'findTarget' method). The default implementation is based on the HTTP * specification which says that OPTIONS should return the list of allowed * methods in the Response headers. */ public void handleOptions() { updateAllowedMethods(); getResponse().setStatus(Status.SUCCESS_OK); } /** * Handles a POST call. The default behavior, to be overriden by subclasses, * is to set the status to {@link Status#SERVER_ERROR_INTERNAL}. */ public void handlePost() { getResponse().setStatus(Status.SERVER_ERROR_INTERNAL); } /** * Handles a PUT call. The default behavior, to be overriden by subclasses, * is to set the status to {@link Status#SERVER_ERROR_INTERNAL}. */ public void handlePut() { getResponse().setStatus(Status.SERVER_ERROR_INTERNAL); } /** * Initialize the resource with its context. If you override this method, * make sure that you don't forget to call super.init() first, otherwise * your Resource won't behave properly. * * @param context * The parent context. * @param request * The request to handle. * @param response * The response to return. */ public void init(Context context, Request request, Response response) { this.context = context; this.request = request; this.response = response; } /** * Invokes a method with the given arguments. * * @param method * The method to invoke. * @param args * The arguments to pass. * @return Invocation result. */ private Object invoke(java.lang.reflect.Method method, Object... args) { Object result = null; if (method != null) { try { result = method.invoke(this, args); } catch (Exception e) { getLogger().log( Level.WARNING, "Couldn't invoke the handle method for \"" + method + "\"", e); } } return result; } /** * Sets the parent context. * * @param context * The parent context. */ public void setContext(Context context) { this.context = context; } /** * Sets the request to handle. * * @param request * The request to handle. */ public void setRequest(Request request) { this.request = request; } /** * Sets the response to update. * * @param response * The response to update. */ public void setResponse(Response response) { this.response = response; } /** * Updates the set of allowed methods on the response. */ public void updateAllowedMethods() { updateAllowedMethods(getResponse().getAllowedMethods()); } /** * Updates the set of methods with the ones allowed by this resource * instance. * * @param allowedMethods * The set to update. */ private void updateAllowedMethods(Set allowedMethods) { for (final java.lang.reflect.Method orig_classMethod : getClass() .getMethods()) { java.lang.reflect.Method classMethod; try { classMethod = getAncestorMethod(orig_classMethod); if (classMethod.getName().startsWith("allow") && (classMethod.getParameterTypes().length == 0)) { if ((Boolean) invoke(classMethod)) { final Method allowedMethod = Method.valueOf(classMethod .getName().substring(5)); allowedMethods.add(allowedMethod); } } } catch (NoSuchMethodException e) { getLogger().log(Level.FINE, "Unable to find a public version of this method.", e); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy