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

org.restlet.Finder 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.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.logging.Level;

import org.restlet.data.Method;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.data.Status;

/**
 * Restlet that can find the target handler that will effectively handle the
 * call. Based on a given Handler subclass, it is also capable of instantiating
 * the handler with the call's context, request and response without requiring
 * the usage of a Finder subclass. It will use either the constructor with three
 * arguments: context, request, response; or it will invoke the default
 * constructor then invoke the init() method with the same arguments.
*
* Once the target handler has been found, the call is automatically dispatched * to the appropriate handle*() method (where the '*' character corresponds to * the method name) if the corresponding allow*() method returns true.
*
* For example, if you want to support a MOVE method for a WebDAV server, you * just have to add a handleMove() method in your subclass of Handler and it * will be automatically be used by the Finder instance at runtime.
*
* If no matching handle*() method is found, then a * Status.CLIENT_ERROR_METHOD_NOT_ALLOWED is returned.
*
* Concurrency note: instances of this class or its subclasses can be invoked by * several threads at the same time and therefore must be thread-safe. You * should be especially careful when storing state in member variables. * * @see Tutorial: * Reaching target Resources * @author Jerome Louvel */ public class Finder extends Restlet { /** Target handler class. */ private volatile Class targetClass; /** * Constructor. */ public Finder() { this(null); } /** * Constructor. * * @param context * The context. */ public Finder(Context context) { this(context, null); } /** * Constructor. * * @param context * The context. * @param targetClass * The target handler class. */ public Finder(Context context, Class targetClass) { super(context); this.targetClass = targetClass; } /** * Indicates if a method is allowed on a target handler. * * @param method * The method to test. * @param target * The target handler. * @return True if a method is allowed on a target handler. */ private boolean allow(Method method, Handler target) { boolean result = false; if (target != null) { if (method.equals(Method.GET)) { result = target.allowGet(); } else if (method.equals(Method.POST)) { result = target.allowPost(); } else if (method.equals(Method.PUT)) { result = target.allowPut(); } else if (method.equals(Method.DELETE)) { result = target.allowDelete(); } else if (method.equals(Method.HEAD)) { result = target.allowHead(); } else if (method.equals(Method.OPTIONS)) { result = target.allowOptions(); } else { // Dynamically introspect the target handler to detect a // matching "allow" method. final java.lang.reflect.Method allowMethod = getAllowMethod( method, target); if (allowMethod != null) { result = (Boolean) invoke(target, allowMethod); } } } return result; } /** * Creates a new instance of the handler class designated by the * "targetClass" property. The default behavior is to invoke the * {@link #createTarget(Class, Request, Response)} with the "targetClass" * property as a parameter. * * @param request * The request to handle. * @param response * The response to update. * @return The created handler or null. * @deprecated Use the {@link #createTarget(Request, Response)} instead. */ @Deprecated public Handler createResource(Request request, Response response) { return createTarget(getTargetClass(), request, response); } /** * Creates a new instance of a given handler class. Note that Error and * RuntimeException thrown by Handler constructors are rethrown by this * method. Other exception are caught and logged. * * @param request * The request to handle. * @param response * The response to update. * @return The created handler or null. */ public Handler createTarget(Class targetClass, Request request, Response response) { Handler result = null; if (targetClass != null) { try { Constructor constructor; try { // Invoke the constructor with Context, Request and Response // parameters constructor = targetClass.getConstructor(Context.class, Request.class, Response.class); result = (Handler) constructor.newInstance(getContext(), request, response); } catch (NoSuchMethodException nsme) { // Invoke the default constructor then the init(Context, // Request, Response) method. constructor = targetClass.getConstructor(); if (constructor != null) { result = (Handler) constructor.newInstance(); result.init(getContext(), request, response); } } } catch (InvocationTargetException e) { if (e.getCause() instanceof Error) { throw (Error) e.getCause(); } else if (e.getCause() instanceof RuntimeException) { throw (RuntimeException) e.getCause(); } else { getLogger() .log( Level.WARNING, "Exception while instantiating the target handler.", e); } } catch (Exception e) { getLogger().log(Level.WARNING, "Exception while instantiating the target handler.", e); } } return result; } /** * Creates a new instance of the handler class designated by the * "targetClass" property. The default behavior is to invoke the * {@link #createTarget(Class, Request, Response)} with the "targetClass" * property as a parameter. * * @param request * The request to handle. * @param response * The response to update. * @return The created handler or null. */ protected Handler createTarget(Request request, Response response) { return createTarget(getTargetClass(), request, response); } /** * Finds the target Handler if available. The default behavior is to invoke * the {@link #createTarget(Request, Response)} method. * * @param request * The request to handle. * @param response * The response to update. * @return The target handler if available or null. */ protected Handler findTarget(Request request, Response response) { return createTarget(request, response); } /** * Returns the allow method matching the given method name. * * @param method * The method to match. * @param target * The target handler. * @return The allow method matching the given method name. */ private java.lang.reflect.Method getAllowMethod(Method method, Handler target) { return getMethod("allow", method, target); } /** * Returns the handle method matching the given method name. * * @param method * The method to match. * @return The handle method matching the given method name. */ private java.lang.reflect.Method getHandleMethod(Handler target, Method method) { return getMethod("handle", method, target); } /** * Returns the method matching the given prefix and method name. * * @param prefix * The method prefix to match (ex: "allow" or "handle"). * @param method * The method to match. * @return The method matching the given prefix and method name. */ private java.lang.reflect.Method getMethod(String prefix, Method method, Object target, Class... classes) { java.lang.reflect.Method result = null; final StringBuilder sb = new StringBuilder(); final String methodName = method.getName().toLowerCase(); if ((methodName != null) && (methodName.length() > 0)) { sb.append(prefix); sb.append(Character.toUpperCase(methodName.charAt(0))); sb.append(methodName.substring(1)); } try { result = target.getClass().getMethod(sb.toString(), classes); } catch (SecurityException e) { getLogger().log( Level.WARNING, "Couldn't access the " + prefix + " method for \"" + method + "\"", e); } catch (NoSuchMethodException e) { getLogger().log( Level.INFO, "Couldn't find the " + prefix + " method for \"" + method + "\"", e); } return result; } /** * Returns the target Handler class. * * @return the target Handler class. */ public Class getTargetClass() { return this.targetClass; } /** * Handles a call. * * @param request * The request to handle. * @param response * The response to update. */ @Override public void handle(Request request, Response response) { super.handle(request, response); if (isStarted()) { final Handler target = findTarget(request, response); if (!response.getStatus().equals(Status.SUCCESS_OK)) { // Probably during the instantiation of the target handler, or // earlier the status was changed from the default one. Don't go // further. } else if (target == null) { // If the currrent status is a success but we couldn't find the // target handler for the request's resource URI, then we set // the response status to 404 (Not Found). response.setStatus(Status.CLIENT_ERROR_NOT_FOUND); } else { final Method method = request.getMethod(); if (method == null) { response.setStatus(Status.CLIENT_ERROR_BAD_REQUEST, "No method specified"); } else { if (!allow(method, target)) { response .setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED); target.updateAllowedMethods(); } else { if (method.equals(Method.GET)) { target.handleGet(); } else if (method.equals(Method.HEAD)) { target.handleHead(); } else if (method.equals(Method.POST)) { target.handlePost(); } else if (method.equals(Method.PUT)) { target.handlePut(); } else if (method.equals(Method.DELETE)) { target.handleDelete(); } else if (method.equals(Method.OPTIONS)) { target.handleOptions(); } else { final java.lang.reflect.Method handleMethod = getHandleMethod( target, method); if (handleMethod != null) { invoke(target, handleMethod); } else { response .setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED); } } } } } } } /** * Invokes a method with the given arguments. * * @param target * The target object. * @param method * The method to invoke. * @param args * The arguments to pass. * @return Invocation result. */ private Object invoke(Object target, java.lang.reflect.Method method, Object... args) { Object result = null; if (method != null) { try { result = method.invoke(target, args); } catch (Exception e) { getLogger().log( Level.WARNING, "Couldn't invoke the handle method for \"" + method + "\"", e); } } return result; } /** * Sets the target Handler class. * * @param targetClass * The target Handler class. */ public void setTargetClass(Class targetClass) { this.targetClass = targetClass; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy