http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestServletContext.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestServletContext.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestServletContext.java new file mode 100755 index 0000000..f093a35 --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestServletContext.java @@ -0,0 +1,218 @@ +/*************************************************************************************************************************** + * 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.juneau.server; + +import java.util.*; + +import org.apache.juneau.*; +import org.apache.juneau.internal.*; +import org.apache.juneau.parser.*; +import org.apache.juneau.serializer.*; +import org.apache.juneau.server.annotation.*; + +/** + * Configurable properties on the {@link RestServlet} class. + * <p> + * Properties can be set on the {@link RestServlet} class using the {@link RestResource#properties} or {@link RestMethod#properties} annotations. + * <p> + * These properties can also be passed in as servlet init parameters or system properties. + * <p> + * Some of these properties are only applicable on the servlet class, and others can be specified on the servlet class or method.<br> + * These distinctions are noted below. + * <p> + * See {@link ContextFactory} for more information about context properties. + * + * @author James Bognar (james.bog...@salesforce.com) + */ +public final class RestServletContext extends Context { + + /** + * Allow header URL parameters ({@link Boolean}, default=<jk>true</jk>). + * <p> + * When enabled, headers such as <js>"Accept"</js> and <js>"Content-Type"</js> to be passed in as URL query parameters. + * For example: <js>"?Accept=text/json&Content-Type=text/json"</js> + * <p> + * Parameter names are case-insensitive. + * <p> + * Useful for debugging REST interface using only a browser. + * <p> + * Applicable to servlet class only. + */ + public static final String REST_allowHeaderParams = "RestServlet.allowHeaderParams"; + + /** + * Allow <js>"method"</js> URL parameter for specific HTTP methods (String, default=<js>""</js>, example=<js>"HEAD,OPTIONS"</js>). + * <p> + * When specified, the HTTP method can be overridden by passing in a <js>"method"</js> URL parameter on a regular GET request. + * For example: <js>"?method=OPTIONS"</js> + * <p> + * Parameter name is case-insensitive. Use "*" to represent all methods. For backwards compatibility, "true" also means "*". + * <p> + * Note that per the <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html">HTTP specification</a>, special care should + * be taken when allowing non-safe (POST, PUT, DELETE) methods to be invoked through GET requests. + * <p> + * Applicable to servlet class only. + */ + public static final String REST_allowMethodParam = "RestServlet.allowMethodParam"; + + /** + * Allow <js>"content"</js> URL parameter ({@link Boolean}, default=<jk>true</jk>). + * <p> + * When enabled, the HTTP body content on PUT and POST requests can be passed in as text using the <js>"content"</js> URL parameter. + * For example: <js>"?content={name:'John%20Smith',age:45}"</js> + * <p> + * Parameter name is case-insensitive. + * <p> + * Useful for debugging PUT and POST methods using only a browser. + * <p> + * Applicable to servlet class only. + */ + public static final String REST_allowContentParam = "RestServlet.allowContentParam"; + + /** + * Render stack traces in HTTP response bodies when errors occur ({@link Boolean}, default=<jk>false</jk>). + * <p> + * When enabled, Java stack traces will be rendered in the output response. + * Useful for debugging, although allowing stack traces to be rendered may cause security concerns. + * <p> + * Applicable to servlet class only. + */ + public static final String REST_renderResponseStackTraces = "RestServlet.renderResponseStackTraces"; + + /** + * Use stack trace hashes ({@link Boolean}, default=<jk>true</jk>). + * <p> + * When enabled, the number of times an exception has occurred will be determined based on stack trace hashsums, + * made available through the {@link RestException#getOccurrence()} method. + * <p> + * Applicable to servlet class only. + */ + public static final String REST_useStackTraceHashes = "RestServlet.useStackTraceHashes"; + + /** + * The default character encoding for the request and response if not specified on the request ({@link String}>, default=<js>"utf-8"</js>). + * <p> + * Applicable to servlet class and methods. + */ + public static final String REST_defaultCharset = "RestServlet.defaultCharset"; + + /** + * The expected format of request parameters ({@link String}, default=<js>"UON"</js>). + * <p> + * Possible values: + * <ul class='spaced-list'> + * <li><js>"UON"</js> - URL-Encoded Object Notation.<br> + * This notation allows for request parameters to contain arbitrarily complex POJOs. + * <li><js>"PLAIN"</js> - Plain text.<br> + * This treats request parameters as plain text.<br> + * Only POJOs directly convertable from <l>Strings</l> can be represented in parameters when using this mode. + * </ul> + * <p> + * Note that the parameter value <js>"(foo)"</js> is interpreted as <js>"(foo)"</js> when using plain mode, but + * <js>"foo"</js> when using UON mode. + * <p> + * The format can also be specified per-parameter using the {@link Param#format() @Param.format()} and {@link QParam#format() @QParam.format()} + * annotations. + * <p> + * Applicable to servlet class and methods. + */ + public static final String REST_paramFormat = "RestServlet.paramFormat"; + + //-------------------------------------------------------------------------------- + // Automatically added properties. + //-------------------------------------------------------------------------------- + + /** + * The request servlet path. + * <p> + * Automatically added to properties return by {@link RestServlet#createRequestProperties(org.apache.juneau.ObjectMap, RestRequest)} + * and are therefore available through {@link SerializerSession#getProperties()} and {@link ParserSession#getProperties()}. + * <p> + * Equivalent to the value returned by {@link RestRequest#getServletPath()} + */ + public static final String REST_servletPath = "RestServlet.servletPath"; + + /** + * The request servlet URI. + * <p> + * Equivalent to the value returned by {@link RestRequest#getServletURI()} + */ + public static final String REST_servletURI = "RestServlet.servletURI"; + + /** + * The request servlet URI. + * <p> + * Equivalent to the value returned by {@link RestRequest#getRelativeServletURI()} + */ + public static final String REST_relativeServletURI = "RestServlet.relativeServletURI"; + + /** + * The request URI path info. + * <p> + * Automatically added to properties return by {@link RestServlet#createRequestProperties(org.apache.juneau.ObjectMap, RestRequest)} + * and are therefore available through {@link SerializerSession#getProperties()} and {@link ParserSession#getProperties()}. + * <p> + * Equivalent to the value returned by {@link RestRequest#getPathInfo()} + */ + public static final String REST_pathInfo = "RestServlet.pathInfo"; + + /** + * The request URI. + * <p> + * Automatically added to properties return by {@link RestServlet#createRequestProperties(org.apache.juneau.ObjectMap, RestRequest)} + * and are therefore available through {@link SerializerSession#getProperties()} and {@link ParserSession#getProperties()}. + * <p> + * Equivalent to the value returned by {@link RestRequest#getRequestURI()} + */ + public static final String REST_requestURI = "RestServlet.requestURI"; + + /** + * The request method. + * <p> + * Automatically added to properties return by {@link RestServlet#createRequestProperties(org.apache.juneau.ObjectMap, RestRequest)} + * and are therefore available through {@link SerializerSession#getProperties()} and {@link ParserSession#getProperties()}. + * <p> + * Equivalent to the value returned by {@link RestRequest#getMethod()} + */ + public static final String REST_method = "RestServlet.method"; + + + final boolean allowHeaderParams, allowContentParam, renderResponseStackTraces, useStackTraceHashes; + final String defaultCharset, paramFormat; + final Set<String> allowMethodParams; + + /** + * Constructor. + * <p> + * Typically only called from {@link ContextFactory#getContext(Class)}. + * + * @param cf The factory that created this context. + */ + public RestServletContext(ContextFactory cf) { + super(cf); + allowHeaderParams = cf.getProperty(REST_allowHeaderParams, boolean.class, true); + allowContentParam = cf.getProperty(REST_allowContentParam, boolean.class, true); + renderResponseStackTraces = cf.getProperty(REST_renderResponseStackTraces, boolean.class, false); + useStackTraceHashes = cf.getProperty(REST_useStackTraceHashes, boolean.class, true); + defaultCharset = cf.getProperty(REST_defaultCharset, String.class, "utf-8"); + paramFormat = cf.getProperty(REST_paramFormat, String.class, ""); + + Set<String> s = new LinkedHashSet<String>(); + for (String m : StringUtils.split(cf.getProperty(REST_allowMethodParam, String.class, ""), ',')) + if (m.equals("true")) // For backwards compatibility when this was a boolean field. + s.add("*"); + else + s.add(m.toUpperCase()); + allowMethodParams = Collections.unmodifiableSet(s); + } +}
http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestServletDefault.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestServletDefault.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestServletDefault.java new file mode 100755 index 0000000..2402927 --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestServletDefault.java @@ -0,0 +1,235 @@ +/*************************************************************************************************************************** + * 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.juneau.server; + +import static org.apache.juneau.html.HtmlDocSerializerContext.*; +import static org.apache.juneau.server.RestServletContext.*; + +import org.apache.juneau.html.*; +import org.apache.juneau.jso.*; +import org.apache.juneau.json.*; +import org.apache.juneau.msgpack.*; +import org.apache.juneau.plaintext.*; +import org.apache.juneau.server.annotation.*; +import org.apache.juneau.server.labels.*; +import org.apache.juneau.soap.*; +import org.apache.juneau.urlencoding.*; +import org.apache.juneau.xml.*; + +/** + * Subclass of {@link RestServlet} with default serializers and parsers defined. + * <p> + * Supports the following request <code>Accept</code> header values with the resulting response <code>Content-Type</code>: + * </p> + * <table class='styled'> + * <tr> + * <th>Accept</th> + * <th>Content-Type</th> + * <th>Serializer</th> + * </tr> + * <tr> + * <td class='code'>application/json<br>text/json</td> + * <td class='code'>application/json</td> + * <td>{@link JsonSerializer}</td> + * </tr> + * <tr> + * <td class='code'>application/json+simple<br>text/json+simple</td> + * <td class='code'>application/json</td> + * <td>{@link org.apache.juneau.json.JsonSerializer.Simple}</td> + * </tr> + * <td class='code'>application/json+schema<br>text/json+schema</td> + * <td class='code'>application/json</td> + * <td>{@link JsonSchemaSerializer}</td> + * </tr> + * <tr> + * <td class='code'>text/xml</td> + * <td class='code'>text/xml</td> + * <td>{@link XmlDocSerializer}</td> + * </tr> + * <tr> + * <td class='code'>text/xml+schema</td> + * <td class='code'>text/xml</td> + * <td>{@link XmlSchemaDocSerializer}</td> + * </tr> + * <tr> + * <td class='code'>text/html</td> + * <td class='code'>text/html</td> + * <td>{@link HtmlDocSerializer}</td> + * </tr> + * <tr> + * <td class='code'>text/html+stripped</td> + * <td class='code'>text/html</td> + * <td>{@link HtmlStrippedDocSerializer}</td> + * </tr> + * <tr> + * <td class='code'>text/uon</td> + * <td class='code'>text/uon</td> + * <td>{@link UonSerializer}</td> + * </tr> + * <tr> + * <td class='code'>text/uon-simple</td> + * <td class='code'>text/uon</td> + * <td>{@link org.apache.juneau.urlencoding.UonSerializer.Simple}</td> + * </tr> + * <tr> + * <td class='code'>application/x-www-form-urlencoded</td> + * <td class='code'>application/x-www-form-urlencoded</td> + * <td>{@link UrlEncodingSerializer}</td> + * </tr> + * <tr> + * <td class='code'>application/x-www-form-urlencoded-simple</td> + * <td class='code'>application/x-www-form-urlencoded</td> + * <td>{@link org.apache.juneau.urlencoding.UrlEncodingSerializer.Simple}</td> + * </tr> + * <tr> + * <td class='code'>text/xml+soap</td> + * <td class='code'>text/xml</td> + * <td>{@link SoapXmlSerializer}</td> + * </tr> + * <tr> + * <td class='code'>text/plain</td> + * <td class='code'>text/plain</td> + * <td>{@link PlainTextSerializer}</td> + * </tr> + * <tr> + * <td class='code'>application/x-java-serialized-object</td> + * <td class='code'>application/x-java-serialized-object</td> + * <td>{@link JavaSerializedObjectSerializer}</td> + * </tr> + * </table> + * <p> + * Supports the following request <code>Content-Type</code> header values: + * </p> + * <table class='styled'> + * <tr> + * <th>Content-Type</th> + * <th>Parser</th> + * </tr> + * <tr> + * <td class='code'>application/json<br>text/json</td> + * <td>{@link JsonParser}</td> + * </tr> + * <tr> + * <td class='code'>text/xml<br>application/xml</td> + * <td>{@link XmlParser}</td> + * </tr> + * <tr> + * <td class='code'>text/html<br>text/html+stripped</td> + * <td>{@link HtmlParser}</td> + * </tr> + * <tr> + * <td class='code'>text/uon</td> + * <td>{@link UonParser}</td> + * </tr> + * <tr> + * <td class='code'>application/x-www-form-urlencoded</td> + * <td>{@link UrlEncodingParser}</td> + * </tr> + * <tr> + * <td class='code'>text/plain</td> + * <td>{@link PlainTextParser}</td> + * </tr> + * </table> + * <p> + * It should be noted that we do NOT add {@link JavaSerializedObjectParser} to the list of parsers since this could + * cause security issues. Use caution when using this particular parser as it could inadvertantly cause + * code execution security holes. + * </p> + * <p> + * The list of serializers and parsers can be appended to using the {@link RestResource#serializers() @RestResource.serializers()} + * and {@link RestResource#parsers() @RestResource.parsers()} annotations on subclasses. + * </p> + * <p> + * This subclass also provides a default OPTIONS page by implementing a {@link #getOptions(RestRequest)} that returns a POJO consisting + * of beans describing the class. + * </p> + * <img class='bordered' src='doc-files/OptionsPage.png'> + * <p> + * The OPTIONS page can be modified or augmented by overriding this method and providing your own data. + * </p> + * + * <h6 class='topic'>Other Notes</h6> + * <ul class='spaced-list'> + * <li>Provides a default HTML stylesheet by setting {@link RestResource#stylesheet() @RestResource.stylesheet()} to <js>"styles/juneau.css"</js>. + * <li>Provides a default favicon by setting {@link RestResource#favicon() @RestResource.favicon()} to <js>"juneau.ico"</js>. + * <li>Provides a default classpath entry "htdocs" by setting {@link RestResource#staticFiles() @RestResource.staticFiles()} to <js>"{htdocs:'htdocs'}"</js>. + * This allows files inside the <code>[servletPackage].htdocs</code> package to be served up under the URL <code>/servletPath/htdocs</code>. + * </ul> + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@RestResource( + serializers={ + HtmlDocSerializer.class, // HTML must be listed first because Internet Explore does not include text/html in their Accept header. + HtmlStrippedDocSerializer.class, + HtmlSchemaDocSerializer.class, + JsonSerializer.class, + JsonSerializer.Simple.class, + JsonSchemaSerializer.class, + XmlDocSerializer.class, + XmlSchemaDocSerializer.class, + UonSerializer.class, + UonSerializer.Simple.class, + UrlEncodingSerializer.class, + UrlEncodingSerializer.Simple.class, + MsgPackSerializer.class, + SoapXmlSerializer.class, + PlainTextSerializer.class, + JavaSerializedObjectSerializer.class + }, + parsers={ + JsonParser.class, + XmlParser.class, + HtmlParser.class, + UonParser.class, + UrlEncodingParser.class, + MsgPackParser.class, + PlainTextParser.class + }, + properties={ + // Allow &method parameter on safe HTTP methods. + @Property(name=REST_allowMethodParam, value="OPTIONS"), + // Provide a default title on HTML pages. + @Property(name=HTMLDOC_title, value="$R{servletLabel}"), + // Provide a default description on HTML pages. + @Property(name=HTMLDOC_description, value="$R{servletDescription}") + }, + stylesheet="styles/juneau.css", + favicon="juneau.ico", + staticFiles="{htdocs:'htdocs'}" +) +public abstract class RestServletDefault extends RestServlet { + private static final long serialVersionUID = 1L; + + /** + * [OPTIONS /*] - Show resource options. + * + * @param req The HTTP request. + * @return A bean containing the contents for the OPTIONS page. + */ + @RestMethod(name="OPTIONS", path="/*", + properties={ + @Property(name=HTMLDOC_links, value="{back:'$R{servletURI}'}"), + @Property(name=HTMLDOC_description, value="Resource options") + }, + description="Resource options" + ) + public ResourceOptions getOptions(RestRequest req) { + return new ResourceOptions(this, req); + } + + @Override /* RestServlet */ + public boolean hasOptionsPage() { + return true; + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestServletException.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestServletException.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestServletException.java new file mode 100755 index 0000000..1e33808 --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestServletException.java @@ -0,0 +1,48 @@ +/*************************************************************************************************************************** + * 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.juneau.server; + +import java.text.*; + +import javax.servlet.*; + +/** + * General exception thrown from {@link RestServlet} during construction or initialization. + * @author James Bognar (james.bog...@salesforce.com) + */ +public class RestServletException extends ServletException { + + private static final long serialVersionUID = 1L; + + /** + * Constructor. + * + * @param message The detailed message. + * @param args Optional message arguments. + */ + public RestServletException(String message, Object...args) { + super(args.length == 0 ? message : MessageFormat.format(message, args)); + } + + /** + * Sets the inner cause for this exception. + * + * @param cause The inner cause. + * @return This object (for method chaining). + */ + @Override /* Throwable */ + public synchronized RestServletException initCause(Throwable cause) { + super.initCause(cause); + return this; + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestServletGroupDefault.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestServletGroupDefault.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestServletGroupDefault.java new file mode 100755 index 0000000..4083e61 --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestServletGroupDefault.java @@ -0,0 +1,43 @@ +/*************************************************************************************************************************** + * 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.juneau.server; + +import org.apache.juneau.server.annotation.*; +import org.apache.juneau.server.labels.*; + +/** + * Specialized subclass of {@link RestServletDefault} for showing "group" pages. + * <p> + * Group pages consist of simple lists of child resource URLs and their labels. + * They're meant to be used as jumping-off points for child resources. + * <p> + * Child resources are specified using the {@link RestResource#children()} annotation. + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@RestResource() +public abstract class RestServletGroupDefault extends RestServletDefault { + private static final long serialVersionUID = 1L; + + /** + * [GET /] - Get child resources. + * + * @param req The HTTP request. + * @return The bean containing links to the child resources. + */ + @RestMethod(name="GET", path="/", description="Child resources") + public ChildResourceDescriptions getChildren(RestRequest req) { + return new ChildResourceDescriptions(this, req); + } +} + http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestUtils.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestUtils.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestUtils.java new file mode 100755 index 0000000..12ce0cd --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/RestUtils.java @@ -0,0 +1,250 @@ +/*************************************************************************************************************************** + * 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.juneau.server; + +import java.io.*; +import java.net.*; +import java.util.*; + +import javax.servlet.http.*; + +import org.apache.juneau.internal.*; + +/** + * Various reusable utility methods. + * + * @author James Bognar (james.bog...@salesforce.com) + */ +public final class RestUtils { + + /** + * Returns readable text for an HTTP response code. + * + * @param rc The HTTP response code. + * @return Readable text for an HTTP response code, or <jk>null</jk> if it's an invalid code. + */ + public static String getHttpResponseText(int rc) { + return httpMsgs.get(rc); + } + + @SuppressWarnings("serial") + private static Map<Integer,String> httpMsgs = new HashMap<Integer,String>() {{ + put(200, "OK"); + put(201, "Created"); + put(202, "Accepted"); + put(203, "Non-Authoritative Information"); + put(204, "No Content"); + put(205, "Reset Content"); + put(206, "Partial Content"); + put(300, "Multiple Choices"); + put(301, "Moved Permanently"); + put(302, "Temporary Redirect"); + put(303, "See Other"); + put(304, "Not Modified"); + put(305, "Use Proxy"); + put(307, "Temporary Redirect"); + put(400, "Bad Request"); + put(401, "Unauthorized"); + put(402, "Payment Required"); + put(403, "Forbidden"); + put(404, "Not Found"); + put(405, "Method Not Allowed"); + put(406, "Not Acceptable"); + put(407, "Proxy Authentication Required"); + put(408, "Request Time-Out"); + put(409, "Conflict"); + put(410, "Gone"); + put(411, "Length Required"); + put(412, "Precondition Failed"); + put(413, "Request Entity Too Large"); + put(414, "Request-URI Too Large"); + put(415, "Unsupported Media Type"); + put(500, "Internal Server Error"); + put(501, "Not Implemented"); + put(502, "Bad Gateway"); + put(503, "Service Unavailable"); + put(504, "Gateway Timeout"); + put(505, "HTTP Version Not Supported"); + }}; + + /** + * Trims <js>'/'</js> characters from both the start and end of the specified string. + * + * @param s The string to trim. + * @return A new trimmed string, or the same string if no trimming was necessary. + */ + public static String trimSlashes(String s) { + if (s == null) + return null; + while (StringUtils.endsWith(s, '/')) + s = s.substring(0, s.length()-1); + while (s.length() > 0 && s.charAt(0) == '/') + s = s.substring(1); + return s; + } + + /** + * Trims <js>'/'</js> characters from the end of the specified string. + * + * @param s The string to trim. + * @return A new trimmed string, or the same string if no trimming was necessary. + */ + public static String trimTrailingSlashes(String s) { + if (s == null) + return null; + while (StringUtils.endsWith(s, '/')) + s = s.substring(0, s.length()-1); + return s; + } + + /** + * Trims <js>'/'</js> characters from the end of the specified string. + * + * @param s The string to trim. + * @return The same string buffer. + */ + public static StringBuffer trimTrailingSlashes(StringBuffer s) { + if (s == null) + return null; + while (s.length() > 0 && s.charAt(s.length()-1) == '/') + s.setLength(s.length()-1); + return s; + } + + /** + * Decodes a <code>application/x-www-form-urlencoded</code> string using <code>UTF-8</code> encoding scheme. + * + * @param s The string to decode. + * @return The decoded string, or <jk>null</jk> if input is <jk>null</jk>. + */ + public static String decode(String s) { + if (s == null) + return s; + boolean needsDecode = false; + for (int i = 0; i < s.length() && ! needsDecode; i++) { + char c = s.charAt(i); + if (c == '+' || c == '%') + needsDecode = true; + } + if (needsDecode) + try { + return URLDecoder.decode(s, "UTF-8"); + } catch (UnsupportedEncodingException e) {/* Won't happen */} + return s; + } + + // Characters that do not need to be URL-encoded + private static final AsciiSet unencodedChars = new AsciiSet("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()\\"); + + /** + * Encodes a <code>application/x-www-form-urlencoded</code> string using <code>UTF-8</code> encoding scheme. + * + * @param s The string to encode. + * @return The encoded string, or <jk>null</jk> if input is <jk>null</jk>. + */ + public static String encode(String s) { + if (s == null) + return null; + boolean needsEncode = false; + for (int i = 0; i < s.length() && ! needsEncode; i++) + needsEncode |= (! unencodedChars.contains(s.charAt(i))); + if (needsEncode) + try { + return URLEncoder.encode(s, "UTF-8"); + } catch (UnsupportedEncodingException e) {/* Won't happen */} + return s; + } + + /** + * Identical to {@link HttpServletRequest#getPathInfo()} but doesn't decode encoded characters. + * + * @param req The HTTP request + * @return The undecoded path info. + */ + public static String getPathInfoUndecoded(HttpServletRequest req) { + String requestURI = req.getRequestURI(); + String contextPath = req.getContextPath(); + String servletPath = req.getServletPath(); + int l = contextPath.length() + servletPath.length(); + if (requestURI.length() == l) + return null; + return requestURI.substring(l); + } + + /** + * Efficiently trims the path info part from a request URI. + * <p> + * The result is the URI of the servlet itself. + * + * @param requestURI The value returned by {@link HttpServletRequest#getRequestURL()} + * @param contextPath The value returned by {@link HttpServletRequest#getContextPath()} + * @param servletPath The value returned by {@link HttpServletRequest#getServletPath()} + * @return The same StringBuilder with remainder trimmed. + */ + public static StringBuffer trimPathInfo(StringBuffer requestURI, String contextPath, String servletPath) { + if (servletPath.equals("/")) + servletPath = ""; + if (contextPath.equals("/")) + contextPath = ""; + + try { + // Given URL: http://hostname:port/servletPath/extra + // We want: http://hostname:port/servletPath + int sc = 0; + for (int i = 0; i < requestURI.length(); i++) { + char c = requestURI.charAt(i); + if (c == '/') { + sc++; + if (sc == 3) { + if (servletPath.isEmpty()) { + requestURI.setLength(i); + return requestURI; + } + + // Make sure context path follows the authority. + for (int j = 0; j < contextPath.length(); i++, j++) + if (requestURI.charAt(i) != contextPath.charAt(j)) + throw new Exception("case=1"); + + // Make sure servlet path follows the authority. + for (int j = 0; j < servletPath.length(); i++, j++) + if (requestURI.charAt(i) != servletPath.charAt(j)) + throw new Exception("case=2"); + + // Make sure servlet path isn't a false match (e.g. /foo2 should not match /foo) + c = (requestURI.length() == i ? '/' : requestURI.charAt(i)); + if (c == '/' || c == '?') { + requestURI.setLength(i); + return requestURI; + } + + throw new Exception("case=3"); + } + } else if (c == '?') { + if (sc != 2) + throw new Exception("case=4"); + if (servletPath.isEmpty()) { + requestURI.setLength(i); + return requestURI; + } + throw new Exception("case=5"); + } + } + if (servletPath.isEmpty()) + return requestURI; + throw new Exception("case=6"); + } catch (Exception e) { + throw new RuntimeException("Could not find servlet path in request URI. URI=["+requestURI+"], servletPath=["+servletPath+"]", e); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/StreamResource.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/StreamResource.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/StreamResource.java new file mode 100755 index 0000000..fb7dd13 --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/StreamResource.java @@ -0,0 +1,91 @@ +/*************************************************************************************************************************** + * 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.juneau.server; + +import java.io.*; +import java.util.*; + +import org.apache.juneau.*; +import org.apache.juneau.internal.*; +import org.apache.juneau.server.response.*; + +/** + * Represents the contents of a byte stream file with convenience methods for adding HTTP response headers. + * <p> + * This class is handled special by the {@link StreamableHandler} class. + * + * @author James Bognar (james.bog...@salesforce.com) + */ +public class StreamResource implements Streamable { + + private byte[] contents; + private String mediaType; + private Map<String,String> headers = new LinkedHashMap<String,String>(); + + /** + * Constructor. + * Create a stream resource from a byte array. + * + * @param contents The resource contents. + * @param mediaType The resource media type. + */ + public StreamResource(byte[] contents, String mediaType) { + this.contents = contents; + this.mediaType = mediaType; + } + + /** + * Constructor. + * Create a stream resource from an <code>InputStream</code>. + * Contents of stream will be loaded into a reusable byte array. + * + * @param contents The resource contents. + * @param mediaType The resource media type. + * @throws IOException + */ + public StreamResource(InputStream contents, String mediaType) throws IOException { + this.contents = IOUtils.readBytes(contents, 1024); + this.mediaType = mediaType; + } + + /** + * Add an HTTP response header. + * + * @param name The header name. + * @param value The header value, converted to a string using {@link Object#toString()}. + * @return This object (for method chaining). + */ + public StreamResource setHeader(String name, Object value) { + headers.put(name, value == null ? "" : value.toString()); + return this; + } + + /** + * Get the HTTP response headers. + * + * @return The HTTP response headers. Never <jk>null</jk>. + */ + public Map<String,String> getHeaders() { + return headers; + } + + @Override /* Streamable */ + public void streamTo(OutputStream os) throws IOException { + os.write(contents); + } + + @Override /* Streamable */ + public String getMediaType() { + return mediaType; + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/UrlPathPattern.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/UrlPathPattern.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/UrlPathPattern.java new file mode 100755 index 0000000..4c161bb --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/UrlPathPattern.java @@ -0,0 +1,161 @@ +/*************************************************************************************************************************** + * 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.juneau.server; + +import static org.apache.juneau.server.RestUtils.*; + +import java.util.*; +import java.util.regex.*; + +import org.apache.juneau.internal.*; +import org.apache.juneau.server.annotation.*; + +/** + * A parsed path pattern constructed from a {@link RestMethod#path()} value. + * <p> + * Handles aspects of matching and precedence ordering. + * + * @author James Bognar (james.bog...@salesforce.com) + */ +public final class UrlPathPattern implements Comparable<UrlPathPattern> { + private Pattern pattern; + String patternString; + private boolean isOnlyDotAll, isDotAll; + String[] vars = new String[0]; + + /** + * Constructor. + * + * @param patternString The raw pattern string from the {@link RestMethod#path()} annotation. + */ + public UrlPathPattern(String patternString) { + this.patternString = patternString; + if (! StringUtils.startsWith(patternString, '/')) + patternString = '/' + patternString; + if (patternString.equals("/*")) { + isOnlyDotAll = true; + return; + } + if (patternString.endsWith("/*")) + isDotAll = true; + + // Find all {xxx} variables. + Pattern p = Pattern.compile("\\{([^\\}]+)\\}"); + List<String> vl = new LinkedList<String>(); + Matcher m = p.matcher(patternString); + while (m.find()) + vl.add(m.group(1)); + this.vars = vl.toArray(new String[vl.size()]); + + patternString = patternString.replaceAll("\\{[^\\}]+\\}", "([^\\/]+)"); + patternString = patternString.replaceAll("\\/\\*$", "((?:)|(?:\\/.*))"); + pattern = Pattern.compile(patternString); + } + + /** + * Returns a non-<jk>null</jk> value if the specified path matches this pattern. + * + * @param path The path to match against. + * @return An array of values matched against <js>"{var}"</js> variable in the pattern, + * or an empty array if the pattern matched but no vars were present, or <jk>null</jk> + * if the specified path didn't match the pattern. + */ + protected String[] match(String path) { + + if (isOnlyDotAll) { + // Remainder always gets leading slash trimmed. + if (path != null) + path = path.substring(1); + return new String[]{path}; + } + + if (path == null) + return (patternString.equals("/") ? new String[]{} : null); + + Matcher m = pattern.matcher(path); + if (! m.matches()) + return null; + + int len = m.groupCount(); + String[] v = new String[len]; + + for (int i = 0; i < len; i++) { + if (isDotAll && i == len-1) + v[i] = m.group(i+1).isEmpty() ? null : m.group(i+1).substring(1); + else + v[i] = decode(m.group(i+1)); + } + + return v; + } + + /** + * Comparator for this object. + * The comparator is designed to order URL pattern from most-specific to least-specific. + * For example, the following patterns would be ordered as follows: + * <ol> + * <li><code>/foo/bar</code> + * <li><code>/foo/bar/*</code> + * <li><code>/foo/{id}/bar</code> + * <li><code>/foo/{id}/bar/*</code> + * <li><code>/foo/{id}</code> + * <li><code>/foo/{id}/*</code> + * <li><code>/foo</code> + * <li><code>/foo/*</code> + * </ol> + */ + @Override /* Comparable */ + public int compareTo(UrlPathPattern o) { + String s1 = patternString.replaceAll("\\{[^\\}]+\\}", ".").replaceAll("\\w+", "X").replaceAll("\\.", "W"); + String s2 = o.patternString.replaceAll("\\{[^\\}]+\\}", ".").replaceAll("\\w+", "X").replaceAll("\\.", "W"); + if (s1.isEmpty()) + s1 = "+"; + if (s2.isEmpty()) + s2 = "+"; + if (! s1.endsWith("/*")) + s1 = s1 + "/W"; + if (! s2.endsWith("/*")) + s2 = s2 + "/W"; + int c = s2.compareTo(s1); + if (c == 0) + return o.toRegEx().compareTo(toRegEx()); + return c; + } + + @Override /* Object */ + public boolean equals(Object o) { + if (! (o instanceof UrlPathPattern)) + return false; + return (compareTo((UrlPathPattern)o) == 0); + } + + @Override /* Object */ + public int hashCode() { + return super.hashCode(); + } + + @Override /* Object */ + public String toString() { + return patternString; + } + + /** + * Returns this path pattern as the compiled regular expression. + * Useful for debugging. + * + * @return The path pattern. + */ + public String toRegEx() { + return isOnlyDotAll ? "*" : pattern.pattern(); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Attr.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Attr.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Attr.java new file mode 100755 index 0000000..6c1aed5 --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Attr.java @@ -0,0 +1,74 @@ +/*************************************************************************************************************************** + * 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.juneau.server.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +/** + * Annotation that can be applied to a parameter of a {@link RestMethod} annotated method + * to identify it as a variable in a URL path pattern converted to a POJO. + * + * <h6 class='topic'>Example</h6> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/myurl/{foo}/{bar}/{baz}/*"</js>) + * <jk>public void</jk> doGet(RestRequest req, RestResponse res, + * <ja>@Attr</ja> String foo, <ja>@Attr</ja> <jk>int</jk> bar, <ja>@Attr</ja> UUID baz) { + * ... + * } + * </p> + * <p> + * The <ja>@Attr</ja> annotation is optional if the parameters are specified immediately + * following the <code>RestRequest</code> and <code>RestResponse</code> parameters, + * and are specified in the same order as the variables in the URL path pattern. + * The following example is equivalent to the previous example. + * </p> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/myurl/{foo}/{bar}/{baz}/*"</js>) + * <jk>public void</jk> doGet(RestRequest req, RestResponse res, + * String foo, <jk>int</jk> bar, UUID baz) { + * ... + * } + * </p> + * <p> + * If the order of parameters is not the default order shown above, the + * attribute names must be specified (since parameter names are lost during compilation). + * The following example is equivalent to the previous example, except + * the parameter order has been switched, requiring the use of the <ja>@Attr</ja> + * annotations. + * <p> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/myurl/{foo}/{bar}/{baz}/*"</js>) + * <jk>public void</jk> doGet(RestRequest req, RestResponse res, + * <ja>@Attr</ja>(<js>"baz"</js>) UUID baz, <ja>@Attr</ja>(<js>"foo"</js>) String foo, <ja>@Attr</ja>(<js>"bar"</js>) <jk>int</jk> bar) { + * ... + * } + * </p> + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target(PARAMETER) +@Retention(RUNTIME) +@Inherited +public @interface Attr { + + /** + * URL variable name. + * <p> + * Optional if the attributes are specified in the same order as in the URL path pattern. + */ + String value() default ""; +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Content.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Content.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Content.java new file mode 100755 index 0000000..bdf3e65 --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Content.java @@ -0,0 +1,58 @@ +/*************************************************************************************************************************** + * 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.juneau.server.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.io.*; +import java.lang.annotation.*; + +/** + * Annotation that can be applied to a parameter of a {@link RestMethod} annotated method + * to identify it as the HTTP request body converted to a POJO. + * + * <h6 class='topic'>Example</h6> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"POST"</js>) + * <jk>public void</jk> doPostPerson(RestRequest req, RestResponse res, <ja>@Content</ja> Person person) { + * ... + * } + * </p> + * <p> + * This is functionally equivalent to the following code... + * </p> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"POST"</js>) + * <jk>public void</jk> doPostPerson(RestRequest req, RestResponse res) { + * Person person = req.getInput(Person.<jk>class</jk>); + * ... + * } + * </p> + * <p> + * {@link Reader Readers} and {@link InputStream InputStreams} can also be specified as content parameters. + * When specified, any registered parsers are bypassed. + * </p> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"POST"</js>) + * <jk>public void</jk> doPostPerson(<ja>@Header</ja> String mediaType, <ja>@Content</ja> InputStream input) { + * ... + * } + * </p> + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target(PARAMETER) +@Retention(RUNTIME) +@Inherited +public @interface Content {} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/HasParam.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/HasParam.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/HasParam.java new file mode 100755 index 0000000..06c44a6 --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/HasParam.java @@ -0,0 +1,95 @@ +/*************************************************************************************************************************** + * 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.juneau.server.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +import org.apache.juneau.server.*; + +/** + * Annotation that can be applied to a parameter of a {@link RestMethod} annotated method + * to identify whether or not the request has the specified GET or POST parameter. + * <p> + * Note that this can be used to detect the existence of a parameter when it's not set to a particular value. + * <h6 class='topic'>Example</h6> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>) + * <jk>public void</jk> doGet(<ja>@HasParam</ja>(<js>"p1"</js>) <jk>boolean</jk> p1) { + * ... + * } + * </p> + * <p> + * This is functionally equivalent to the following code... + * </p> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>) + * <jk>public void</jk> doGet(RestRequest req) { + * <jk>boolean</jk> p1 = req.hasParameter(<js>"p1"</js>); + * ... + * } + * </p> + * <p> + * The following table shows the behavioral differences between <code>@HasParam</code> and <code>@Param</code>... + * <table class='styled'> + * <tr> + * <th><code>URL</code></th> + * <th><code><ja>@HasParam</ja>(<js>"a"</js>)</code></th> + * <th><code><ja>@Param</ja>(<js>"a"</js>)</code></th> + * </tr> + * <tr> + * <td><code>?a=foo</code></td> + * <td><code><jk>true</jk></td> + * <td><code><js>"foo"</js></td> + * </tr> + * <tr> + * <td><code>?a=</code></td> + * <td><code><jk>true</jk></td> + * <td><code><js>""</js></td> + * </tr> + * <tr> + * <td><code>?a</code></td> + * <td><code><jk>true</jk></td> + * <td><code><jk>null</jk></td> + * </tr> + * <tr> + * <td><code>?b=foo</code></td> + * <td><code><jk>false</jk></td> + * <td><code><jk>null</jk></td> + * </tr> + * </table> + * + * <h6 class='topic'>Important note concerning FORM posts</h6> + * <p> + * This annotation should not be combined with the {@link Content @Content} annotation or {@link RestRequest#getInput(Class)} method + * for <code>application/x-www-form-urlencoded POST</code> posts, since it will trigger the underlying servlet API to parse the body + * content as key-value pairs, resulting in empty content. + * <p> + * The {@link HasQParam @HasQParam} annotation can be used to check for the existing of a URL parameter + * in the URL string without triggering the servlet to drain the body content. + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target(PARAMETER) +@Retention(RUNTIME) +@Inherited +public @interface HasParam { + + /** + * URL parameter name. + */ + String value(); +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/HasQParam.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/HasQParam.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/HasQParam.java new file mode 100755 index 0000000..a51a56b --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/HasQParam.java @@ -0,0 +1,61 @@ +/*************************************************************************************************************************** + * 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.juneau.server.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +import org.apache.juneau.server.*; + +/** + * Identical to {@link HasParam @HasParam}, but only checks the existing of the parameter in the + * URL string, not URL-encoded form posts. + * <p> + * Unlike {@link HasParam @HasParam}, using this annotation does not result in the servlet reading the contents + * of URL-encoded form posts. + * Therefore, this annotation can be used in conjunction with the {@link Content @Content} annotation + * or {@link RestRequest#getInput(Class)} method for <code>application/x-www-form-urlencoded POST</code> calls. + * + * <h6 class='topic'>Example</h6> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>) + * <jk>public void</jk> doPost(<ja>@HasQParam</ja>(<js>"p1"</js>) <jk>boolean</jk> p1, <ja>@Content</ja> Bean myBean) { + * ... + * } + * </p> + * <p> + * This is functionally equivalent to the following code... + * </p> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>) + * <jk>public void</jk> doGet(RestRequest req) { + * <jk>boolean</jk> p1 = req.hasQueryParameter(<js>"p1"</js>); + * ... + * } + * </p> + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target(PARAMETER) +@Retention(RUNTIME) +@Inherited +public @interface HasQParam { + + /** + * URL parameter name. + */ + String value(); +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Header.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Header.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Header.java new file mode 100755 index 0000000..b26674d --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Header.java @@ -0,0 +1,54 @@ +/*************************************************************************************************************************** + * 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.juneau.server.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +/** + * Annotation that can be applied to a parameter of a {@link RestMethod} annotated method + * to identify it as a HTTP request header converted to a POJO. + * + * <h6 class='topic'>Example</h6> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>) + * <jk>public void</jk> doGet(RestRequest req, RestResponse res, <ja>@Header</ja>(<js>"ETag"</js>) UUID etag) { + * ... + * } + * </p> + * <p> + * This is functionally equivalent to the following code... + * </p> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>) + * <jk>public void</jk> doPostPerson(RestRequest req, RestResponse res) { + * UUID etag = req.getHeader(UUID.<jk>class</jk>, "ETag"); + * ... + * } + * </p> + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target(PARAMETER) +@Retention(RUNTIME) +@Inherited +public @interface Header { + + /** + * HTTP header name. + */ + String value(); +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Inherit.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Inherit.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Inherit.java new file mode 100755 index 0000000..de0f6ac --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Inherit.java @@ -0,0 +1,34 @@ +/*************************************************************************************************************************** + * 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.juneau.server.annotation; + +/** + * Inheritance values for the {@link RestMethod#serializersInherit()} and {@link RestMethod#parsersInherit()} + * annotations. + * + * @author James Bognar (james.bog...@salesforce.com) + */ +public enum Inherit { + + /** Inherit serializers from parent. */ + SERIALIZERS, + + /** Inherit parsers from parent. */ + PARSERS, + + /** Inherit transforms from parent. */ + TRANSFORMS, + + /** Inherit properties from parent. */ + PROPERTIES +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Messages.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Messages.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Messages.java new file mode 100755 index 0000000..66cbc7f --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Messages.java @@ -0,0 +1,52 @@ +/*************************************************************************************************************************** + * 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.juneau.server.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; +import java.util.*; + +import org.apache.juneau.utils.*; + +/** + * Annotation that can be applied to a parameter of a {@link RestMethod} annotated method + * to identify it as the resource bundle for the request locale. + * <p> + * Parameter type must be either {@link ResourceBundle} or {@link MessageBundle}. + * + * <h6 class='topic'>Example</h6> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>) + * <jk>public</jk> String doGet(<ja>@Messages</ja> ResourceBundle messages) { + * <jk>return</jk> messages.getString(<js>"myLocalizedMessage"</js>); + * } + * </p> + * <p> + * This is functionally equivalent to the following code... + * </p> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>) + * <jk>public</jk> String doGet(RestRequest req) { + * <jk>return</jk> req.getMessage(<js>"myLocalizedMessage"</js>); + * } + * </p> + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target(PARAMETER) +@Retention(RUNTIME) +@Inherited +public @interface Messages {} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Method.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Method.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Method.java new file mode 100755 index 0000000..80acbb4 --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Method.java @@ -0,0 +1,51 @@ +/*************************************************************************************************************************** + * 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.juneau.server.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +/** + * Annotation that can be applied to a parameter of a {@link RestMethod} annotated method + * to identify it as the HTTP method. + * <p> + * Typically used for HTTP method handlers of type <js>"*"</js> (i.e. handle all requests). + * + * <h6 class='topic'>Example</h6> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"*"</js>) + * <jk>public void</jk> doAnything(RestRequest req, RestResponse res, <ja>@Method</ja> String method) { + * ... + * } + * </p> + * <p> + * This is functionally equivalent to the following code... + * </p> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"*"</js>) + * <jk>public void</jk> doAnything(RestRequest req, RestResponse res) { + * String method = req.getMethod(); + * ... + * } + * </p> + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target(PARAMETER) +@Retention(RUNTIME) +@Inherited +public @interface Method { +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Param.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Param.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Param.java new file mode 100755 index 0000000..d20f08c --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Param.java @@ -0,0 +1,98 @@ +/*************************************************************************************************************************** + * 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.juneau.server.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +import org.apache.juneau.server.*; + +/** + * Annotation that can be applied to a parameter of a {@link RestMethod} annotated method + * to identify it as a URL query parameter converted to a POJO. + * + * <h6 class='topic'>Example</h6> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>) + * <jk>public void</jk> doGet(RestRequest req, RestResponse res, + * <ja>@Param</ja>(<js>"p1"</js>) <jk>int</jk> p1, <ja>@Param</ja>(<js>"p2"</js>) String p2, <ja>@Param</ja>(<js>"p3"</js>) UUID p3) { + * ... + * } + * </p> + * <p> + * This is functionally equivalent to the following code... + * </p> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>) + * <jk>public void</jk> doGet(RestRequest req, RestResponse res) { + * <jk>int</jk> p1 = req.getParam(<jk>int</jk>.<jk>class</jk>, <js>"p1"</js>, 0); + * String p2 = req.getParam(String.<jk>class</jk>, <js>"p2"</js>); + * UUID p3 = req.getParam(UUID.<jk>class</jk>, <js>"p3"</js>); + * ... + * } + * </p> + * + * <h6 class='topic'>Important note concerning FORM posts</h6> + * <p> + * This annotation should not be combined with the {@link Content @Content} annotation or {@link RestRequest#getInput(Class)} method + * for <code>application/x-www-form-urlencoded POST</code> posts, since it will trigger the underlying servlet + * API to parse the body content as key-value pairs resulting in empty content. + * <p> + * The {@link QParam @QParam} annotation can be used to retrieve a URL parameter + * in the URL string without triggering the servlet to drain the body content. + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target(PARAMETER) +@Retention(RUNTIME) +@Inherited +public @interface Param { + + /** + * URL parameter name. + */ + String value(); + + /** + * Specify <jk>true</jk> if using multi-part parameters to represent collections and arrays. + * <p> + * Normally, we expect single parameters to be specified in UON notation for representing + * collections of values (e.g. <js>"&key=(1,2,3)"</js>. + * This annotation allows the use of multi-part parameters to represent collections + * (e.g. <js>"&key=1&key=2&key=3"</js>. + * <p> + * This setting should only be applied to Java parameters of type array or Collection. + */ + boolean multipart() default false; + + /** + * The expected format of the request parameter. + * <p> + * Possible values: + * <ul class='spaced-list'> + * <li><js>"UON"</js> - URL-Encoded Object Notation.<br> + * This notation allows for request parameters to contain arbitrarily complex POJOs. + * <li><js>"PLAIN"</js> - Plain text.<br> + * This treats request parameters as plain text.<br> + * Only POJOs directly convertable from <l>Strings</l> can be represented in parameters when using this mode. + * <li><js>"INHERIT"</js> (default) - Inherit from the {@link RestServletContext#REST_paramFormat} property on the servlet method or class. + * </ul> + * <p> + * Note that the parameter value <js>"(foo)"</js> is interpreted as <js>"(foo)"</js> when using plain mode, but + * <js>"foo"</js> when using UON mode. + */ + String format() default "INHERIT"; +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/PathRemainder.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/PathRemainder.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/PathRemainder.java new file mode 100755 index 0000000..b51ff6b --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/PathRemainder.java @@ -0,0 +1,48 @@ +/*************************************************************************************************************************** + * 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.juneau.server.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +/** + * Annotation that can be applied to a parameter of a {@link RestMethod} annotated method + * to identify it as the URL parameter remainder after a path pattern match. + * + * <h6 class='topic'>Example</h6> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/foo/*"</js>) + * <jk>public void</jk> doGet(RestRequest req, RestResponse res, <ja>@PathRemainder</ja> String remainder) { + * ... + * } + * </p> + * <p> + * This is functionally equivalent to the following code... + * </p> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/foo/*"</js>) + * <jk>public void</jk> doGet(RestRequest req, RestResponse res) { + * String remainder = req.getPathRemainder(); + * ... + * } + * </p> + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target(PARAMETER) +@Retention(RUNTIME) +@Inherited +public @interface PathRemainder {} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Properties.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Properties.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Properties.java new file mode 100755 index 0000000..5aba15e --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Properties.java @@ -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.juneau.server.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +import org.apache.juneau.*; + +/** + * Annotation that can be applied to a parameter of a {@link RestMethod} annotated method + * to identify the request-duration properties object for the current request. + * + * <h6 class='topic'>Example</h6> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>) + * <jk>public Person</jk> doGetPerson(<ja>@Properties</ja> ObjectMap properties) { + * properties.put(<jsf>HTMLDOC_title</jsf>, <js>"This is a person"</js>); + * ... + * } + * </p> + * <p> + * This is functionally equivalent to the following code... + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>) + * <jk>public Person</jk> doGetPerson(RestResponse res) { + * ObjectMap properties = res.getProperties(); + * properties.put(<jsf>HTMLDOC_title</jsf>, <js>"This is a person"</js>); + * ... + * } + * </p> + * <p> + * ...or this... + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>) + * <jk>public Person</jk> doGetPerson(RestResponse res) { + * res.setProperty(<jsf>HTMLDOC_title</jsf>, <js>"This is a person"</js>); + * ... + * } + * </p> + * <p> + * The parameter type can be one of the following: + * <ul> + * <li>{@link ObjectMap} + * <li><code>Map<String,Object></code> + * </ul> + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target(PARAMETER) +@Retention(RUNTIME) +@Inherited +public @interface Properties {} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Property.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Property.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Property.java new file mode 100755 index 0000000..c06675d --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/Property.java @@ -0,0 +1,65 @@ +/*************************************************************************************************************************** + * 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.juneau.server.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +import org.apache.juneau.*; +import org.apache.juneau.jena.*; +import org.apache.juneau.json.*; +import org.apache.juneau.parser.*; +import org.apache.juneau.serializer.*; +import org.apache.juneau.xml.*; + +/** + * Property name/value pair used in the {@link RestResource#properties()} annotation. + * <p> + * Any of the following property names can be specified: + * <ul> + * <li>{@link BeanContext} + * <li>{@link SerializerContext} + * <li>{@link ParserContext} + * <li>{@link JsonSerializerContext} + * <li>{@link RdfSerializerContext} + * <li>{@link RdfParserContext} + * <li>{@link RdfCommonContext} + * <li>{@link XmlSerializerContext} + * <li>{@link XmlParserContext} + * </ul> + * <p> + * Property values types that are not <code>Strings</code> will automatically be converted to the + * correct type (e.g. <code>Boolean</code>, etc...). + * <p> + * See {@link RestResource#properties} for more information. + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target(ANNOTATION_TYPE) +@Retention(RUNTIME) +@Inherited +public @interface Property { + + /** + * Property name. + */ + String name(); + + /** + * Property value. + */ + String value(); +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/1b4f98a0/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/QParam.java ---------------------------------------------------------------------- diff --git a/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/QParam.java b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/QParam.java new file mode 100755 index 0000000..0b13621 --- /dev/null +++ b/org.apache.juneau.server/src/main/java/org/apache/juneau/server/annotation/QParam.java @@ -0,0 +1,94 @@ +/*************************************************************************************************************************** + * 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.juneau.server.annotation; + +import static java.lang.annotation.ElementType.*; +import static java.lang.annotation.RetentionPolicy.*; + +import java.lang.annotation.*; + +import org.apache.juneau.server.*; + +/** + * Identical to {@link Param @Param}, but only retrieves the parameter from the + * URL string, not URL-encoded form posts. + * <p> + * Unlike {@link Param @Param}, using this annotation does not result in the servlet reading the contents + * of URL-encoded form posts. + * Therefore, this annotation can be used in conjunction with the {@link Content @Content} annotation + * or {@link RestRequest#getInput(Class)} method for <code>application/x-www-form-urlencoded POST</code> calls. + * + * <h6 class='topic'>Example</h6> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>) + * <jk>public void</jk> doGet(RestRequest req, RestResponse res, + * <ja>@QParam</ja>(<js>"p1"</js>) <jk>int</jk> p1, <ja>@QParam</ja>(<js>"p2"</js>) String p2, <ja>@QParam</ja>(<js>"p3"</js>) UUID p3) { + * ... + * } + * </p> + * <p> + * This is functionally equivalent to the following code... + * </p> + * <p class='bcode'> + * <ja>@RestMethod</ja>(name=<js>"GET"</js>) + * <jk>public void</jk> doGet(RestRequest req, RestResponse res) { + * <jk>int</jk> p1 = req.getQueryParameter(<jk>int</jk>.<jk>class</jk>, <js>"p1"</js>, 0); + * String p2 = req.getQueryParameter(String.<jk>class</jk>, <js>"p2"</js>); + * UUID p3 = req.getQueryParameter(UUID.<jk>class</jk>, <js>"p3"</js>); + * ... + * } + * </p> + * + * @author James Bognar (james.bog...@salesforce.com) + */ +@Documented +@Target(PARAMETER) +@Retention(RUNTIME) +@Inherited +public @interface QParam { + + /** + * URL parameter name. + */ + String value(); + + /** + * Specify <jk>true</jk> if using multi-part parameters to represent collections and arrays. + * <p> + * Normally, we expect single parameters to be specified in UON notation for representing + * collections of values (e.g. <js>"&key=(1,2,3)"</js>. + * This annotation allows the use of multi-part parameters to represent collections + * (e.g. <js>"&key=1&key=2&key=3"</js>. + * <p> + * This setting should only be applied to Java parameters of type array or Collection. + */ + boolean multipart() default false; + + /** + * The expected format of the request parameter. + * <p> + * Possible values: + * <ul class='spaced-list'> + * <li><js>"UON"</js> - URL-Encoded Object Notation.<br> + * This notation allows for request parameters to contain arbitrarily complex POJOs. + * <li><js>"PLAIN"</js> - Plain text.<br> + * This treats request parameters as plain text.<br> + * Only POJOs directly convertable from <l>Strings</l> can be represented in parameters when using this mode. + * <li><js>"INHERIT"</js> (default) - Inherit from the {@link RestServletContext#REST_paramFormat} property on the servlet method or class. + * </ul> + * <p> + * Note that the parameter value <js>"(foo)"</js> is interpreted as <js>"(foo)"</js> when using plain mode, but + * <js>"foo"</js> when using UON mode. + */ + String format() default "INHERIT"; +}