You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2016/08/01 17:30:15 UTC
[26/53] [partial] incubator-juneau git commit: Merge changes from
GitHub repo.
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.bognar@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.bognar@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.bognar@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.bognar@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.bognar@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.bognar@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.bognar@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.bognar@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.bognar@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.bognar@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.bognar@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.bognar@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.bognar@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.bognar@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.bognar@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.bognar@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.bognar@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.bognar@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.bognar@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.bognar@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";
+}