http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/UrlContentTest.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/UrlContentTest.java
 
b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/UrlContentTest.java
new file mode 100644
index 0000000..a4424b4
--- /dev/null
+++ 
b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/UrlContentTest.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.rest.test;
+
+import static org.junit.Assert.*;
+
+import org.apache.juneau.rest.client.*;
+import org.junit.*;
+
+public class UrlContentTest {
+
+       private static String URL = "/testUrlContent";
+       private static RestClient client;
+
+       @BeforeClass
+       public static void beforeClass() {
+               client = new TestRestClient().setHeader("Accept", "text/plain");
+       }
+
+       @AfterClass
+       public static void afterClass() {
+               client.closeQuietly();
+       }
+
+       
//====================================================================================================
+       // Test URL &Body parameter containing a String
+       
//====================================================================================================
+       @Test
+       public void testString() throws Exception {
+               String r;
+               r = client.doGet(URL + 
"/testString?body=\'xxx\'&Content-Type=text/json").getResponseAsString();
+               assertEquals("class=java.lang.String, value=xxx", r);
+       }
+
+       
//====================================================================================================
+       // Test URL &Body parameter containing an Enum
+       
//====================================================================================================
+       @Test
+       public void testEnum() throws Exception {
+               String r;
+               r = client.doGet(URL + 
"/testEnum?body='X1'&Content-Type=text/json").getResponseAsString();
+               
assertEquals("class=org.apache.juneau.rest.test.UrlContentResource$TestEnum, 
value=X1", r);
+       }
+
+       
//====================================================================================================
+       // Test URL &Body parameter containing a Bean
+       
//====================================================================================================
+       @Test
+       public void testBean() throws Exception {
+               String r;
+               r = client.doGet(URL + 
"/testBean?body=%7Bf1:1,f2:'foobar'%7D&Content-Type=text/json").getResponseAsString();
+               
assertEquals("class=org.apache.juneau.rest.test.UrlContentResource$TestBean, 
value={f1:1,f2:'foobar'}", r);
+       }
+
+       
//====================================================================================================
+       // Test URL &Body parameter containing an int
+       
//====================================================================================================
+       @Test
+       public void testInt() throws Exception {
+               String r;
+               r = client.doGet(URL + 
"/testInt?body=123&Content-Type=text/json").getResponseAsString();
+               assertEquals("class=java.lang.Integer, value=123", r);
+       }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/UrlPathPatternTest.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/UrlPathPatternTest.java
 
b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/UrlPathPatternTest.java
new file mode 100644
index 0000000..c122074
--- /dev/null
+++ 
b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/UrlPathPatternTest.java
@@ -0,0 +1,40 @@
+// 
***************************************************************************************************************************
+// * 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.rest.test;
+
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.apache.juneau.json.*;
+import org.apache.juneau.rest.*;
+import org.junit.*;
+
+public class UrlPathPatternTest {
+       @Test
+       public void testComparison() throws Exception {
+               List<UrlPathPattern> l = new LinkedList<UrlPathPattern>();
+
+               l.add(new UrlPathPattern("/foo"));
+               l.add(new UrlPathPattern("/foo/*"));
+               l.add(new UrlPathPattern("/foo/bar"));
+               l.add(new UrlPathPattern("/foo/bar/*"));
+               l.add(new UrlPathPattern("/foo/{id}"));
+               l.add(new UrlPathPattern("/foo/{id}/*"));
+               l.add(new UrlPathPattern("/foo/{id}/bar"));
+               l.add(new UrlPathPattern("/foo/{id}/bar/*"));
+
+               Collections.sort(l);
+               
assertEquals("['/foo/bar','/foo/bar/*','/foo/{id}/bar','/foo/{id}/bar/*','/foo/{id}','/foo/{id}/*','/foo','/foo/*']",
 JsonSerializer.DEFAULT_LAX.serialize(l));
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/_TestSuite.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/_TestSuite.java 
b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/_TestSuite.java
new file mode 100644
index 0000000..43f1b6e
--- /dev/null
+++ b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/_TestSuite.java
@@ -0,0 +1,92 @@
+// 
***************************************************************************************************************************
+// * 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.rest.test;
+
+import java.util.*;
+
+import org.apache.juneau.microservice.*;
+import org.junit.*;
+import org.junit.runner.*;
+import org.junit.runners.*;
+import org.junit.runners.Suite.*;
+
+/**
+ * Runs all the testcases in this project.
+ * Starts a REST service running org.apache.juneau.rest.test.Root on port 
10001.
+ * Stops the REST service after running the tests.
+ */
+@RunWith(Suite.class)
+@SuiteClasses({
+       AcceptCharsetTest.class,
+       BeanContextPropertiesTest.class,
+       CallbackStringsTest.class,
+       CharsetEncodingsTest.class,
+       ClientVersionTest.class,
+       ConfigTest.class,
+       ContentTest.class,
+       DefaultContentTypesTest.class,
+       ErrorConditionsTest.class,
+       GroupsTest.class,
+       GzipTest.class,
+       InheritanceTest.class,
+       JacocoDummyTest.class,
+       LargePojosTest.class,
+       MessagesTest.class,
+       NlsPropertyTest.class,
+       NlsTest.class,
+       NoParserInputTest.class,
+       OnPostCallTest.class,
+       OnPreCallTest.class,
+       OptionsWithoutNlsTest.class,
+       OverlappingMethodsTest.class,
+       ParamsTest.class,
+       ParsersTest.class,
+       PathsTest.class,
+       PathTest.class,
+       PropertiesTest.class,
+       RestClientTest.class,
+       RestUtilsTest.class,
+       SerializersTest.class,
+       StaticFilesTest.class,
+       TransformsTest.class,
+       UrisTest.class,
+       UrlContentTest.class,
+       UrlPathPatternTest.class
+})
+public class _TestSuite {
+       static Microservice microservice;
+
+       @BeforeClass
+       public static void setUp() {
+               try {
+                       Locale.setDefault(Locale.US);
+                       microservice = new RestMicroservice()
+                               .setConfig("juneau-rest-test.cfg", false)
+                               .setManifestContents(
+                                       "Test-Entry: test-value"
+                               );
+                       microservice.start();
+               } catch (Exception e) {
+                       throw new RuntimeException(e);
+               }
+       }
+
+       @AfterClass
+       public static void tearDown() {
+               try {
+                       microservice.stop();
+               } catch (Exception e) {
+                       throw new RuntimeException(e);
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/.gitignore
----------------------------------------------------------------------
diff --git a/juneau-rest/.gitignore b/juneau-rest/.gitignore
new file mode 100644
index 0000000..b5ffa7e
--- /dev/null
+++ b/juneau-rest/.gitignore
@@ -0,0 +1,3 @@
+/target/
+/.settings/
+/.classpath

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/.project
----------------------------------------------------------------------
diff --git a/juneau-rest/.project b/juneau-rest/.project
new file mode 100644
index 0000000..b6551cc
--- /dev/null
+++ b/juneau-rest/.project
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 
***************************************************************************************************************************
+ * 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.  
                                            *
+ 
***************************************************************************************************************************
+-->
+<projectDescription>
+  <name>juneau-rest</name>
+  <comment>REST servlet API. NO_M2ECLIPSE_SUPPORT: Project files created with 
the maven-eclipse-plugin are not supported in M2Eclipse.</comment>
+  <projects>
+    <project>juneau-core</project>
+  </projects>
+  <buildSpec>
+    <buildCommand>
+      <name>org.eclipse.jdt.core.javabuilder</name>
+    </buildCommand>
+  </buildSpec>
+  <natures>
+    <nature>org.eclipse.jdt.core.javanature</nature>
+  </natures>
+</projectDescription>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/pom.xml
----------------------------------------------------------------------
diff --git a/juneau-rest/pom.xml b/juneau-rest/pom.xml
new file mode 100644
index 0000000..6a07bb1
--- /dev/null
+++ b/juneau-rest/pom.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 
***************************************************************************************************************************
+ * 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.  
                                            *
+ 
***************************************************************************************************************************
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+       
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>juneau-rest</artifactId>
+       <name>Apache Juneau REST Server</name>
+       <description>REST servlet API</description>
+       <packaging>bundle</packaging>
+
+       <parent>
+               <groupId>org.apache.juneau</groupId>
+               <artifactId>juneau</artifactId>
+               <version>6.0.2-incubating-SNAPSHOT</version>
+               <relativePath>../pom.xml</relativePath>
+       </parent>
+
+       <dependencies>
+               <dependency>
+                       <groupId>org.apache.juneau</groupId>
+                       <artifactId>juneau-core</artifactId>
+                       <version>${project.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>javax.ws.rs</groupId>
+                       <artifactId>jsr311-api</artifactId>
+                       <optional>true</optional>
+               </dependency>
+               <dependency>
+                       <groupId>javax.servlet</groupId>
+                       <artifactId>javax.servlet-api</artifactId>
+               </dependency>
+       </dependencies>
+       
+       <properties>
+               <!-- Skip javadoc generation since we generate them in the 
aggregate pom -->
+               <maven.javadoc.skip>true</maven.javadoc.skip>
+       </properties>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-source-plugin</artifactId>
+                               <version>3.0.1</version>
+                               <executions>
+                                       <execution>
+                                               <id>attach-sources</id>
+                                               <phase>verify</phase>
+                                               <goals>
+                                                       <goal>jar-no-fork</goal>
+                                               </goals>
+                                       </execution>
+                               </executions>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <version>3.2.0</version>
+                               <extensions>true</extensions>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-surefire-plugin</artifactId>
+                               <version>2.19.1</version>
+                               <configuration>
+                                       <includes>
+                                               
<include>**/*Test.class</include>
+                                       </includes>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/ClientVersionMatcher.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest/src/main/java/org/apache/juneau/rest/ClientVersionMatcher.java 
b/juneau-rest/src/main/java/org/apache/juneau/rest/ClientVersionMatcher.java
new file mode 100644
index 0000000..4f65615
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/ClientVersionMatcher.java
@@ -0,0 +1,50 @@
+// 
***************************************************************************************************************************
+// * 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.rest;
+
+import org.apache.juneau.internal.*;
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Specialized matcher for matching client versions.
+ * <p>
+ * See {@link RestResource#clientVersionHeader} and {@link 
RestMethod#clientVersion} for more info.
+ */
+public class ClientVersionMatcher extends RestMatcherReflecting {
+
+       private final String clientVersionHeader;
+       private final VersionRange range;
+
+       /**
+        * Constructor.
+        *
+        * @param servlet The servlet.
+        * @param javaMethod The version string that the client version must 
match.
+        */
+       protected ClientVersionMatcher(RestServlet servlet, 
java.lang.reflect.Method javaMethod) {
+               super(servlet, javaMethod);
+               this.clientVersionHeader = servlet.getClientVersionHeader();
+               RestMethod m = javaMethod.getAnnotation(RestMethod.class);
+               range = new VersionRange(m.clientVersion());
+       }
+
+       @Override /* RestMatcher */
+       public boolean matches(RestRequest req) {
+               return range.matches(req.getHeader(clientVersionHeader));
+       }
+
+       @Override /* RestMatcher */
+       public boolean mustMatch() {
+               return true;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/ReaderResource.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest/src/main/java/org/apache/juneau/rest/ReaderResource.java 
b/juneau-rest/src/main/java/org/apache/juneau/rest/ReaderResource.java
new file mode 100644
index 0000000..193c1ce
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/ReaderResource.java
@@ -0,0 +1,99 @@
+// 
***************************************************************************************************************************
+// * 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.rest;
+
+import java.io.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.response.*;
+import org.apache.juneau.svl.*;
+
+/**
+ * Represents the contents of a text file with convenience methods for 
resolving
+ *     {@link Parameter} variables and adding HTTP response headers.
+ * <p>
+ * This class is handled special by the {@link WritableHandler} class.
+ */
+public class ReaderResource implements Writable {
+
+       private String contents;
+       private String mediaType;
+       private VarResolverSession varSession;
+       private Map<String,String> headers = new LinkedHashMap<String,String>();
+
+       /**
+        * Constructor.
+        *
+        * @param contents The contents of this resource.
+        * @param mediaType The HTTP media type.
+        */
+       protected ReaderResource(String contents, String mediaType) {
+               this.contents = contents;
+               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 ReaderResource setHeader(String name, Object value) {
+               headers.put(name, value == null ? "" : value.toString());
+               return this;
+       }
+
+       /**
+        * Use the specified {@link VarResolver} to resolve any {@link 
Parameter StringVars} in the
+        * contents of this file when the {@link #writeTo(Writer)} or {@link 
#toString()} methods are called.
+        *
+        * @param varSession The string variable resolver to use to resolve 
string variables.
+        * @return This object (for method chaining).
+        */
+       public ReaderResource setVarSession(VarResolverSession varSession) {
+               this.varSession = varSession;
+               return this;
+       }
+
+       /**
+        * Get the HTTP response headers.
+        *
+        * @return The HTTP response headers.
+        */
+       public Map<String,String> getHeaders() {
+               return headers;
+       }
+
+       @Override /* Writeable */
+       public void writeTo(Writer w) throws IOException {
+               if (varSession != null)
+                       varSession.resolveTo(contents, w);
+               else
+                       w.write(contents);
+       }
+
+       @Override /* Streamable */
+       public String getMediaType() {
+               return mediaType;
+       }
+
+       @Override /* Object */
+       public String toString() {
+               if (varSession != null)
+                       return varSession.resolve(contents);
+               return contents;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/Redirect.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/Redirect.java 
b/juneau-rest/src/main/java/org/apache/juneau/rest/Redirect.java
new file mode 100644
index 0000000..ab3923f
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/Redirect.java
@@ -0,0 +1,138 @@
+// 
***************************************************************************************************************************
+// * 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.rest;
+
+import java.net.*;
+import java.text.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.urlencoding.*;
+
+/**
+ * REST methods can return this object as a shortcut for performing <code>HTTP 
302</code> redirects.
+ * <p>
+ * The following example shows the difference between handling redirects via 
the {@link RestRequest}/{@link RestResponse},
+ *     and the simplified approach of using this class.
+ * <p class='bcode'>
+ *     <jc>// Redirect to "/contextPath/servletPath/foobar"</jc>
+ *
+ *     <jc>// Using RestRequest and RestResponse</jc>
+ *     <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/example1"</js>)
+ *     <jk>public void</jk> example1(RestRequest req, RestResponse res) 
<jk>throws</jk> IOException {
+ *             res.sendRedirect(req.getServletURI() + <js>"/foobar"</js>);
+ *     }
+ *
+ *     <jc>// Using Redirect</jc>
+ *     <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/example2"</js>)
+ *     <jk>public</jk> Redirect example2() {
+ *             <jk>return new</jk> Redirect(<js>"foobar"</js>);
+ *     }
+ * </p>
+ * <p>
+ * The constructor can use a {@link MessageFormat}-style pattern with multiple 
arguments:
+ * <p class='bcode'>
+ *     <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/example3"</js>)
+ *     <jk>public</jk> Redirect example3() {
+ *             <jk>return new</jk> Redirect(<js>"foo/{0}/bar/{1}"</js>, id1, 
id2);
+ *     }
+ * </p>
+ * <p>
+ * The arguments are serialized to strings using the servlet's {@link 
UrlEncodingSerializer},
+ *     so any filters defined on the serializer or REST method/class will be 
used when present.
+ * The arguments will also be automatically URL-encoded.
+ * <p>
+ * Redirecting to the servlet root can be accomplished by simply using the 
no-arg constructor.
+ * <p class='bcode'>
+ *     <jc>// Simply redirect to the servlet root.
+ *     // Equivalent to res.sendRedirect(req.getServletURI()).</jc>
+ *     <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/example4"</js>)
+ *     <jk>public</jk> Redirect exmaple4() {
+ *             <jk>return new</jk> Redirect();
+ *     }
+ * </p>
+ * <p>
+ * This class is handled by {@link 
org.apache.juneau.rest.response.RedirectHandler}, a built-in default
+ *     response handler created by {@link 
RestServlet#createResponseHandlers(ObjectMap)}.
+ */
+public final class Redirect {
+
+       private int httpResponseCode;
+       private String url;
+       private Object[] args;
+
+       /**
+        * Redirect to the specified URL.
+        * Relative paths are interpreted as relative to the servlet path.
+        *
+        * @param url The URL to redirect to.
+        * @param args Optional {@link MessageFormat} arguments to replace in 
the URL string.
+        */
+       public Redirect(CharSequence url, Object...args) {
+               this.url = (url == null ? null : url.toString());
+               this.args = args;
+       }
+
+       /**
+        * Convenience method for redirecting to instance of {@link URL} and 
{@link URI}.
+        * Same as calling <code>toString()</code> on the object and using the 
other constructor.
+        *
+        * @param url The URL to redirect to.
+        */
+       public Redirect(Object url) {
+               this.url = (url == null ? null : url.toString());
+       }
+
+       /**
+        * Redirect to the specified URL.
+        * Relative paths are interpreted as relative to the servlet path.
+        *
+        * @param httpResponseCode The HTTP response code.
+        * @param url The URL to redirect to.
+        * @param args Optional {@link MessageFormat} arguments to replace in 
the URL string.
+        */
+       public Redirect(int httpResponseCode, CharSequence url, Object...args) {
+               this.httpResponseCode = httpResponseCode;
+               this.url = (url == null ? null : url.toString());
+               this.args = args;
+       }
+
+       /**
+        * Shortcut for redirecting to the servlet root.
+        */
+       public Redirect() {
+       }
+
+       /**
+        * Calculates the URL to redirect to.
+        *
+        * @param s Use this serializer to encode arguments using the {@link 
UrlEncodingSerializer#serializeUrlPart(Object)} method.
+        * @return The URL to redirect to.
+        */
+       public String toUrl(UrlEncodingSerializer s) {
+               if (url != null && args != null && args.length > 0) {
+                       for (int i = 0; i < args.length; i++)
+                               args[i] = s.serializeUrlPart(args[i]);
+                       url = MessageFormat.format(url, args);
+               }
+               return url;
+       }
+
+       /**
+        * Returns the response code passed in through the constructor.
+        *
+        * @return The response code passed in through the constructor, or 
<code>0</code> if response code wasn't specified.
+        */
+       public int getHttpResponseCode() {
+               return httpResponseCode;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/ResponseHandler.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest/src/main/java/org/apache/juneau/rest/ResponseHandler.java 
b/juneau-rest/src/main/java/org/apache/juneau/rest/ResponseHandler.java
new file mode 100644
index 0000000..8144782
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/ResponseHandler.java
@@ -0,0 +1,92 @@
+// 
***************************************************************************************************************************
+// * 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.rest;
+
+import java.io.*;
+
+import javax.servlet.http.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.response.*;
+
+/**
+ * Defines the interface for handlers that convert POJOs to appropriate HTTP 
responses.
+ * <p>
+ * The {@link RestServlet} API uses the concept of registered response 
handlers for
+ *     converting objects returned by REST methods or set through {@link 
RestResponse#setOutput(Object)}
+ *     into appropriate HTTP responses.
+ * <p>
+ * Response handlers can be associated with {@link RestServlet RestServlets} 
through the following ways:
+ * <ul class='spaced-list'>
+ *     <li>Through the {@link RestResource#responseHandlers 
@RestResource.responseHandlers} annotation.
+ *     <li>By overriding {@link RestServlet#createResponseHandlers(ObjectMap)} 
and augmenting or creating your
+ *             own list of handlers.
+ * </ul>
+ * <p>
+ * By default, {@link RestServlet RestServlets} are registered with the 
following response handlers:
+ * <ul class='spaced-list'>
+ *     <li>{@link DefaultHandler} - Serializes POJOs using the Juneau 
serializer API.
+ *     <li>{@link ReaderHandler} - Pipes the output of {@link Reader Readers} 
to the response writer ({@link RestResponse#getWriter()}).
+ *     <li>{@link InputStreamHandler} - Pipes the output of {@link InputStream 
InputStreams} to the response output stream ({@link 
RestResponse#getOutputStream()}).
+ *     <li>{@link RedirectHandler} - Handles {@link Redirect} objects.
+ * </ul>
+ * <p>
+ * Response handlers can be used to process POJOs that cannot normally be 
handled through Juneau serializers, or
+ *     because it's simply easier to define response handlers for special 
cases.
+ * <p>
+ * The following example shows how to create a response handler to handle 
special <code>Foo</code> objects outside the normal
+ *     Juneau architecture.
+ * <p class='bcode'>
+ *     <ja>@RestResource</ja>(
+ *             path=<js>"/example"</js>,
+ *             responseHandlers=FooHandler.<jk>class</jk>
+ *     )
+ *     <jk>public class</jk> Example <jk>extends</jk> RestServlet {
+ *
+ *             <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/"</js>)
+ *             <jk>public</jk> Foo test1() {
+ *                     <jk>return new</jk> Foo(<js>"123"</js>);
+ *             }
+ *
+ *             <jk>public static class</jk> FooHandler <jk>implements</jk> 
ResponseHandler {
+ *                     <ja>@Override</ja>
+ *                     <jk>public boolean</jk> handle(RestRequest req, 
RestResponse res, Object output) <jk>throws</jk> IOException, RestException {
+ *                             <jk>if</jk> (output <jk>instanceof</jk> Foo) {
+ *                                     Foo foo = (Foo)output;
+ *                                     <jc>// Set some headers and body 
content.</jc>
+ *                                     res.setHeader(<js>"Foo-ID"</js>, 
foo.getId());
+ *                                     
res.getWriter().write(<js>"foo.id="</js> + foo.getId());
+ *                                     <jk>return true</jk>;  <jc>// We 
handled it.</jc>
+ *                             }
+ *                             <jk>return false</jk>;  <jc>// We didn't handle 
it.</jc>
+ *                     }
+ *             }
+ *     }
+ * </p>
+ */
+public interface ResponseHandler {
+
+       /**
+        * Process this response if possible.
+        * This method should return <jk>false</jk> if it wasn't able to 
process the response.
+        *
+        * @param req The HTTP servlet request.
+        * @param res The HTTP servlet response;
+        * @param output The POJO returned by the REST method that now needs to 
be sent to the response.
+        * @return true If this handler handled the response.
+        * @throws IOException - If low-level exception occurred on output 
stream.  Results in a {@link HttpServletResponse#SC_INTERNAL_SERVER_ERROR} 
error.
+        * @throws RestException - If some other exception occurred.  Can be 
used to provide an appropriate HTTP response code and message.
+        */
+       boolean handle(RestRequest req, RestResponse res, Object output) throws 
IOException, RestException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/RestConverter.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest/src/main/java/org/apache/juneau/rest/RestConverter.java 
b/juneau-rest/src/main/java/org/apache/juneau/rest/RestConverter.java
new file mode 100644
index 0000000..9c3e378
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestConverter.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.rest;
+
+import org.apache.juneau.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.converters.*;
+import org.apache.juneau.serializer.*;
+
+/**
+ * REST method response converter.
+ * <p>
+ *     Implements a filter mechanism for REST method calls that allows 
response objects to be
+ *     converted to some other POJO after invocation of the REST method.
+ * <p>
+ *     Converters are associated with REST methods through the {@link 
RestMethod#converters()} annotation.
+ * <h6 class='topic'>Example:</h6>
+ * <p class='bcode'>
+ *     <jk>public class</jk> RequestEchoResource <jk>extends</jk> RestServlet {
+ *
+ *             <jc>// GET request handler</jc>
+ *             <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/*"</js>, 
converters={Queryable.<jk>class</jk>,Traversable.<jk>class</jk>})
+ *             <jk>public</jk> HttpServletRequest doGet(RestRequest req) {
+ *                     res.setTitle(<js>"Contents of HttpServletRequest 
object"</js>);
+ *                     <jk>return</jk> req;
+ *             }
+ *     }
+ * </p>
+ * <p>
+ *     Converters can also be associated at the servlet level using the {@link 
RestResource#converters()} annotation.
+ *     Applying converters at the resource level is equivalent to applying 
converters to each resource method individually.
+ *
+ * <h6 class='topic'>How to implement</h6>
+ * <p>
+ *     Implementers should simply implement the {@link #convert(RestRequest, 
Object, ClassMeta)} and
+ *             return back a 'converted' object.
+ *     It's up to the implementer to decide what this means.
+ * <p>
+ *     Converters must implement a no-args constructor.
+ *
+ * <h6 class='topic'>Predefined converters</h6>
+ * <p>
+ *     The following converters are available by default.
+ * <ul class='spaced-list'>
+ *     <li>{@link Traversable} - Allows URL additional path info to address 
individual elements in a POJO tree.
+ *     <li>{@link Queryable} - Allows query/view/sort functions to be 
performed on POJOs.
+ *     <li>{@link Introspectable} - Allows Java public methods to be invoked 
on the returned POJOs.
+ * </ul>
+ */
+public interface RestConverter {
+
+       /**
+        * Performs post-call conversion on the specified response object.
+        *
+        * @param req The servlet request.
+        * @param res The response object set by the REST method through the 
{@link RestResponse#setOutput(Object)} method.
+        * @param cm The {@link ClassMeta} on the object from the bean context 
of the servlet.
+        *      Can be used to check if the object has any filters.
+        * @return The converted object.
+        * @throws RestException Thrown if any errors occur during conversion.
+        * @throws SerializeException
+        */
+       public Object convert(RestRequest req, Object res, ClassMeta<?> cm) 
throws RestException, SerializeException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/RestException.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest/src/main/java/org/apache/juneau/rest/RestException.java 
b/juneau-rest/src/main/java/org/apache/juneau/rest/RestException.java
new file mode 100644
index 0000000..2f510bb
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestException.java
@@ -0,0 +1,135 @@
+// 
***************************************************************************************************************************
+// * 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.rest;
+
+import java.text.*;
+
+/**
+ * Exception thrown to trigger an error HTTP status.
+ * <p>
+ *     REST methods on subclasses of {@link RestServlet} can throw
+ *     this exception to trigger an HTTP status other than the 
automatically-generated
+ *     <code>404</code>, <code>405</code>, and <code>500</code> statuses.
+ */
+public class RestException extends RuntimeException {
+
+       private static final long serialVersionUID = 1L;
+
+       private int status;
+       private int occurrence;
+
+       /**
+        * Constructor.
+        *
+        * @param status The HTTP status code.
+        * @param msg The status message.
+        * @param args Optional string format arguments.
+        */
+       public RestException(int status, String msg, Object...args) {
+               super(args.length == 0 ? msg : MessageFormat.format(msg, args));
+               this.status = status;
+       }
+
+       /**
+        * Constructor.
+        *
+        * @param status The HTTP status code.
+        * @param cause The root exception.
+        */
+       public RestException(int status, Throwable cause) {
+               this(status, cause.getLocalizedMessage());
+               initCause(cause);
+       }
+
+
+       /**
+        * Sets the inner cause for this exception.
+        *
+        * @param cause The inner cause.
+        * @return This object (for method chaining).
+        */
+       @Override /* Throwable */
+       public synchronized RestException initCause(Throwable cause) {
+               super.initCause(cause);
+               return this;
+       }
+
+
+       /**
+        * Returns all error messages from all errors in this stack.
+        * <p>
+        * Typically useful if you want to render all the error messages in the 
stack, but don't
+        * want to render all the stack traces too.
+        *
+        * @param scrubForXssVulnerabilities If <jk>true</jk>, replaces 
<js>'&lt;'</js>, <js>'&gt;'</js>, and <js>'&amp;'</js> characters with spaces.
+        * @return All error messages from all errors in this stack.
+        */
+       public String getFullStackMessage(boolean scrubForXssVulnerabilities) {
+               String msg = getMessage();
+               StringBuilder sb = new StringBuilder();
+               if (msg != null) {
+                       if (scrubForXssVulnerabilities)
+                               msg = msg.replace('<', ' ').replace('>', ' 
').replace('&', ' ');
+                       sb.append(msg);
+               }
+               Throwable e = getCause();
+               while (e != null) {
+                       msg = e.getMessage();
+                       if (msg != null && scrubForXssVulnerabilities)
+                               msg = msg.replace('<', ' ').replace('>', ' 
').replace('&', ' ');
+                       String cls = e.getClass().getSimpleName();
+                       if (msg == null)
+                               sb.append(MessageFormat.format("\nCaused by 
({0})", cls));
+                       else
+                               sb.append(MessageFormat.format("\nCaused by 
({0}): {1}", cls, msg));
+                       e = e.getCause();
+               }
+               return sb.toString();
+       }
+
+       @Override /* Object */
+       public int hashCode() {
+               int i = 0;
+               Throwable t = this;
+               while (t != null) {
+                       for (StackTraceElement e : t.getStackTrace())
+                       i ^= e.hashCode();
+                       t = t.getCause();
+               }
+               return i;
+       }
+
+       void setOccurrence(int occurrence) {
+               this.occurrence = occurrence;
+       }
+
+       /**
+        * Returns the number of times this exception occurred on this servlet.
+        * <p>
+        * This only gets set if {@link 
RestServletContext#REST_useStackTraceHashes} is enabled on the servlet.
+        *
+        * @return The occurrence number if {@link 
RestServletContext#REST_useStackTraceHashes} is enabled, or <code>0</code> 
otherwise.
+        */
+       public int getOccurrence() {
+               return occurrence;
+       }
+
+       /**
+        * Returns the HTTP status code.
+        *
+        * @return The HTTP status code.
+        */
+       public int getStatus() {
+               return status;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/RestGuard.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestGuard.java 
b/juneau-rest/src/main/java/org/apache/juneau/rest/RestGuard.java
new file mode 100644
index 0000000..82db0ca
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestGuard.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.rest;
+
+import static javax.servlet.http.HttpServletResponse.*;
+
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * REST method guard.
+ *
+ * <h6 class='topic'>Description</h6>
+ * <p>
+ *     Implements a guard mechanism for REST method calls that allows requests 
to be
+ *             rejected before invocation of the REST method.
+ *     For example, guards can be used to ensure that only administrators can 
call certain methods.
+ * <p>
+ *     Guards are applied to REST methods declaratively through the {@link 
RestResource#guards()} or {@link RestMethod#guards()} annotations.
+ * <p>
+ *     If multiple guards are specified, ALL guards must pass in order for the 
request to proceed.
+ *
+ * <h6 class='topic'>How to implement</h6>
+ * <p>
+ *     Typically, guards will be used for permissions checking on the user 
making the request,
+ *             but it can also be used for other purposes like pre-call 
validation of a request.
+ * <p>
+ *     Implementers should simply throw a {@link RestException} from the 
{@link #guard(RestRequest, RestResponse)}
+ *             method to abort processing on the current request.
+ * <p>
+ *     Guards must implement a no-args constructor.
+ *
+ * <h6 class='topic'>Example usage:</h6>
+ * <p class='bcode'>
+ *     <jk>public</jk> MyResource <jk>extends</jk> RestServlet {
+ *
+ *             <jc>// Delete method with guard that only allows Billy to call 
it.</jc>
+ *             <ja>@RestMethod</ja>(name=<js>"DELETE"</js>, 
guards=BillyGuard.<jk>class</jk>)
+ *             <jk>public</jk> doDelete(RestRequest req, RestResponse res) 
<jk>throws</jk> Exception {...}
+ *     }
+ * </p>
+ *
+ * <h6 class='topic'>Example implementation:</h6>
+ * <p class='bcode'>
+ *     <jc>// Define a guard that only lets Billy make a request</jc>
+ *     <jk>public</jk> BillyGuard <jk>extends</jk> RestGuard {
+ *
+ *             <ja>@Override</ja>
+ *             <jk>public boolean</jk> isRequestAllowed(RestRequest req) {
+ *                     return 
req.getUserPrincipal().getName().contains(<js>"Billy"</js>);
+ *             }
+ *     }
+ * </p>
+ */
+public abstract class RestGuard {
+
+       /**
+        * Checks the current HTTP request and throws a {@link RestException} 
if the guard
+        *      does not permit the request.
+        * <p>
+        *      By default, throws an <jsf>SC_FORBIDDEN</jsf> exception if 
{@link #isRequestAllowed(RestRequest)}
+        *      returns <jk>false</jk>.
+        * <p>
+        *      Subclasses are free to override this method to tailor the 
behavior of how to handle unauthorized
+        *      requests.
+        *
+        * @param req The servlet request.
+        * @param res The servlet response.
+        * @throws RestException Thrown to abort processing on current request.
+        * @return <jk>true</jk> if request can proceed.
+        *      Specify <jk>false</jk> if you're doing something like a 
redirection to a login page.
+        */
+       public boolean guard(RestRequest req, RestResponse res) throws 
RestException {
+               if (! isRequestAllowed(req))
+                       throw new RestException(SC_FORBIDDEN, "Access denied by 
guard");
+               return true;
+       }
+
+       /**
+        * Returns <jk>true</jk> if the specified request can pass through this 
guard.
+        *
+        * @param req The servlet request.
+        * @return <jk>true</jk> if the specified request can pass through this 
guard.
+        */
+       public abstract boolean isRequestAllowed(RestRequest req);
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/RestMatcher.java
----------------------------------------------------------------------
diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/RestMatcher.java 
b/juneau-rest/src/main/java/org/apache/juneau/rest/RestMatcher.java
new file mode 100644
index 0000000..84a14f3
--- /dev/null
+++ b/juneau-rest/src/main/java/org/apache/juneau/rest/RestMatcher.java
@@ -0,0 +1,76 @@
+// 
***************************************************************************************************************************
+// * 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.rest;
+
+import org.apache.juneau.rest.annotation.*;
+
+/**
+ * Class used for defining method-level matchers using the {@link 
RestMethod#matchers()} annotation.
+ * <p>
+ * Matchers are used to allow multiple Java methods to handle requests 
assigned to the same
+ *     URL path pattern, but differing based on some request attribute, such 
as a specific header value.
+ * For example, matchers can be used to provide two different methods for 
handling requests
+ *     from two different client versions.
+ * <p>
+ * Java methods with matchers associated with them are always attempted before 
Java methods
+ *     without matchers.
+ * This allows a 'default' method to be defined to handle requests where no 
matchers match.
+ * <p>
+ * When multiple matchers are specified on a method, only one matcher is 
required to match.
+ * This is opposite from the {@link RestMethod#guards()} annotation, where all 
guards
+ *     are required to match in order to execute the method.
+ *
+ * <h6 class='topic'>Example:</h6>
+ * <p class='bcode'>
+ *     <jk>public class</jk> MyResource <jk>extends</jk> RestServlet {
+ *
+ *             <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/foo"</js>, 
matchers=IsDNT.<jk>class</jk>)
+ *             <jk>public</jk> Object doGetWithDNT() {
+ *                     <jc>// Handle request with Do-Not-Track specified</jc>
+ *             }
+ *
+ *             <ja>@RestMethod</ja>(name=<js>"GET"</js>, path=<js>"/foo"</js>)
+ *             <jk>public</jk> Object doGetWithoutDNT() {
+ *                     <jc>// Handle request without Do-Not-Track 
specified</jc>
+ *             }
+ *     }
+ *
+ *     <jk>public class</jk> IsDNT <jk>extends</jk> RestMatcher {
+ *             <ja>@Override</ja>
+ *             <jk>public boolean</jk> matches(RestRequest req) {
+ *                     <jk>return</jk> 
req.getHeader(<jk>int</jk>.<jk>class</jk>, <js>"DNT"</js>, 0) == 1;
+ *             }
+ *     }
+ * </p>
+ */
+public abstract class RestMatcher {
+
+       /**
+        * Returns <jk>true</jk> if the specified request matches this matcher.
+        *
+        * @param req The servlet request.
+        * @return <jk>true</jk> if the specified request matches this matcher.
+        */
+       public abstract boolean matches(RestRequest req);
+
+       /**
+        * Returns <jk>true</jk> if this matcher is required to match in order 
for the method to be invoked.
+        * <p>
+        * If <jk>false</jk>, then only one of the matchers must match.
+        *
+        * @return <jk>true</jk> if this matcher is required to match in order 
for the method to be invoked.
+        */
+       public boolean mustMatch() {
+               return false;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/91a388d0/juneau-rest/src/main/java/org/apache/juneau/rest/RestMatcherReflecting.java
----------------------------------------------------------------------
diff --git 
a/juneau-rest/src/main/java/org/apache/juneau/rest/RestMatcherReflecting.java 
b/juneau-rest/src/main/java/org/apache/juneau/rest/RestMatcherReflecting.java
new file mode 100644
index 0000000..f40e14b
--- /dev/null
+++ 
b/juneau-rest/src/main/java/org/apache/juneau/rest/RestMatcherReflecting.java
@@ -0,0 +1,33 @@
+// 
***************************************************************************************************************************
+// * 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.rest;
+
+import java.lang.reflect.*;
+
+/**
+ * Subclass of {@link RestMatcher} that gives access to the servlet and Java 
method it's applied to.
+ * <p>
+ *     Essentially the same as {@link RestMatcher} except has a constructor 
where the
+ *     Java method is passed in so that you can access annotations defined on 
it to tailor
+ *     the behavior of the matcher.
+ */
+public abstract class RestMatcherReflecting extends RestMatcher {
+
+       /**
+        * Constructor.
+        *
+        * @param servlet The REST servlet.
+        * @param javaMethod The Java method that this rest matcher is defined 
on.
+        */
+       protected RestMatcherReflecting(RestServlet servlet, Method javaMethod) 
{}
+}

Reply via email to