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&lt;String,Object&gt;</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";
+}

Reply via email to