/** * Copyright 2005-2014 Restlet * * The contents of this file are subject to the terms of one of the following * open source licenses: Apache 2.0 or LGPL 3.0 or LGPL 2.1 or CDDL 1.0 or EPL * 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 Apache 2.0 license at * http://www.opensource.org/licenses/apache-2.0 * * You can obtain a copy of the LGPL 3.0 license at * http://www.opensource.org/licenses/lgpl-3.0 * * You can obtain a copy of the LGPL 2.1 license at * http://www.opensource.org/licenses/lgpl-2.1 * * You can obtain a copy of the CDDL 1.0 license at * http://www.opensource.org/licenses/cddl1 * * You can obtain a copy of the EPL 1.0 license at * http://www.opensource.org/licenses/eclipse-1.0 * * See the Licenses for the specific language governing permissions and * limitations under the Licenses. * * Alternatively, you can obtain a royalty free commercial license with less * limitations, transferable or non-transferable, directly at * http://www.restlet.com/products/restlet-framework * * Restlet is a registered trademark of Restlet */ package org.restlet.data; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * Method to execute when handling a call. * * @author Jerome Louvel */ public final class Method implements Comparable<Method> { /** Map of registered methods. */ private static final Map<String, Method> _methods = new ConcurrentHashMap<String, Method>(); /** * Pseudo-method use to match all methods. */ public static final Method ALL = new Method("*", "Pseudo-method use to match all methods."); private static final String BASE_HTTP = "http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html"; private static final String BASE_WEBDAV = "http://www.webdav.org/specs/rfc2518.html"; /** * Used with a proxy that can dynamically switch to being a tunnel. * * @see <a * href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.9">HTTP * RFC - 9.9 CONNECT</a> */ public static final Method CONNECT = new Method("CONNECT", "Used with a proxy that can dynamically switch to being a tunnel", BASE_HTTP + "#sec9.9", false, false); /** * Creates a duplicate of the source resource, identified by the * Request-URI, in the destination resource, identified by the URI in the * Destination header. * * @see <a * href="http://www.webdav.org/specs/rfc2518.html#METHOD_COPY">WEBDAV * RFC - 8.8 COPY Method</a> */ public static final Method COPY = new Method( "COPY", "Creates a duplicate of the source resource, identified by the Request-URI, in the destination resource, identified by the URI in the Destination header", BASE_WEBDAV + "#METHOD_COPY", false, true); /** * Requests that the origin server deletes the resource identified by the * request URI. * * @see <a * href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.7">HTTP * RFC - 9.7 DELETE</a> */ public static final Method DELETE = new Method( "DELETE", "Requests that the origin server deletes the resource identified by the request URI", BASE_HTTP + "#sec9.7", false, true); /** * Retrieves whatever information (in the form of an entity) that is * identified by the request URI. * * @see <a * href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.3">HTTP * RFC - 9.3 GET</a> */ public static final Method GET = new Method( "GET", "Retrieves whatever information (in the form of an entity) that is identified by the request URI", BASE_HTTP + "#sec9.3", true, true); /** * Identical to GET except that the server must not return a message body in * the response but only the message header. * * @see <a * href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.4">HTTP * RFC - 9.4 HEAD</a> */ public static final Method HEAD = new Method( "HEAD", "Identical to GET except that the server must not return a message body in the response", BASE_HTTP + "#sec9.4", true, true); /** * Used to take out a lock of any access type on the resource identified by * the request URI. * * @see <a * href="http://www.webdav.org/specs/rfc2518.html#METHOD_LOCK">WEBDAV * RFC - 8.10 LOCK Method</a> */ public static final Method LOCK = new Method("LOCK", "Used to take out a lock of any access type (WebDAV)", BASE_WEBDAV + "#METHOD_LOCK", true, false); /** * MKCOL creates a new collection resource at the location specified by the * Request URI. * * @see <a * href="http://www.webdav.org/specs/rfc2518.html#METHOD_MKCOL">WEBDAV * RFC - 8.3 MKCOL Method</a> */ public static final Method MKCOL = new Method("MKCOL", "Used to create a new collection (WebDAV)", BASE_WEBDAV + "#METHOD_MKCOL", false, true); /** * Logical equivalent of a copy, followed by consistency maintenance * processing, followed by a delete of the source where all three actions * are performed atomically. * * @see <a * href="http://www.webdav.org/specs/rfc2518.html#METHOD_MOVE">WEBDAV * RFC - 8.3 MKCOL Method</a> */ public static final Method MOVE = new Method( "MOVE", "Logical equivalent of a copy, followed by consistency maintenance processing, followed by a delete of the source (WebDAV)", BASE_WEBDAV + "#METHOD_MOVE", false, false); /** * Requests for information about the communication options available on the * request/response chain identified by the URI. * * @see <a * href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.2">HTTP * RFC - 9.2 OPTIONS</a> */ public static final Method OPTIONS = new Method( "OPTIONS", "Requests for information about the communication options available on the request/response chain identified by the URI", BASE_HTTP + "#sec9.2", true, true); /** * Requests that the origin server applies partial modifications contained * in the entity enclosed in the request to the resource identified by the * request URI. * * @see <a href="http://tools.ietf.org/html/rfc5789">HTTP PATCH RFC 5789</a> */ public static final Method PATCH = new Method( "PATCH", "Requests that the origin server applies partial modifications to the resource identified by the request URI", "http://tools.ietf.org/html/rfc5789", false, false); /** * Requests that the origin server accepts the entity enclosed in the * request as a new subordinate of the resource identified by the request * URI. * * @see <a * href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5">HTTP * RFC - 9.5 POST</a> */ public static final Method POST = new Method( "POST", "Requests that the origin server accepts the entity enclosed in the request as a new subordinate of the resource identified by the request URI", BASE_HTTP + "#sec9.5", false, false); /** * Retrieves properties defined on the resource identified by the request * URI. * * @see <a * href="http://www.webdav.org/specs/rfc2518.html#METHOD_PROPFIND">WEBDAV * RFC - 8.1 PROPFIND</a> */ public static final Method PROPFIND = new Method( "PROPFIND", "Retrieves properties defined on the resource identified by the request URI", BASE_WEBDAV + "#METHOD_PROPFIND", true, true); /** * Processes instructions specified in the request body to set and/or remove * properties defined on the resource identified by the request URI. * * @see <a * href="http://www.webdav.org/specs/rfc2518.html#METHOD_PROPPATCH">WEBDAV * RFC - 8.2 PROPPATCH</a> */ public static final Method PROPPATCH = new Method( "PROPPATCH", "Processes instructions specified in the request body to set and/or remove properties defined on the resource identified by the request URI", BASE_WEBDAV + "#METHOD_PROPPATCH", false, true); /** * Requests that the enclosed entity be stored under the supplied request * URI. * * @see <a * href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6" * HTTP RFC - 9.6 PUT</a> */ public static final Method PUT = new Method( "PUT", "Requests that the enclosed entity be stored under the supplied request URI", BASE_HTTP + "#sec9.6", false, true); /** * Used to invoke a remote, application-layer loop-back of the request * message. * * @see <a * href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.8">HTTP * RFC - 9.8 TRACE</a> */ public static final Method TRACE = new Method( "TRACE", "Used to invoke a remote, application-layer loop-back of the request message", BASE_HTTP + "#sec9.8", true, true); /** * Removes the lock identified by the lock token from the request URI, and * all other resources included in the lock. * * @see <a * href="http://www.webdav.org/specs/rfc2518.html#METHOD_UNLOCK">WEBDAV * RFC - 8.11 UNLOCK Method</a> */ public static final Method UNLOCK = new Method( "UNLOCK", "Removes the lock identified by the lock token from the request URI, and all other resources included in the lock", BASE_WEBDAV + "#METHOD_UNLOCK", true, false); /** * Adds a new Method to the list of registered methods. * * @param method * The method to register. */ public static void register(Method method) { String name = (method == null) ? null : method.getName().toLowerCase(); if ((name != null) && !name.equals("")) { _methods.put(name, method); } } /** * Sorts the given list of methods by name. * * @param methods * The methods to sort. */ public static void sort(List<Method> methods) { Collections.sort(methods, new Comparator<Method>() { public int compare(Method m1, Method m2) { return m1.getName().compareTo(m2.getName()); } }); } /** * Returns the method associated to a given method name. If an existing * constant exists then it is returned, otherwise a new instance is created. * * @param name * The method name. * @return The associated method. */ public static Method valueOf(final String name) { Method result = null; if ((name != null) && !name.equals("")) { result = Method._methods.get(name.toLowerCase()); if (result == null) { result = new Method(name); } } return result; } /** The description. */ private final String description; /** * Indicates if the side-effects of several requests is the same as a single * request. */ private volatile boolean idempotent; /** The name. */ private volatile String name; /** Indicates if the method replies with a response. */ private final boolean replying; /** * Indicates if it should have the significance of taking an action other * than retrieval. */ private final boolean safe; /** The URI of the specification describing the method. */ private volatile String uri; // { // // Let the engine register all methods (the default ones and the ones to // // be discovered) as soon as the Method class is loaded or at least // // used. // Engine.getInstance(); // } /** * Constructor for unsafe and non idempotent methods. * * @param name * The technical name of the method. * @see org.restlet.data.Method#valueOf(String) */ public Method(final String name) { this(name, null); } /** * Constructor for unsafe and non idempotent methods. * * @param name * The technical name of the method. * @param description * The description. * @see org.restlet.data.Method#valueOf(String) */ public Method(String name, String description) { this(name, description, null, false, false); } /** * Constructor for unsafe and non idempotent methods. * * @param name * The technical name. * @param description * The description. * @param uri * The URI of the specification describing the method. * @see org.restlet.data.Method#valueOf(String) */ public Method(String name, String description, String uri) { this(name, description, uri, false, false); } /** * Constructor for methods that reply to requests with responses. * * @param name * The technical name. * @param description * The description. * @param uri * The URI of the specification describing the method. * @param safe * Indicates if the method is safe. * @param idempotent * Indicates if the method is idempotent. * @see org.restlet.data.Method#valueOf(String) */ public Method(String name, String description, String uri, boolean safe, boolean idempotent) { this(name, description, uri, safe, idempotent, true); } /** * Constructor. * * @param name * The technical name. * @param description * The description. * @param uri * The URI of the specification describing the method. * @param safe * Indicates if the method is safe. * @param idempotent * Indicates if the method is idempotent. * @param replying * Indicates if the method replies with a response. * @see org.restlet.data.Method#valueOf(String) */ public Method(String name, String description, String uri, boolean safe, boolean idempotent, boolean replying) { this.name = name; this.description = description; this.uri = uri; this.safe = safe; this.idempotent = idempotent; this.replying = replying; } /** * Compares this method to another. Based on the method name. * * @param o * The other method. */ public int compareTo(Method o) { if (o != null) { return this.getName().compareTo(o.getName()); } return 1; } /** {@inheritDoc} */ @Override public boolean equals(final Object object) { return (object instanceof Method) && ((Method) object).getName().equals(getName()); } /** * Returns the description. * * @return The description. */ public String getDescription() { return this.description; } /** * Returns the name. * * @return The name. */ public String getName() { return name; } /** * Returns the URI of the specification describing the method. * * @return The URI of the specification describing the method. */ public String getUri() { return this.uri; } /** {@inheritDoc} */ @Override public int hashCode() { return (getName() == null) ? 0 : getName().hashCode(); } /** * Indicates if the side-effects of several requests is the same as a single * request. * * @return True if the method is idempotent. */ public boolean isIdempotent() { return idempotent; } /** * Indicates if the method replies with a response. * * @return True if the method replies with a response. */ public boolean isReplying() { return replying; } /** * Indicates if it should have the significance of taking an action other * than retrieval. * * @return True if the method is safe. */ public boolean isSafe() { return safe; } /** * Returns the name. * * @return The name. */ @Override public String toString() { return getName(); } }