You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2017/05/29 22:22:00 UTC

[3/5] incubator-juneau git commit: Improved support for resolution of URIs.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/Common_UonTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/Common_UonTest.java b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/Common_UonTest.java
index 5cc1775..3bc6fa4 100755
--- a/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/Common_UonTest.java
+++ b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/Common_UonTest.java
@@ -21,7 +21,6 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
-import org.apache.juneau.testbeans.*;
 import org.apache.juneau.uon.*;
 import org.apache.juneau.utils.*;
 import org.junit.*;
@@ -231,141 +230,6 @@ public class Common_UonTest {
 	}
 
 	//====================================================================================================
-	// Test URIs with URI_CONTEXT and URI_AUTHORITY
-	//====================================================================================================
-	@Test
-	public void testUris() throws Exception {
-		UonSerializerBuilder s = new UonSerializerBuilder();
-		TestURI t = new TestURI();
-		String r;
-		String expected;
-
-		s.relativeUriBase(null);
-		r = s.build().serialize(t);
-		expected = ""
-			+"("
-			+"f0=f0/x0,"
-			+"f1=f1/x1,"
-			+"f2=/f2/x2,"
-			+"f3=http://www.apache.org/f3/x3,"
-			+"f4=f4/x4,"
-			+"f5=/f5/x5,"
-			+"f6=http://www.apache.org/f6/x6,"
-			+"f7=http://www.apache.org/f7/x7,"
-			+"f8=f8/x8,"
-			+"f9=f9/x9,"
-			+"fa=http://www.apache.org/fa/xa#MY_LABEL,"
-			+"fb='http://www.apache.org/fb/xb?label=MY_LABEL&foo=bar',"
-			+"fc='http://www.apache.org/fc/xc?foo=bar&label=MY_LABEL',"
-			+"fd='http://www.apache.org/fd/xd?label2=MY_LABEL&foo=bar',"
-			+"fe='http://www.apache.org/fe/xe?foo=bar&label2=MY_LABEL'"
-			+")";
-		assertEquals(expected, r);
-
-		s.relativeUriBase("");  // Same as null.
-		r = s.build().serialize(t);
-		assertEquals(expected, r);
-
-		s.relativeUriBase("/cr");
-		r = s.build().serialize(t);
-		expected = ""
-			+"("
-			+"f0=/cr/f0/x0,"
-			+"f1=/cr/f1/x1,"
-			+"f2=/f2/x2,"
-			+"f3=http://www.apache.org/f3/x3,"
-			+"f4=/cr/f4/x4,"
-			+"f5=/f5/x5,"
-			+"f6=http://www.apache.org/f6/x6,"
-			+"f7=http://www.apache.org/f7/x7,"
-			+"f8=/cr/f8/x8,"
-			+"f9=/cr/f9/x9,"
-			+"fa=http://www.apache.org/fa/xa#MY_LABEL,"
-			+"fb='http://www.apache.org/fb/xb?label=MY_LABEL&foo=bar',"
-			+"fc='http://www.apache.org/fc/xc?foo=bar&label=MY_LABEL',"
-			+"fd='http://www.apache.org/fd/xd?label2=MY_LABEL&foo=bar',"
-			+"fe='http://www.apache.org/fe/xe?foo=bar&label2=MY_LABEL'"
-			+")";
-		assertEquals(expected, r);
-
-		s.relativeUriBase("/cr/");  // Same as above
-		r = s.build().serialize(t);
-		assertEquals(expected, r);
-
-		s.relativeUriBase("/");
-		r = s.build().serialize(t);
-		expected = ""
-			+"("
-			+"f0=/f0/x0,"
-			+"f1=/f1/x1,"
-			+"f2=/f2/x2,"
-			+"f3=http://www.apache.org/f3/x3,"
-			+"f4=/f4/x4,"
-			+"f5=/f5/x5,"
-			+"f6=http://www.apache.org/f6/x6,"
-			+"f7=http://www.apache.org/f7/x7,"
-			+"f8=/f8/x8,"
-			+"f9=/f9/x9,"
-			+"fa=http://www.apache.org/fa/xa#MY_LABEL,"
-			+"fb='http://www.apache.org/fb/xb?label=MY_LABEL&foo=bar',"
-			+"fc='http://www.apache.org/fc/xc?foo=bar&label=MY_LABEL',"
-			+"fd='http://www.apache.org/fd/xd?label2=MY_LABEL&foo=bar',"
-			+"fe='http://www.apache.org/fe/xe?foo=bar&label2=MY_LABEL'"
-			+")";
-		assertEquals(expected, r);
-
-		s.relativeUriBase(null);
-
-		s.absolutePathUriBase("http://foo");
-		r = s.build().serialize(t);
-		expected = ""
-			+"("
-			+"f0=f0/x0,"
-			+"f1=f1/x1,"
-			+"f2=http://foo/f2/x2,"
-			+"f3=http://www.apache.org/f3/x3,"
-			+"f4=f4/x4,"
-			+"f5=http://foo/f5/x5,"
-			+"f6=http://www.apache.org/f6/x6,"
-			+"f7=http://www.apache.org/f7/x7,"
-			+"f8=f8/x8,"
-			+"f9=f9/x9,"
-			+"fa=http://www.apache.org/fa/xa#MY_LABEL,"
-			+"fb='http://www.apache.org/fb/xb?label=MY_LABEL&foo=bar',"
-			+"fc='http://www.apache.org/fc/xc?foo=bar&label=MY_LABEL',"
-			+"fd='http://www.apache.org/fd/xd?label2=MY_LABEL&foo=bar',"
-			+"fe='http://www.apache.org/fe/xe?foo=bar&label2=MY_LABEL'"
-			+")";
-		assertEquals(expected, r);
-
-		s.absolutePathUriBase("http://foo/");
-		r = s.build().serialize(t);
-		assertEquals(expected, r);
-
-		s.absolutePathUriBase("");  // Same as null.
-		r = s.build().serialize(t);
-		expected = ""
-			+"("
-			+"f0=f0/x0,"
-			+"f1=f1/x1,"
-			+"f2=/f2/x2,"
-			+"f3=http://www.apache.org/f3/x3,"
-			+"f4=f4/x4,"
-			+"f5=/f5/x5,"
-			+"f6=http://www.apache.org/f6/x6,"
-			+"f7=http://www.apache.org/f7/x7,"
-			+"f8=f8/x8,"
-			+"f9=f9/x9,"
-			+"fa=http://www.apache.org/fa/xa#MY_LABEL,"
-			+"fb='http://www.apache.org/fb/xb?label=MY_LABEL&foo=bar',"
-			+"fc='http://www.apache.org/fc/xc?foo=bar&label=MY_LABEL',"
-			+"fd='http://www.apache.org/fd/xd?label2=MY_LABEL&foo=bar',"
-			+"fe='http://www.apache.org/fe/xe?foo=bar&label2=MY_LABEL'"
-			+")";
-		assertEquals(expected, r);
-	}
-
-	//====================================================================================================
 	// Recursion
 	//====================================================================================================
 	@Test

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/Common_UrlEncodingTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/Common_UrlEncodingTest.java b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/Common_UrlEncodingTest.java
index 806eaf0..e4f2d1b 100755
--- a/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/Common_UrlEncodingTest.java
+++ b/juneau-core-test/src/test/java/org/apache/juneau/urlencoding/Common_UrlEncodingTest.java
@@ -21,7 +21,6 @@ import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
-import org.apache.juneau.testbeans.*;
 import org.apache.juneau.utils.*;
 import org.junit.*;
 
@@ -232,131 +231,6 @@ public class Common_UrlEncodingTest {
 	}
 
 	//====================================================================================================
-	// Test URIs with URI_CONTEXT and URI_AUTHORITY
-	//====================================================================================================
-	@Test
-	public void testUris() throws Exception {
-		UrlEncodingSerializerBuilder s = new UrlEncodingSerializerBuilder();
-		TestURI t = new TestURI();
-		String r;
-		String expected = "";
-
-		s.relativeUriBase(null);
-		r = s.build().serialize(t);
-		expected = ""
-			+"f0=f0/x0"
-			+"&f1=f1/x1"
-			+"&f2=/f2/x2"
-			+"&f3=http://www.apache.org/f3/x3"
-			+"&f4=f4/x4"
-			+"&f5=/f5/x5"
-			+"&f6=http://www.apache.org/f6/x6"
-			+"&f7=http://www.apache.org/f7/x7"
-			+"&f8=f8/x8"
-			+"&f9=f9/x9"
-			+"&fa=http://www.apache.org/fa/xa%23MY_LABEL"
-			+"&fb='http://www.apache.org/fb/xb?label=MY_LABEL%26foo=bar'"
-			+"&fc='http://www.apache.org/fc/xc?foo=bar%26label=MY_LABEL'"
-			+"&fd='http://www.apache.org/fd/xd?label2=MY_LABEL%26foo=bar'"
-			+"&fe='http://www.apache.org/fe/xe?foo=bar%26label2=MY_LABEL'";
-		assertEquals(expected, r);
-
-		s.relativeUriBase("");  // Same as null.
-		r = s.build().serialize(t);
-		assertEquals(expected, r);
-
-		s.relativeUriBase("/cr");
-		r = s.build().serialize(t);
-		expected = ""
-			+"f0=/cr/f0/x0"
-			+"&f1=/cr/f1/x1"
-			+"&f2=/f2/x2"
-			+"&f3=http://www.apache.org/f3/x3"
-			+"&f4=/cr/f4/x4"
-			+"&f5=/f5/x5"
-			+"&f6=http://www.apache.org/f6/x6"
-			+"&f7=http://www.apache.org/f7/x7"
-			+"&f8=/cr/f8/x8"
-			+"&f9=/cr/f9/x9"
-			+"&fa=http://www.apache.org/fa/xa%23MY_LABEL"
-			+"&fb='http://www.apache.org/fb/xb?label=MY_LABEL%26foo=bar'"
-			+"&fc='http://www.apache.org/fc/xc?foo=bar%26label=MY_LABEL'"
-			+"&fd='http://www.apache.org/fd/xd?label2=MY_LABEL%26foo=bar'"
-			+"&fe='http://www.apache.org/fe/xe?foo=bar%26label2=MY_LABEL'";
-		assertEquals(expected, r);
-
-		s.relativeUriBase("/cr/");  // Same as above
-		r = s.build().serialize(t);
-		assertEquals(expected, r);
-
-		s.relativeUriBase("/");
-		r = s.build().serialize(t);
-		expected = ""
-			+"f0=/f0/x0"
-			+"&f1=/f1/x1"
-			+"&f2=/f2/x2"
-			+"&f3=http://www.apache.org/f3/x3"
-			+"&f4=/f4/x4"
-			+"&f5=/f5/x5"
-			+"&f6=http://www.apache.org/f6/x6"
-			+"&f7=http://www.apache.org/f7/x7"
-			+"&f8=/f8/x8"
-			+"&f9=/f9/x9"
-			+"&fa=http://www.apache.org/fa/xa%23MY_LABEL"
-			+"&fb='http://www.apache.org/fb/xb?label=MY_LABEL%26foo=bar'"
-			+"&fc='http://www.apache.org/fc/xc?foo=bar%26label=MY_LABEL'"
-			+"&fd='http://www.apache.org/fd/xd?label2=MY_LABEL%26foo=bar'"
-			+"&fe='http://www.apache.org/fe/xe?foo=bar%26label2=MY_LABEL'";
-		assertEquals(expected, r);
-
-		s.relativeUriBase(null);
-
-		s.absolutePathUriBase("http://foo");
-		r = s.build().serialize(t);
-		expected = ""
-			+"f0=f0/x0"
-			+"&f1=f1/x1"
-			+"&f2=http://foo/f2/x2"
-			+"&f3=http://www.apache.org/f3/x3"
-			+"&f4=f4/x4"
-			+"&f5=http://foo/f5/x5"
-			+"&f6=http://www.apache.org/f6/x6"
-			+"&f7=http://www.apache.org/f7/x7"
-			+"&f8=f8/x8"
-			+"&f9=f9/x9"
-			+"&fa=http://www.apache.org/fa/xa%23MY_LABEL"
-			+"&fb='http://www.apache.org/fb/xb?label=MY_LABEL%26foo=bar'"
-			+"&fc='http://www.apache.org/fc/xc?foo=bar%26label=MY_LABEL'"
-			+"&fd='http://www.apache.org/fd/xd?label2=MY_LABEL%26foo=bar'"
-			+"&fe='http://www.apache.org/fe/xe?foo=bar%26label2=MY_LABEL'";
-		assertEquals(expected, r);
-
-		s.absolutePathUriBase("http://foo/");
-		r = s.build().serialize(t);
-		assertEquals(expected, r);
-
-		s.absolutePathUriBase("");  // Same as null.
-		r = s.build().serialize(t);
-		expected = ""
-			+"f0=f0/x0"
-			+"&f1=f1/x1"
-			+"&f2=/f2/x2"
-			+"&f3=http://www.apache.org/f3/x3"
-			+"&f4=f4/x4"
-			+"&f5=/f5/x5"
-			+"&f6=http://www.apache.org/f6/x6"
-			+"&f7=http://www.apache.org/f7/x7"
-			+"&f8=f8/x8"
-			+"&f9=f9/x9"
-			+"&fa=http://www.apache.org/fa/xa%23MY_LABEL"
-			+"&fb='http://www.apache.org/fb/xb?label=MY_LABEL%26foo=bar'"
-			+"&fc='http://www.apache.org/fc/xc?foo=bar%26label=MY_LABEL'"
-			+"&fd='http://www.apache.org/fd/xd?label2=MY_LABEL%26foo=bar'"
-			+"&fe='http://www.apache.org/fe/xe?foo=bar%26label2=MY_LABEL'";
-		assertEquals(expected, r);
-	}
-
-	//====================================================================================================
 	// Recursion
 	//====================================================================================================
 	@Test

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core-test/src/test/java/org/apache/juneau/utils/UriContextResolutionComboTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/utils/UriContextResolutionComboTest.java b/juneau-core-test/src/test/java/org/apache/juneau/utils/UriContextResolutionComboTest.java
index 2995cf6..d5fd0f4 100644
--- a/juneau-core-test/src/test/java/org/apache/juneau/utils/UriContextResolutionComboTest.java
+++ b/juneau-core-test/src/test/java/org/apache/juneau/utils/UriContextResolutionComboTest.java
@@ -35,7 +35,7 @@ public class UriContextResolutionComboTest {
 		return Arrays.asList(new Object[][] {
 
 			// Happy cases - All URL parts known.
-			{
+			{	/* 0 */
 				"Happy-1a",
 				input(
 					"http://host:port","/context","/resource","/path",
@@ -50,7 +50,7 @@ public class UriContextResolutionComboTest {
 					"http://foo.com:123/foobar"
 				)
 			},
-			{
+			{	/* 1 */
 				"Happy-2",
 				input(
 					"http://host:port","/context","/resource","/path",
@@ -65,7 +65,7 @@ public class UriContextResolutionComboTest {
 					"http://foo.com:123"
 				)
 			},
-			{
+			{	/* 2 */
 				"Happy-3",
 				input(
 					"http://host:port","/context","/resource","/path",
@@ -80,7 +80,7 @@ public class UriContextResolutionComboTest {
 					"/foobar"
 				)
 			},
-			{
+			{	/* 3 */
 				"Happy-4",
 				input(
 					"http://host:port","/context","/resource","/path", 
@@ -95,7 +95,7 @@ public class UriContextResolutionComboTest {
 					"/"
 				)
 			},
-			{
+			{	/* 4 */
 				"Happy-5",
 				input(
 					"http://host:port","/context","/resource","/path", 
@@ -110,7 +110,7 @@ public class UriContextResolutionComboTest {
 					"foobar"
 				)
 			},
-			{
+			{	/* 5 */
 				"Happy-6",
 				input(
 					"http://host:port","/context","/resource","/path", 
@@ -125,7 +125,7 @@ public class UriContextResolutionComboTest {
 					""
 				)
 			},
-			{
+			{	/* 6 */
 				"Happy-7",
 				input(
 					"http://host:port","/context","/resource","/path", 
@@ -140,7 +140,7 @@ public class UriContextResolutionComboTest {
 					"/context/foo"
 				)
 			},
-			{
+			{	/* 7 */
 				"Happy-8",
 				input(
 					"http://host:port","/context","/resource","/path", 
@@ -155,7 +155,7 @@ public class UriContextResolutionComboTest {
 					"/context"
 				)
 			},
-			{
+			{	/* 8 */
 				"Happy-9",
 				input(
 					"http://host:port","/context","/resource","/path", 
@@ -170,7 +170,7 @@ public class UriContextResolutionComboTest {
 					"/context/resource/foo"
 				)
 			},
-			{
+			{	/* 9 */
 				"Happy-10",
 				input(
 					"http://host:port","/context","/resource","/path", 
@@ -187,7 +187,7 @@ public class UriContextResolutionComboTest {
 			},
 			
 			// Multiple context and resource parts
-			{
+			{	/* 10 */
 				"MultiContextResource-1",
 				input(
 					"http://host:port","/c1/c2","/r1/r2","/p1/p2",
@@ -202,7 +202,7 @@ public class UriContextResolutionComboTest {
 					"http://foo.com:123/foobar"
 				)
 			},
-			{
+			{	/* 11 */
 				"MultiContextResource-2",
 				input(
 					"http://host:port","/c1/c2","/r1/r2","/p1/p2",
@@ -217,7 +217,7 @@ public class UriContextResolutionComboTest {
 					"http://foo.com:123"
 				)
 			},
-			{
+			{	/* 12 */
 				"MultiContextResource-3",
 				input(
 					"http://host:port","/c1/c2","/r1/r2","/p1/p2",
@@ -232,7 +232,7 @@ public class UriContextResolutionComboTest {
 					"/foobar"
 				)
 			},
-			{
+			{	/* 13 */
 				"MultiContextResource-4",
 				input(
 					"http://host:port","/c1/c2","/r1/r2","/p1/p2",
@@ -247,7 +247,7 @@ public class UriContextResolutionComboTest {
 					"/"
 				)
 			},
-			{
+			{	/* 14 */
 				"MultiContextResource-5",
 				input(
 					"http://host:port","/c1/c2","/r1/r2","/p1/p2",
@@ -262,7 +262,7 @@ public class UriContextResolutionComboTest {
 					"foobar"
 				)
 			},
-			{
+			{	/* 15 */
 				"MultiContextResource-6",
 				input(
 					"http://host:port","/c1/c2","/r1/r2","/p1/p2",
@@ -277,7 +277,7 @@ public class UriContextResolutionComboTest {
 					""
 				)
 			},
-			{
+			{	/* 16 */
 				"MultiContextResource-7",
 				input(
 					"http://host:port","/c1/c2","/r1/r2","/p1/p2",
@@ -292,7 +292,7 @@ public class UriContextResolutionComboTest {
 					"/c1/c2/foo"
 				)
 			},
-			{
+			{	/* 17 */
 				"MultiContextResource-8",
 				input(
 					"http://host:port","/c1/c2","/r1/r2","/p1/p2",
@@ -307,7 +307,7 @@ public class UriContextResolutionComboTest {
 					"/c1/c2"
 				)
 			},
-			{
+			{	/* 18 */
 				"MultiContextResource-9",
 				input(
 					"http://host:port","/c1/c2","/r1/r2","/p1/p2",
@@ -322,7 +322,7 @@ public class UriContextResolutionComboTest {
 					"/c1/c2/r1/r2/foo"
 				)
 			},
-			{
+			{	/* 19 */
 				"MultiContextResource-10",
 				input(
 					"http://host:port","/c1/c2","/r1/r2","/p1/p2",
@@ -339,7 +339,7 @@ public class UriContextResolutionComboTest {
 			},
 			
 			// No authority given
-			{
+			{	/* 20 */
 				"NoAuthority-1",
 				input(
 					"","/context","/resource","/path",
@@ -354,7 +354,7 @@ public class UriContextResolutionComboTest {
 					"http://foo.com:123/foobar"
 				)
 			},
-			{
+			{	/* 21 */
 				"NoAuthority-2",
 				input(
 					"","/context","/resource","/path",
@@ -369,7 +369,7 @@ public class UriContextResolutionComboTest {
 					"http://foo.com:123"
 				)
 			},
-			{
+			{	/* 22 */
 				"NoAuthority-3",
 				input(
 					"","/context","/resource","/path",
@@ -384,7 +384,7 @@ public class UriContextResolutionComboTest {
 					"/foobar"
 				)
 			},
-			{
+			{	/* 23 */
 				"NoAuthority-4",
 				input(
 					"","/context","/resource","/path",
@@ -399,7 +399,7 @@ public class UriContextResolutionComboTest {
 					"/"
 				)
 			},
-			{
+			{	/* 24 */
 				"NoAuthority-5",
 				input(
 					"","/context","/resource","/path",
@@ -414,7 +414,7 @@ public class UriContextResolutionComboTest {
 					"foobar"
 				)
 			},
-			{
+			{	/* 25 */
 				"NoAuthority-6",
 				input(
 					"","/context","/resource","/path",
@@ -429,7 +429,7 @@ public class UriContextResolutionComboTest {
 					""
 				)
 			},
-			{
+			{	/* 26 */
 				"NoAuthority-7",
 				input(
 					"","/context","/resource","/path",
@@ -444,7 +444,7 @@ public class UriContextResolutionComboTest {
 					"/context/foo"
 				)
 			},
-			{
+			{	/* 27 */
 				"NoAuthority-8",
 				input(
 					"","/context","/resource","/path",
@@ -459,7 +459,7 @@ public class UriContextResolutionComboTest {
 					"/context"
 				)
 			},
-			{
+			{	/* 28 */
 				"NoAuthority-9",
 				input(
 					"","/context","/resource","/path",
@@ -474,7 +474,7 @@ public class UriContextResolutionComboTest {
 					"/context/resource/foo"
 				)
 			},
-			{
+			{	/* 29 */
 				"NoAuthority-10",
 				input(
 					"","/context","/resource","/path",
@@ -491,7 +491,7 @@ public class UriContextResolutionComboTest {
 			},
 			
 			// No authority or context given
-			{
+			{	/* 30 */
 				"NoAuthorityOrContext-1",
 				input(
 					"","","/resource","/path",
@@ -506,7 +506,7 @@ public class UriContextResolutionComboTest {
 					"http://foo.com:123/foobar"
 				)
 			},
-			{
+			{	/* 31 */
 				"NoAuthorityOrContext-2",
 				input(
 					"","","/resource","/path",
@@ -521,7 +521,7 @@ public class UriContextResolutionComboTest {
 					"http://foo.com:123"
 				)
 			},
-			{
+			{	/* 32 */
 				"NoAuthorityOrContext-3",
 				input(
 					"","","/resource","/path",
@@ -536,7 +536,7 @@ public class UriContextResolutionComboTest {
 					"/foobar"
 				)
 			},
-			{
+			{	/* 33 */
 				"NoAuthorityOrContext-4",
 				input(
 					"","","/resource","/path",
@@ -551,7 +551,7 @@ public class UriContextResolutionComboTest {
 					"/"
 				)
 			},
-			{
+			{	/* 34 */
 				"NoAuthorityOrContext-5",
 				input(
 					"","","/resource","/path",
@@ -566,7 +566,7 @@ public class UriContextResolutionComboTest {
 					"foobar"
 				)
 			},
-			{
+			{	/* 35 */
 				"NoAuthorityOrContext-6",
 				input(
 					"","","/resource","/path",
@@ -581,7 +581,7 @@ public class UriContextResolutionComboTest {
 					""
 				)
 			},
-			{
+			{	/* 36 */
 				"NoAuthorityOrContext-7",
 				input(
 					"","","/resource","/path",
@@ -596,7 +596,7 @@ public class UriContextResolutionComboTest {
 					"/foo"
 				)
 			},
-			{
+			{	/* 37 */
 				"NoAuthorityOrContext-8",
 				input(
 					"","","/resource","/path",
@@ -611,7 +611,7 @@ public class UriContextResolutionComboTest {
 					"/"
 				)
 			},
-			{
+			{	/* 38 */
 				"NoAuthorityOrContext-9",
 				input(
 					"","","/resource","/path",
@@ -626,7 +626,7 @@ public class UriContextResolutionComboTest {
 					"/resource/foo"
 				)
 			},
-			{
+			{	/* 39 */
 				"NoAuthorityOrContext-10",
 				input(
 					"","","/resource","/path",
@@ -643,7 +643,7 @@ public class UriContextResolutionComboTest {
 			},
 
 			// No authority or context or resource given
-			{
+			{	/* 40 */
 				"NoAuthorityOrContextOrResource-1",
 				input(
 					"","","","/path",
@@ -658,7 +658,7 @@ public class UriContextResolutionComboTest {
 					"http://foo.com:123/foobar"
 				)
 			},
-			{
+			{	/* 41 */
 				"NoAuthorityOrContextOrResource-2",
 				input(
 					"","","","/path",
@@ -673,7 +673,7 @@ public class UriContextResolutionComboTest {
 					"http://foo.com:123"
 				)
 			},
-			{
+			{	/* 42 */
 				"NoAuthorityOrContextOrResource-3",
 				input(
 					"","","","/path",
@@ -688,7 +688,7 @@ public class UriContextResolutionComboTest {
 					"/foobar"
 				)
 			},
-			{
+			{	/* 43 */
 				"NoAuthorityOrContextOrResource-4",
 				input(
 					"","","","/path",
@@ -703,7 +703,7 @@ public class UriContextResolutionComboTest {
 					"/"
 				)
 			},
-			{
+			{	/* 44 */
 				"NoAuthorityOrContextOrResource-5",
 				input(
 					"","","","/path",
@@ -718,8 +718,7 @@ public class UriContextResolutionComboTest {
 					"foobar"
 				)
 			},
-//			return new Results(eAbsResource, eAbsPathInfo, eRrResource, eRrPathInfo, eNoneResource, eNonePathInfo);
-			{
+			{	/* 45 */
 				"NoAuthorityOrContextOrResource-6",
 				input(
 					"","","","/path",
@@ -734,7 +733,7 @@ public class UriContextResolutionComboTest {
 					""
 				)
 			},
-			{
+			{	/* 46 */
 				"NoAuthorityOrContextOrResource-7",
 				input(
 					"","","","/path",
@@ -749,7 +748,7 @@ public class UriContextResolutionComboTest {
 					"/foo"
 				)
 			},
-			{
+			{	/* 47 */
 				"NoAuthorityOrContextOrResource-8",
 				input(
 					"","","","/path",
@@ -764,7 +763,7 @@ public class UriContextResolutionComboTest {
 					"/"
 				)
 			},
-			{
+			{	/* 48 */
 				"NoAuthorityOrContextOrResource-9",
 				input(
 					"","","","/path",
@@ -779,7 +778,7 @@ public class UriContextResolutionComboTest {
 					"/foo"
 				)
 			},
-			{
+			{	/* 49 */
 				"NoAuthorityOrContextOrResource-10",
 				input(
 					"","","","/path",
@@ -796,7 +795,7 @@ public class UriContextResolutionComboTest {
 			},
 			
 			// No context or resource given.
-			{
+			{	/* 50 */
 				"NoContextOrResource-1",
 				input(
 					"http://host:port","","","/path",
@@ -811,7 +810,7 @@ public class UriContextResolutionComboTest {
 					"http://foo.com:123/foobar"
 				)
 			},
-			{
+			{	/* 51 */
 				"NoContextOrResource-2",
 				input(
 					"http://host:port","","","/path",
@@ -826,7 +825,7 @@ public class UriContextResolutionComboTest {
 					"http://foo.com:123"
 				)
 			},
-			{
+			{	/* 52 */
 				"NoContextOrResource-3",
 				input(
 					"http://host:port","","","/path",
@@ -841,7 +840,7 @@ public class UriContextResolutionComboTest {
 					"/foobar"
 				)
 			},
-			{
+			{	/* 53 */
 				"NoContextOrResource-4",
 				input(
 					"http://host:port","","","/path",
@@ -856,7 +855,7 @@ public class UriContextResolutionComboTest {
 					"/"
 				)
 			},
-			{
+			{	/* 54 */
 				"NoContextOrResource-5",
 				input(
 					"http://host:port","","","/path",
@@ -871,7 +870,7 @@ public class UriContextResolutionComboTest {
 					"foobar"
 				)
 			},
-			{
+			{	/* 55 */
 				"NoContextOrResource-6",
 				input(
 					"http://host:port","","","/path",
@@ -886,7 +885,7 @@ public class UriContextResolutionComboTest {
 					""
 				)
 			},
-			{
+			{	/* 56 */
 				"NoContextOrResource-7",
 				input(
 					"http://host:port","","","/path",
@@ -901,7 +900,7 @@ public class UriContextResolutionComboTest {
 					"/foo"
 				)
 			},
-			{
+			{	/* 57 */
 				"NoContextOrResource-8",
 				input(
 					"http://host:port","","","/path",
@@ -916,7 +915,7 @@ public class UriContextResolutionComboTest {
 					"/"
 				)
 			},
-			{
+			{	/* 58 */
 				"NoContextOrResource-9",
 				input(
 					"http://host:port","","","/path",
@@ -931,7 +930,7 @@ public class UriContextResolutionComboTest {
 					"/foo"
 				)
 			},
-			{
+			{	/* 59 */
 				"NoContextOrResource-10",
 				input(
 					"http://host:port","","","/path",
@@ -995,61 +994,61 @@ public class UriContextResolutionComboTest {
 	
 	@Test
 	public void a01_testAbsoluteResource() {
-		assertEquals(r.aResource, new UriContext(ABSOLUTE, RESOURCE, in.authority, in.context, in.resource, in.path).resolve(in.uri), "{0}: testAbsolute() failed", label);
+		assertEquals(r.aResource, new UriResolver(ABSOLUTE, RESOURCE, new UriContext(in.authority, in.context, in.resource, in.path)).resolve(in.uri), "{0}: testAbsolute() failed", label);
 	}	
 		
 	@Test
 	public void a02_testAppendAbsoluteResource() {
-		assertEquals(r.aResource, new UriContext(ABSOLUTE, RESOURCE, in.authority, in.context, in.resource, in.path).append(new StringBuilder(), in.uri).toString(), "{0}: testAbsolute() failed", label);
+		assertEquals(r.aResource, new UriResolver(ABSOLUTE, RESOURCE, new UriContext(in.authority, in.context, in.resource, in.path)).append(new StringBuilder(), in.uri).toString(), "{0}: testAbsolute() failed", label);
 	}
 	
 	@Test
 	public void a03_testAbsolutePathInfo() {
-		assertEquals(r.aPathInfo, new UriContext(ABSOLUTE, PATH_INFO, in.authority, in.context, in.resource, in.path).resolve(in.uri), "{0}: testAbsolute() failed", label);
+		assertEquals(r.aPathInfo, new UriResolver(ABSOLUTE, PATH_INFO, new UriContext(in.authority, in.context, in.resource, in.path)).resolve(in.uri), "{0}: testAbsolute() failed", label);
 	}	
 		
 	@Test
 	public void a04_testAppendAbsolutePathInfo() {
-		assertEquals(r.aPathInfo, new UriContext(ABSOLUTE, PATH_INFO, in.authority, in.context, in.resource, in.path).append(new StringBuilder(), in.uri).toString(), "{0}: testAbsolute() failed", label);
+		assertEquals(r.aPathInfo, new UriResolver(ABSOLUTE, PATH_INFO, new UriContext(in.authority, in.context, in.resource, in.path)).append(new StringBuilder(), in.uri).toString(), "{0}: testAbsolute() failed", label);
 	}
 
 	@Test
 	public void a05_testRootRelativeResource() {
-		assertEquals(r.rrResource, new UriContext(ROOT_RELATIVE, RESOURCE, in.authority, in.context, in.resource, in.path).resolve(in.uri), "{0}: testAbsolute() failed", label);
+		assertEquals(r.rrResource, new UriResolver(ROOT_RELATIVE, RESOURCE, new UriContext(in.authority, in.context, in.resource, in.path)).resolve(in.uri), "{0}: testAbsolute() failed", label);
 	}	
 		
 	@Test
 	public void a06_testAppendRootRelativeResource() {
-		assertEquals(r.rrResource, new UriContext(ROOT_RELATIVE, RESOURCE, in.authority, in.context, in.resource, in.path).append(new StringBuilder(), in.uri).toString(), "{0}: testAbsolute() failed", label);
+		assertEquals(r.rrResource, new UriResolver(ROOT_RELATIVE, RESOURCE, new UriContext(in.authority, in.context, in.resource, in.path)).append(new StringBuilder(), in.uri).toString(), "{0}: testAbsolute() failed", label);
 	}
 
 	@Test
 	public void a07_testRootRelativePathInfo() {
-		assertEquals(r.rrPathInfo, new UriContext(ROOT_RELATIVE, PATH_INFO, in.authority, in.context, in.resource, in.path).resolve(in.uri), "{0}: testAbsolute() failed", label);
+		assertEquals(r.rrPathInfo, new UriResolver(ROOT_RELATIVE, PATH_INFO, new UriContext(in.authority, in.context, in.resource, in.path)).resolve(in.uri), "{0}: testAbsolute() failed", label);
 	}	
 		
 	@Test
 	public void a08_testAppendRootRelativePathInfo() {
-		assertEquals(r.rrPathInfo, new UriContext(ROOT_RELATIVE, PATH_INFO, in.authority, in.context, in.resource, in.path).append(new StringBuilder(), in.uri).toString(), "{0}: testAbsolute() failed", label);
+		assertEquals(r.rrPathInfo, new UriResolver(ROOT_RELATIVE, PATH_INFO, new UriContext(in.authority, in.context, in.resource, in.path)).append(new StringBuilder(), in.uri).toString(), "{0}: testAbsolute() failed", label);
 	}
 
 	@Test
 	public void a09_testNoneResource() {
-		assertEquals(r.nResource, new UriContext(NONE, RESOURCE, in.authority, in.context, in.resource, in.path).resolve(in.uri), "{0}: testAbsolute() failed", label);
+		assertEquals(r.nResource, new UriResolver(NONE, RESOURCE, new UriContext(in.authority, in.context, in.resource, in.path)).resolve(in.uri), "{0}: testAbsolute() failed", label);
 	}	
 		
 	@Test
 	public void a10_testAppendNoneResource() {
-		assertEquals(r.nResource, new UriContext(NONE, RESOURCE, in.authority, in.context, in.resource, in.path).append(new StringBuilder(), in.uri).toString(), "{0}: testAbsolute() failed", label);
+		assertEquals(r.nResource, new UriResolver(NONE, RESOURCE, new UriContext(in.authority, in.context, in.resource, in.path)).append(new StringBuilder(), in.uri).toString(), "{0}: testAbsolute() failed", label);
 	}
 
 	@Test
 	public void a11_testNonePathInfo() {
-		assertEquals(r.nPathInfo, new UriContext(NONE, PATH_INFO, in.authority, in.context, in.resource, in.path).resolve(in.uri), "{0}: testAbsolute() failed", label);
+		assertEquals(r.nPathInfo, new UriResolver(NONE, PATH_INFO, new UriContext(in.authority, in.context, in.resource, in.path)).resolve(in.uri), "{0}: testAbsolute() failed", label);
 	}	
 		
 	@Test
 	public void a12_testAppendNonePathInfo() {
-		assertEquals(r.nPathInfo, new UriContext(NONE, PATH_INFO, in.authority, in.context, in.resource, in.path).append(new StringBuilder(), in.uri).toString(), "{0}: testAbsolute() failed", label);
+		assertEquals(r.nPathInfo, new UriResolver(NONE, PATH_INFO, new UriContext(in.authority, in.context, in.resource, in.path)).append(new StringBuilder(), in.uri).toString(), "{0}: testAbsolute() failed", label);
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core-test/src/test/java/org/apache/juneau/utils/UriContextUriComboTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/utils/UriContextUriComboTest.java b/juneau-core-test/src/test/java/org/apache/juneau/utils/UriContextUriComboTest.java
index e63f87f..9b94944 100644
--- a/juneau-core-test/src/test/java/org/apache/juneau/utils/UriContextUriComboTest.java
+++ b/juneau-core-test/src/test/java/org/apache/juneau/utils/UriContextUriComboTest.java
@@ -199,7 +199,7 @@ public class UriContextUriComboTest {
 		private final UriContext uriContext;
 		
 		public Input(String authority, String context, String resource, String path) {
-			this.uriContext = new UriContext(UriResolution.ABSOLUTE, UriRelativity.RESOURCE, authority, context, resource, path);
+			this.uriContext = new UriContext(authority, context, resource, path);
 		}
 	}
 	

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core-test/src/test/java/org/apache/juneau/xml/CommonTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/xml/CommonTest.java b/juneau-core-test/src/test/java/org/apache/juneau/xml/CommonTest.java
index 07ac1c6..3e8563f 100755
--- a/juneau-core-test/src/test/java/org/apache/juneau/xml/CommonTest.java
+++ b/juneau-core-test/src/test/java/org/apache/juneau/xml/CommonTest.java
@@ -23,7 +23,6 @@ import java.util.*;
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.jena.annotation.*;
-import org.apache.juneau.testbeans.*;
 import org.apache.juneau.utils.*;
 import org.apache.juneau.xml.annotation.*;
 import org.junit.*;
@@ -248,136 +247,6 @@ public class CommonTest {
 	}
 
 	//====================================================================================================
-	// Test URIs with URI_CONTEXT and URI_AUTHORITY
-	//====================================================================================================
-	@Test
-	public void testUris() throws Exception {
-		XmlSerializerBuilder s = new XmlSerializerBuilder().sq();
-		TestURI t = new TestURI();
-		String r;
-		String expected;
-
-		s.relativeUriBase(null);
-		r = s.build().serialize(t);
-		expected = ""
-			+"<object f0='f0/x0'>"
-			+"<f1>f1/x1</f1>"
-			+"<f2>/f2/x2</f2>"
-			+"<f3>http://www.apache.org/f3/x3</f3>"
-			+"<f4>f4/x4</f4>"
-			+"<f5>/f5/x5</f5>"
-			+"<f6>http://www.apache.org/f6/x6</f6>"
-			+"<f7>http://www.apache.org/f7/x7</f7>"
-			+"<f8>f8/x8</f8>"
-			+"<f9>f9/x9</f9>"
-			+"<fa>http://www.apache.org/fa/xa#MY_LABEL</fa>"
-			+"<fb>http://www.apache.org/fb/xb?label=MY_LABEL&amp;foo=bar</fb>"
-			+"<fc>http://www.apache.org/fc/xc?foo=bar&amp;label=MY_LABEL</fc>"
-			+"<fd>http://www.apache.org/fd/xd?label2=MY_LABEL&amp;foo=bar</fd>"
-			+"<fe>http://www.apache.org/fe/xe?foo=bar&amp;label2=MY_LABEL</fe>"
-			+"</object>";
-		assertEquals(expected, r);
-
-		s.relativeUriBase("");  // Same as null.
-		r = s.build().serialize(t);
-		assertEquals(expected, r);
-
-		s.relativeUriBase("/cr");
-		r = s.build().serialize(t);
-		expected = ""
-			+"<object f0='/cr/f0/x0'>"
-			+"<f1>/cr/f1/x1</f1>"
-			+"<f2>/f2/x2</f2>"
-			+"<f3>http://www.apache.org/f3/x3</f3>"
-			+"<f4>/cr/f4/x4</f4>"
-			+"<f5>/f5/x5</f5>"
-			+"<f6>http://www.apache.org/f6/x6</f6>"
-			+"<f7>http://www.apache.org/f7/x7</f7>"
-			+"<f8>/cr/f8/x8</f8>"
-			+"<f9>/cr/f9/x9</f9>"
-			+"<fa>http://www.apache.org/fa/xa#MY_LABEL</fa>"
-			+"<fb>http://www.apache.org/fb/xb?label=MY_LABEL&amp;foo=bar</fb>"
-			+"<fc>http://www.apache.org/fc/xc?foo=bar&amp;label=MY_LABEL</fc>"
-			+"<fd>http://www.apache.org/fd/xd?label2=MY_LABEL&amp;foo=bar</fd>"
-			+"<fe>http://www.apache.org/fe/xe?foo=bar&amp;label2=MY_LABEL</fe>"
-			+"</object>";
-		assertEquals(expected, r);
-
-		s.relativeUriBase("/cr/");  // Same as above
-		r = s.build().serialize(t);
-		assertEquals(expected, r);
-
-		s.relativeUriBase("/");
-		r = s.build().serialize(t);
-		expected = ""
-			+"<object f0='/f0/x0'>"
-			+"<f1>/f1/x1</f1>"
-			+"<f2>/f2/x2</f2>"
-			+"<f3>http://www.apache.org/f3/x3</f3>"
-			+"<f4>/f4/x4</f4>"
-			+"<f5>/f5/x5</f5>"
-			+"<f6>http://www.apache.org/f6/x6</f6>"
-			+"<f7>http://www.apache.org/f7/x7</f7>"
-			+"<f8>/f8/x8</f8>"
-			+"<f9>/f9/x9</f9>"
-			+"<fa>http://www.apache.org/fa/xa#MY_LABEL</fa>"
-			+"<fb>http://www.apache.org/fb/xb?label=MY_LABEL&amp;foo=bar</fb>"
-			+"<fc>http://www.apache.org/fc/xc?foo=bar&amp;label=MY_LABEL</fc>"
-			+"<fd>http://www.apache.org/fd/xd?label2=MY_LABEL&amp;foo=bar</fd>"
-			+"<fe>http://www.apache.org/fe/xe?foo=bar&amp;label2=MY_LABEL</fe>"
-			+"</object>";
-		assertEquals(expected, r);
-
-		s.relativeUriBase(null);
-
-		s.absolutePathUriBase("http://foo");
-		r = s.build().serialize(t);
-		expected = ""
-			+"<object f0='f0/x0'>"
-			+"<f1>f1/x1</f1>"
-			+"<f2>http://foo/f2/x2</f2>"
-			+"<f3>http://www.apache.org/f3/x3</f3>"
-			+"<f4>f4/x4</f4>"
-			+"<f5>http://foo/f5/x5</f5>"
-			+"<f6>http://www.apache.org/f6/x6</f6>"
-			+"<f7>http://www.apache.org/f7/x7</f7>"
-			+"<f8>f8/x8</f8>"
-			+"<f9>f9/x9</f9>"
-			+"<fa>http://www.apache.org/fa/xa#MY_LABEL</fa>"
-			+"<fb>http://www.apache.org/fb/xb?label=MY_LABEL&amp;foo=bar</fb>"
-			+"<fc>http://www.apache.org/fc/xc?foo=bar&amp;label=MY_LABEL</fc>"
-			+"<fd>http://www.apache.org/fd/xd?label2=MY_LABEL&amp;foo=bar</fd>"
-			+"<fe>http://www.apache.org/fe/xe?foo=bar&amp;label2=MY_LABEL</fe>"
-			+"</object>";
-		assertEquals(expected, r);
-
-		s.absolutePathUriBase("http://foo/");
-		r = s.build().serialize(t);
-		assertEquals(expected, r);
-
-		s.absolutePathUriBase("");  // Same as null.
-		r = s.build().serialize(t);
-		expected = ""
-			+"<object f0='f0/x0'>"
-			+"<f1>f1/x1</f1>"
-			+"<f2>/f2/x2</f2>"
-			+"<f3>http://www.apache.org/f3/x3</f3>"
-			+"<f4>f4/x4</f4>"
-			+"<f5>/f5/x5</f5>"
-			+"<f6>http://www.apache.org/f6/x6</f6>"
-			+"<f7>http://www.apache.org/f7/x7</f7>"
-			+"<f8>f8/x8</f8>"
-			+"<f9>f9/x9</f9>"
-			+"<fa>http://www.apache.org/fa/xa#MY_LABEL</fa>"
-			+"<fb>http://www.apache.org/fb/xb?label=MY_LABEL&amp;foo=bar</fb>"
-			+"<fc>http://www.apache.org/fc/xc?foo=bar&amp;label=MY_LABEL</fc>"
-			+"<fd>http://www.apache.org/fd/xd?label2=MY_LABEL&amp;foo=bar</fd>"
-			+"<fe>http://www.apache.org/fe/xe?foo=bar&amp;label2=MY_LABEL</fe>"
-			+"</object>";
-		assertEquals(expected, r);
-	}
-
-	//====================================================================================================
 	// Recursion
 	//====================================================================================================
 	@Test

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/UriContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/UriContext.java b/juneau-core/src/main/java/org/apache/juneau/UriContext.java
index 2756111..9b7c497 100644
--- a/juneau-core/src/main/java/org/apache/juneau/UriContext.java
+++ b/juneau-core/src/main/java/org/apache/juneau/UriContext.java
@@ -13,10 +13,6 @@
 package org.apache.juneau;
 
 import static org.apache.juneau.internal.StringUtils.*;
-import static org.apache.juneau.UriResolution.*;
-import static org.apache.juneau.UriRelativity.*;
-
-import java.io.*;
 
 import org.apache.juneau.annotation.*;
 
@@ -32,44 +28,21 @@ import org.apache.juneau.annotation.*;
  * <p>
  * This class allows you to convert URL strings to absolute (e.g. <js>"http://host:port/foo/bar"</js>) or root-relative
  * 	(e.g. <js>"/foo/bar"</js>) URLs.
- * <p>
- * Two special protocols are used to represent context-root-relative and servlet-relative URIs:
- * 	<js>"context:/"</js> and <js>"servlet:/"</js>.
- *
- * The following list shows the types of URLs that can be resolved with this class:
- * <ul>
- * 	<li><js>"foo://foo"</js> - Absolute URI.
- * 	<li><js>"/foo"</js> - Root-relative URI.
- * 	<li><js>"/"</js> - Root URI.
- * 	<li><js>"context:/foo"</js> - Context-root-relative URI.
- * 	<li><js>"context:/"</js> - Context-root URI.
- * 	<li><js>"servlet:/foo"</js> - Servlet-path-relative URI.
- * 	<li><js>"servlet:/"</js> - Servlet-path URI.
- * 	<li><js>"foo"</js> - Path-info-relative URI.
- * 	<li><js>""</js> - Path-info URI.
- * </ul>
- *
- * The following class shows how
  */
 @Bean
 public class UriContext {
 
 	/**
 	 * Default URI context.
-	 * No URI resolution occurs.
 	 * No information about authority, servlet-root, context-root, or path-info is known.
 	 */
-	public static final UriContext DEFAULT = new UriContext(UriResolution.NONE, UriRelativity.PATH_INFO, null, null, null, null);
+	public static final UriContext DEFAULT = new UriContext();
 
-	private final String authority, contextRoot, servletPath, pathInfo, parentPath;
-
-	private final UriResolution resolution;
-	private final UriRelativity relativity;
+	final String authority, contextRoot, servletPath, pathInfo, parentPath;
 
 	// Lazy-initialized fields.
 	private String aContextRoot, rContextRoot, aServletPath, rResource, aPathInfo, rPath;
 
-
 	/**
 	 * Constructor.
 	 * <p>
@@ -77,17 +50,13 @@ public class UriContext {
 	 * <p>
 	 * Any parameter can be <jk>null</jk>.  Blanks and nulls are equivalent.
 	 *
-	 * @param resolution
-	 * @param relativity
 	 * @param authority - The authority portion of URL (e.g. <js>"http://hostname:port"</js>)
 	 * @param contextRoot - The context root of the application (e.g. <js>"/context-root"</js>, or <js>"context-root"</js>)
 	 * @param servletPath - The servlet path (e.g. <js>"/servlet-path"</js>, or <js>"servlet-path"</js>)
 	 * @param pathInfo - The path info (e.g. <js>"/path-info"</js>, or <js>"path-info"</js>)
 	 */
-	@BeanConstructor(properties="resolution,relativity,authority,contextRoot,servletPath,pathInfo")
-	public UriContext(UriResolution resolution, UriRelativity relativity, String authority, String contextRoot, String servletPath, String pathInfo) {
-		this.resolution = resolution;
-		this.relativity = relativity;
+	@BeanConstructor(properties="authority,contextRoot,servletPath,pathInfo")
+	public UriContext(String authority, String contextRoot, String servletPath, String pathInfo) {
 		this.authority = nullIfEmpty(trimSlashes(authority));
 		this.contextRoot = nullIfEmpty(trimSlashes(contextRoot));
 		this.servletPath = nullIfEmpty(trimSlashes(servletPath));
@@ -97,11 +66,12 @@ public class UriContext {
 
 	/**
 	 * Default constructor.
+	 * All <jk>null</jk> values.
 	 */
 	public UriContext() {
-		this(ROOT_RELATIVE, RESOURCE, null, null, null, null);
+		this(null, null, null, null);
 	}
-
+	
 	/**
 	 * Returns the absolute URI of just the authority portion of this URI context.
 	 * <p>
@@ -278,121 +248,10 @@ public class UriContext {
 		return getParent(getRootRelativePathInfo());
 	}
 
-	/**
-	 * Converts the specified URI to absolute form based on values in this context.
-	 *
-	 * @param uri The URI to convert to absolute form.
-	 * @return The converted URI.
-	 */
-	public String resolve(String uri) {
-		if (isAbsoluteUri(uri))
-			return uri;
-		if (resolution == ROOT_RELATIVE && startsWith(uri, '/'))
-			return uri;
-		if (resolution == NONE && ! isSpecialUri(uri))
-			return uri;
-		return append(new StringBuilder(), uri).toString();
-	}
-
-	/**
-	 * Same as {@link #resolve(String)} except appends result to the specified appendable.
-	 *
-	 * @param a The appendable to append the URL to.
-	 * @param uri The URI to convert to absolute form.
-	 * @return The same appendable passed in.
-	 */
-	public Appendable append(Appendable a, String uri) {
-
-		try {
-			uri = nullIfEmpty(uri);
-
-			// Absolute paths are not changed.
-			if (isAbsoluteUri(uri))
-				return a.append(uri);
-			if (resolution == NONE && ! isSpecialUri(uri))
-				return a.append(emptyIfNull(uri));
-			if (resolution == ROOT_RELATIVE && startsWith(uri, '/'))
-				return a.append(uri);
-
-			// Root-relative path
-			if (startsWith(uri, '/')) {
-				if (authority != null){
-					a.append(authority);
-					if (uri.length() == 1)
-						return a;
-				}
-				return a.append(uri);
-			}
-
-			// Context-relative path
-			if (uri != null && uri.startsWith("context:/")) {
-				if (resolution == ABSOLUTE && authority != null)
-					a.append(authority);
-				if (contextRoot != null)
-					a.append('/').append(contextRoot);
-				if (uri.length() > 9)
-					a.append('/').append(uri.substring(9));
-				else if (contextRoot == null && (authority == null || resolution != ABSOLUTE))
-					a.append('/');
-				return a;
-			}
-
-			// Resource-relative path
-			if (uri != null && uri.startsWith("servlet:/")) {
-				if (resolution == ABSOLUTE && authority != null)
-					a.append(authority);
-				if (contextRoot != null)
-					a.append('/').append(contextRoot);
-				if (servletPath != null)
-					a.append('/').append(servletPath);
-				if (uri.length() > 9)
-					a.append('/').append(uri.substring(9));
-				else if (servletPath == null && contextRoot == null && (authority == null || resolution != ABSOLUTE))
-					a.append('/');
-				return a;
-			}
-
-			// Relative path
-			if (resolution == ABSOLUTE && authority != null)
-				a.append(authority);
-			if (contextRoot != null)
-				a.append('/').append(contextRoot);
-			if (servletPath != null)
-				a.append('/').append(servletPath);
-			if (relativity == RESOURCE && uri != null)
-				a.append('/').append(uri);
-			else if (relativity == PATH_INFO) {
-				if (uri == null) {
-					if (pathInfo != null)
-						a.append('/').append(pathInfo);
-				} else {
-					if (parentPath != null)
-						a.append('/').append(parentPath);
-					a.append('/').append(uri);
-				}
-			}
-			else if (uri == null && contextRoot == null && servletPath == null && (authority == null || resolution != ABSOLUTE))
-				a.append('/');
-
-			return a;
-		} catch (IOException e) {
-			throw new RuntimeException(e);
-		}
-	}
-
 	private static String getParent(String uri) {
 		int i = uri.lastIndexOf('/');
 		if (i <= 1)
 			return "/";
 		return uri.substring(0, i);
 	}
-
-	private static boolean isSpecialUri(String s) {
-		if (s == null || s.length() == 0)
-			return false;
-		char c = s.charAt(0);
-		if (c != 's' && c != 'c')
-			return false;
-		return s.startsWith("servlet:/") || s.startsWith("context:/");
-	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/UriRelativity.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/UriRelativity.java b/juneau-core/src/main/java/org/apache/juneau/UriRelativity.java
index 95fc46b..394223b 100644
--- a/juneau-core/src/main/java/org/apache/juneau/UriRelativity.java
+++ b/juneau-core/src/main/java/org/apache/juneau/UriRelativity.java
@@ -13,7 +13,7 @@
 package org.apache.juneau;
 
 /**
- * Identifies how relative URIs should resolve against.
+ * Identifies what relative URIs are relative to.
  */
 public enum UriRelativity {
 
@@ -25,5 +25,5 @@ public enum UriRelativity {
 	/**
 	 * Relative URIs should be considered relative to the request URI.
 	 */
-	PATH_INFO;
+	PATH_INFO
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/UriResolver.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/UriResolver.java b/juneau-core/src/main/java/org/apache/juneau/UriResolver.java
new file mode 100644
index 0000000..995569a
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/UriResolver.java
@@ -0,0 +1,273 @@
+// ***************************************************************************************************************************
+// * 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;
+
+import static org.apache.juneau.UriRelativity.*;
+import static org.apache.juneau.UriResolution.*;
+import static org.apache.juneau.internal.StringUtils.*;
+
+import java.io.*;
+import java.net.*;
+
+import org.apache.juneau.internal.*;
+
+/**
+ * Class used to create absolute and root-relative URIs based on your current URI 'location' and rules about how to
+ * make such resolutions.
+ * <p>
+ * Combines a {@link UriContext} instance with rules for resolution ({@link UriResolution} and relativity
+ * 	({@link UriRelativity}) to define simple {@link #resolve(Object)} and {@link #append(Appendable, Object)}
+ * 	methods.
+  * <p>
+ * Three special protocols are used to represent context-root-relative, servlet-relative, and request-path-relative URIs:
+ * 	<js>"context:/"</js>, <js>"servlet:/"</js>, and <js>"request:/"</js>.
+ *
+ * The following list shows the protocols of URLs that can be resolved with this class:
+ * <ul>
+ * 	<li><js>"foo://foo"</js> - Absolute URI.
+ * 	<li><js>"/foo"</js> - Root-relative URI.
+ * 	<li><js>"/"</js> - Root URI.
+ * 	<li><js>"context:/foo"</js> - Context-root-relative URI.
+ * 	<li><js>"context:/"</js> - Context-root URI.
+ * 	<li><js>"servlet:/foo"</js> - Servlet-path-relative URI.
+ * 	<li><js>"servlet:/"</js> - Servlet-path URI.
+ * 	<li><js>"request:/foo"</js> - Request-path-relative URI.
+ * 	<li><js>"request:/"</js> - Request-path URI.
+ * 	<li><js>"foo"</js> - Path-info-relative URI.
+ * 	<li><js>""</js> - Path-info URI.
+ * </ul>
+*/
+public class UriResolver {
+
+	private final UriResolution resolution;
+	private final UriRelativity relativity;
+	private final String authority, contextRoot, servletPath, pathInfo, parentPath;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param resolution Rule on how URIs should be resolved.
+	 * @param relativity Rule on what relative URIs are relative to.
+	 * @param uriContext Current URI context (i.e. the current URI 'location').
+	 */
+	public UriResolver(UriResolution resolution, UriRelativity relativity, UriContext uriContext) {
+		this.resolution = resolution;
+		this.relativity = relativity;
+		this.authority = uriContext.authority;
+		this.contextRoot = uriContext.contextRoot;
+		this.servletPath = uriContext.servletPath;
+		this.pathInfo = uriContext.pathInfo;
+		this.parentPath = uriContext.parentPath;
+	}
+
+	/**
+	 * Converts the specified URI to absolute form based on values in this context.
+	 *
+	 * @param uri The URI to convert to absolute form.
+	 * 	Can be any of the following:
+	 * 	<ul>
+	 * 		<li>{@link java.net.URI}
+	 * 		<li>{@link java.net.URL}
+	 * 		<li>{@link CharSequence}
+	 * 	</ul>
+	 * 	URI can be any of the following forms:
+	 * 	<ul>
+	 * 		<li><js>"foo://foo"</js> - Absolute URI.
+	 * 		<li><js>"/foo"</js> - Root-relative URI.
+	 * 		<li><js>"/"</js> - Root URI.
+	 * 		<li><js>"context:/foo"</js> - Context-root-relative URI.
+	 * 		<li><js>"context:/"</js> - Context-root URI.
+	 * 		<li><js>"servlet:/foo"</js> - Servlet-path-relative URI.
+	 * 		<li><js>"servlet:/"</js> - Servlet-path URI.
+	 * 		<li><js>"request:/foo"</js> - Request-path-relative URI.
+	 * 		<li><js>"request:/"</js> - Request-path URI.
+	 * 		<li><js>"foo"</js> - Path-info-relative URI.
+	 * 		<li><js>""</js> - Path-info URI.
+	 * 	</ul>
+	 * @return The converted URI.
+	 */
+	public String resolve(Object uri) {
+		return resolve(uri, resolution);
+	}
+
+	private String resolve(Object uri, UriResolution res) {
+		String s = StringUtils.toString(uri);
+		if (isAbsoluteUri(s))
+			return hasDotSegments(s) && res != NONE ? normalize(s) : s;
+		if (res == ROOT_RELATIVE && startsWith(s, '/'))
+			return hasDotSegments(s) ? normalize(s) : s;
+		if (res == NONE && ! isSpecialUri(s))
+			return s;
+		return append(new StringBuilder(), s).toString();
+	}
+
+	/**
+	 * Relativizes a URI.
+	 * <p>
+	 * Similar to {@link URI#relativize(URI)}, except supports special protocols (e.g. <js>"servlet:/"</js>) for
+	 * both the <code>relativeTo</code> and <code>uri</code> parameters.
+	 * <p>
+	 * For example, to relativize a URI to its servlet-relative form:
+	 * <p class='bcode'>
+	 * 	<jc>// relativeUri == "path/foo"</jc>
+	 * 	String relativeUri = resolver.relativize(<js>"servlet:/"</js>, <js>"/context/servlet/path/foo"</js>);
+	 * </p>
+	 *
+	 * @param relativeTo The URI to relativize against.
+	 * @param uri The URI to relativize.
+	 * @return The relativized URI.
+	 */
+	public String relativize(Object relativeTo, Object uri) {
+		String r = resolve(relativeTo, ABSOLUTE);
+		String s = resolve(uri, ABSOLUTE);
+		return URI.create(r).relativize(URI.create(s)).toString();
+	}
+
+	/**
+	 * Same as {@link #resolve(Object)} except appends result to the specified appendable.
+	 *
+	 * @param a The appendable to append the URL to.
+	 * @param o The URI to convert to absolute form.
+	 * @return The same appendable passed in.
+	 */
+	public Appendable append(Appendable a, Object o) {
+
+		try {
+			String uri = StringUtils.toString(o);
+			uri = nullIfEmpty(uri);
+			boolean needsNormalize = hasDotSegments(uri) && resolution != null;
+
+			// Absolute paths are not changed.
+			if (isAbsoluteUri(uri))
+				return a.append(needsNormalize ? normalize(uri) : uri);
+			if (resolution == NONE && ! isSpecialUri(uri))
+				return a.append(emptyIfNull(uri));
+			if (resolution == ROOT_RELATIVE && startsWith(uri, '/'))
+				return a.append(needsNormalize ? normalize(uri) : uri);
+
+			Appendable a2 = needsNormalize ? new StringBuilder() : a;
+
+			// Root-relative path
+			if (startsWith(uri, '/')) {
+				if (authority != null)
+					a2.append(authority);
+				if (uri.length() != 1)
+					a2.append(uri);
+				else if (authority == null)
+					a2.append('/');
+			}
+
+			// Context-relative path
+			else if (uri != null && uri.startsWith("context:/")) {
+				if (resolution == ABSOLUTE && authority != null)
+					a2.append(authority);
+				if (contextRoot != null)
+					a2.append('/').append(contextRoot);
+				if (uri.length() > 9)
+					a2.append('/').append(uri.substring(9));
+				else if (contextRoot == null && (authority == null || resolution != ABSOLUTE))
+					a2.append('/');
+			}
+
+			// Resource-relative path
+			else if (uri != null && uri.startsWith("servlet:/")) {
+				if (resolution == ABSOLUTE && authority != null)
+					a2.append(authority);
+				if (contextRoot != null)
+					a2.append('/').append(contextRoot);
+				if (servletPath != null)
+					a2.append('/').append(servletPath);
+				if (uri.length() > 9)
+					a2.append('/').append(uri.substring(9));
+				else if (servletPath == null && contextRoot == null && (authority == null || resolution != ABSOLUTE))
+					a2.append('/');
+			}
+
+			// Request-relative path
+			else if (uri != null && uri.startsWith("request:/")) {
+				if (resolution == ABSOLUTE && authority != null)
+					a2.append(authority);
+				if (contextRoot != null)
+					a2.append('/').append(contextRoot);
+				if (servletPath != null)
+					a2.append('/').append(servletPath);
+				if (pathInfo != null)
+					a2.append('/').append(pathInfo);
+				if (uri.length() > 9)
+					a2.append('/').append(uri.substring(9));
+				else if (servletPath == null && contextRoot == null && pathInfo == null && (authority == null || resolution != ABSOLUTE))
+					a2.append('/');
+			}
+
+			// Relative path
+			else {
+				if (resolution == ABSOLUTE && authority != null)
+					a2.append(authority);
+				if (contextRoot != null)
+					a2.append('/').append(contextRoot);
+				if (servletPath != null)
+					a2.append('/').append(servletPath);
+				if (relativity == RESOURCE && uri != null)
+					a2.append('/').append(uri);
+				else if (relativity == PATH_INFO) {
+					if (uri == null) {
+						if (pathInfo != null)
+							a2.append('/').append(pathInfo);
+					} else {
+						if (parentPath != null)
+							a2.append('/').append(parentPath);
+						a2.append('/').append(uri);
+					}
+				}
+				else if (uri == null && contextRoot == null && servletPath == null && (authority == null || resolution != ABSOLUTE))
+					a2.append('/');
+			}
+
+			if (needsNormalize)
+				a.append(normalize(a2.toString()));
+
+			return a;
+		} catch (IOException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	private static boolean isSpecialUri(String s) {
+		if (s == null || s.length() == 0)
+			return false;
+		char c = s.charAt(0);
+		if (c != 's' && c != 'c' && c != 'r')
+			return false;
+		return s.startsWith("servlet:/") || s.startsWith("context:/") || s.startsWith("request:/");
+	}
+
+	private static String normalize(String s) {
+		s = URI.create(s).normalize().toString();
+		if (s.length() > 1 && s.charAt(s.length()-1) == '/')
+			s = s.substring(0, s.length()-1);
+		return s;
+	}
+
+	private static boolean hasDotSegments(String s) {
+		if (s == null)
+			return false;
+		for (int i = 0; i < s.length()-1; i++) {
+			char c = s.charAt(i);
+			if (i == 0 && c == '/')
+				return true;
+			if (c == '/' && s.charAt(i+1) == '.')
+				return true;
+		}
+		return false;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/annotation/URI.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/annotation/URI.java b/juneau-core/src/main/java/org/apache/juneau/annotation/URI.java
index 7a3a19c..e5685db 100644
--- a/juneau-core/src/main/java/org/apache/juneau/annotation/URI.java
+++ b/juneau-core/src/main/java/org/apache/juneau/annotation/URI.java
@@ -18,6 +18,7 @@ import static java.lang.annotation.RetentionPolicy.*;
 import java.lang.annotation.*;
 import java.net.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.serializer.*;
 
 /**
@@ -29,8 +30,13 @@ import org.apache.juneau.serializer.*;
  * <p>
  * This annotation allows you to identify other classes that return URIs via <code>toString()</code> as URI objects.
  * <p>
- * Relative URIs are automatically prepended with {@link SerializerContext#SERIALIZER_absolutePathUriBase} and {@link SerializerContext#SERIALIZER_relativeUriBase}
- * 	during serialization just like relative <code>URIs</code>.
+ * URIs are automatically resolved to absolute or root-relative form based on the serializer
+ * 	{@link SerializerContext#SERIALIZER_uriResolution} and {@link SerializerContext#SERIALIZER_uriRelativity}
+ * 	configuration settings, and the URI context defined by the {@link UriContext} that's part of the serializer
+ * 	session.
+ * <p>
+ * Refer to the {@link UriResolver} class for information about the types of URIs that can be resolved during
+ * 	serialization.
  * <p>
  * This annotation can be applied to classes, interfaces, or bean property methods for fields.
  *

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
index 48d7ae3..eb002b3 100644
--- a/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
@@ -127,14 +127,20 @@ public class CsvSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public CsvSerializerBuilder relativeUriBase(String value) {
-		super.relativeUriBase(value);
+	public CsvSerializerBuilder uriContext(UriContext value) {
+		super.uriContext(value);
 		return this;
 	}
 
 	@Override /* SerializerBuilder */
-	public CsvSerializerBuilder absolutePathUriBase(String value) {
-		super.absolutePathUriBase(value);
+	public CsvSerializerBuilder uriResolution(UriResolution value) {
+		super.uriResolution(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public CsvSerializerBuilder uriRelativity(UriRelativity value) {
+		super.uriRelativity(value);
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
index 9bd5a10..b51c8d6 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
@@ -19,7 +19,6 @@ import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.dto.*;
 import org.apache.juneau.http.*;
-import org.apache.juneau.internal.*;
 import org.apache.juneau.serializer.*;
 
 /**
@@ -50,9 +49,7 @@ public class HtmlDocSerializer extends HtmlStrippedDocSerializer {
 
 	// Properties defined in RestServletProperties
 	private static final String
-		REST_method = "RestServlet.method",
-		REST_relativeServletURI = "RestServlet.relativeServletURI";
-
+		REST_method = "RestServlet.method";
 
 	/** Default serializer, all default settings. */
 	public static final HtmlDocSerializer DEFAULT = new HtmlDocSerializer(PropertyStore.create());
@@ -84,6 +81,7 @@ public class HtmlDocSerializer extends HtmlStrippedDocSerializer {
 
 		HtmlDocSerializerSession s = (HtmlDocSerializerSession)session;
 		HtmlWriter w = s.getWriter();
+		UriResolver uriResolver = s.getUriResolver();
 
 		boolean isOptionsPage = session.getProperty(REST_method, "").equalsIgnoreCase("OPTIONS");
 
@@ -93,7 +91,8 @@ public class HtmlDocSerializer extends HtmlStrippedDocSerializer {
 
 		String cssUrl = s.getCssUrl();
 		if (cssUrl == null)
-			cssUrl = session.getProperty(REST_relativeServletURI, "") + "/style.css";
+			cssUrl = "servlet:/style.css";
+		cssUrl = uriResolver.resolve(cssUrl);
 
 		w.oTag(1, "style")
 			.attr("type", "text/css")
@@ -125,15 +124,7 @@ public class HtmlDocSerializer extends HtmlStrippedDocSerializer {
 			Map<String,String> htmlLinks = s.getLinks();
 			if (htmlLinks != null) {
 				for (Map.Entry<String,String> e : htmlLinks.entrySet()) {
-					String uri = e.getValue();
-					if (uri.indexOf("://") == -1 && ! StringUtils.startsWith(uri, '/')) {
-						StringBuilder sb = new StringBuilder(session.getProperty(REST_relativeServletURI, ""));
-						if (! (uri.isEmpty() || uri.charAt(0) == '?' || uri.charAt(0) == '/'))
-							sb.append('/');
-						sb.append(uri);
-						uri = sb.toString();
-					}
-
+					String uri = uriResolver.resolve(e.getValue());
 					actions.add(new Link(e.getKey(), uri));
 				}
 			}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
index f04d2b7..5490265 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
@@ -133,6 +133,6 @@ public final class HtmlDocSerializerSession extends HtmlSerializerSession {
 		Object output = getOutput();
 		if (output instanceof HtmlWriter)
 			return (HtmlWriter)output;
-		return new HtmlWriter(super.getWriter(), isUseWhitespace(), isTrimStrings(), getQuoteChar(), getRelativeUriBase(), getAbsolutePathUriBase(), getUriContext());
+		return new HtmlWriter(super.getWriter(), isUseWhitespace(), isTrimStrings(), getQuoteChar(), getUriResolver());
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
index 91b8f16..736e8c8 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
@@ -326,7 +326,7 @@ public class HtmlSerializer extends XmlSerializer {
 			} else if (session.isUri(sType, pMeta, o)) {
 				String label = session.getAnchorText(pMeta, o);
 				out.oTag("a").attrUri("href", o).append('>');
-				out.append(label);
+				out.text(label);
 				out.eTag("a");
 				cr = CR_SIMPLE;
 
@@ -443,12 +443,12 @@ public class HtmlSerializer extends XmlSerializer {
 			out.cTag();
 
 			try {
-				if (link != null) 
+				if (link != null)
 					out.oTag(i+3, "a").attrUri("href", m.resolveVars(link)).cTag();
 				ContentResult cr = serializeAnything(session, out, render.getContent(session, value), cMeta, key, 2, pMeta, false);
 				if (cr == CR_NORMAL)
 					out.i(i+2);
-				if (link != null) 
+				if (link != null)
 					out.eTag("a");
 			} catch (SerializeException e) {
 				throw e;
@@ -556,12 +556,12 @@ public class HtmlSerializer extends XmlSerializer {
 						if (style != null)
 							out.attr("style", style);
 						out.cTag();
-						if (link != null) 
+						if (link != null)
 							out.oTag(i+3, "a").attrUri("href", m2.resolveVars(link)).cTag();
 						ContentResult cr = serializeAnything(session, out, render.getContent(session, value), pMeta.getClassMeta(), p.getKey().toString(), 2, pMeta, false);
 						if (cr == CR_NORMAL)
 							out.i(i+2);
-						if (link != null) 
+						if (link != null)
 							out.eTag("a");
 						out.eTag("td").nl();
 					}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
index 6190c14..b9a7fad 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerBuilder.java
@@ -304,14 +304,20 @@ public class HtmlSerializerBuilder extends XmlSerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public HtmlSerializerBuilder relativeUriBase(String value) {
-		super.relativeUriBase(value);
+	public HtmlSerializerBuilder uriContext(UriContext value) {
+		super.uriContext(value);
 		return this;
 	}
 
 	@Override /* SerializerBuilder */
-	public HtmlSerializerBuilder absolutePathUriBase(String value) {
-		super.absolutePathUriBase(value);
+	public HtmlSerializerBuilder uriResolution(UriResolution value) {
+		super.uriResolution(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public HtmlSerializerBuilder uriRelativity(UriRelativity value) {
+		super.uriRelativity(value);
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
index 48b16dd..8b28821 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
@@ -14,6 +14,7 @@ package org.apache.juneau.html;
 
 import static org.apache.juneau.html.HtmlSerializerContext.*;
 import static org.apache.juneau.msgpack.MsgPackSerializerContext.*;
+import static org.apache.juneau.xml.XmlUtils.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -21,7 +22,6 @@ import java.util.regex.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
-import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.xml.*;
 
@@ -40,12 +40,11 @@ public class HtmlSerializerSession extends XmlSerializerSession {
 		addBeanTypeProperties;
 	private final Pattern urlPattern = Pattern.compile("http[s]?\\:\\/\\/.*");
 	private final Pattern labelPattern;
-	private final String absolutePathUriBase, relativeUriBase;
 
 
 	@SuppressWarnings("hiding")
 	enum AnchorText {
-		PROPERTY_NAME, TO_STRING, URI, LAST_TOKEN, URI_ANCHOR
+		PROPERTY_NAME, TO_STRING, URI, LAST_TOKEN, URI_ANCHOR, CONTEXT_RELATIVE, SERVLET_RELATIVE, PATH_RELATIVE
 	}
 
 	/**
@@ -84,8 +83,6 @@ public class HtmlSerializerSession extends XmlSerializerSession {
 			addBeanTypeProperties = op.getBoolean(MSGPACK_addBeanTypeProperties, ctx.addBeanTypeProperties);
 		}
 		labelPattern = Pattern.compile("[\\?\\&]" + Pattern.quote(labelParameter) + "=([^\\&]*)");
-		this.absolutePathUriBase = getAbsolutePathUriBase();
-		this.relativeUriBase = getRelativeUriBase();
 	}
 
 	@Override /* XmlSerializerSession */
@@ -93,7 +90,7 @@ public class HtmlSerializerSession extends XmlSerializerSession {
 		Object output = getOutput();
 		if (output instanceof HtmlWriter)
 			return (HtmlWriter)output;
-		return new HtmlWriter(super.getWriter(), isUseWhitespace(), isTrimStrings(), getQuoteChar(), getRelativeUriBase(), getAbsolutePathUriBase(), getUriContext());
+		return new HtmlWriter(super.getWriter(), isUseWhitespace(), isTrimStrings(), getQuoteChar(), getUriResolver());
 	}
 
 	/**
@@ -122,47 +119,40 @@ public class HtmlSerializerSession extends XmlSerializerSession {
 	 * @return The anchor text to use for the specified URL object.
 	 */
 	public String getAnchorText(BeanPropertyMeta pMeta, Object o) {
-		String s;
+		String s = o.toString();
 		if (lookForLabelParameters) {
-			s = o.toString();
 			Matcher m = labelPattern.matcher(s);
 			if (m.find())
-				return m.group(1);
+				return urlDecode(m.group(1));
 		}
 		switch (anchorText) {
 			case LAST_TOKEN:
-				s = o.toString();
+				s = resolveUri(s);
 				if (s.indexOf('/') != -1)
 					s = s.substring(s.lastIndexOf('/')+1);
 				if (s.indexOf('?') != -1)
 					s = s.substring(0, s.indexOf('?'));
 				if (s.indexOf('#') != -1)
 					s = s.substring(0, s.indexOf('#'));
-				return s;
+				if (s.isEmpty())
+					s = "/";
+				return urlDecode(s);
 			case URI_ANCHOR:
-				s = o.toString();
 				if (s.indexOf('#') != -1)
 					s = s.substring(s.lastIndexOf('#')+1);
-				return s;
+				return urlDecode(s);
 			case PROPERTY_NAME:
-				return pMeta == null ? o.toString() : pMeta.getName();
+				return pMeta == null ? s : pMeta.getName();
 			case URI:
-				s = o.toString();
-				if (s.indexOf("://") == -1) {
-					if (StringUtils.startsWith(s, '/')) {
-						s = absolutePathUriBase + s;
-					} else {
-						if (relativeUriBase != null) {
-							if (! relativeUriBase.equals("/"))
-								s = relativeUriBase + "/" + s;
-							else
-								s = "/" + s;
-						}
-					}
-				}
+				return resolveUri(s);
+			case CONTEXT_RELATIVE:
+				return relativizeUri("context:/", s);
+			case SERVLET_RELATIVE:
+				return relativizeUri("servlet:/", s);
+			case PATH_RELATIVE:
+				return relativizeUri("request:/", s);
+			default /* TO_STRING */:
 				return s;
-			default:
-				return o.toString();
 		}
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/html/HtmlWriter.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlWriter.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlWriter.java
index 30114c3..0ea9ccf 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlWriter.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlWriter.java
@@ -30,13 +30,10 @@ public class HtmlWriter extends XmlWriter {
 	 * @param useWhitespace If <jk>true</jk>, tabs will be used in output.
 	 * @param trimStrings If <jk>true</jk>, strings should be trimmed before they're serialized.
 	 * @param quoteChar The quote character to use (i.e. <js>'\''</js> or <js>'"'</js>)
-	 * @param uriContext The web application context path (e.g. "/contextRoot").
-	 * @param uriAuthority The web application URI authority (e.g. "http://hostname:9080")
-	 * @param uriContext2 The URI context.
-	 * 	Identifies the current request URI used for resolution of URIs to absolute or root-relative form.
+	 * @param uriResolver The URI resolver for resolving URIs to absolute or root-relative form.
 	 */
-	public HtmlWriter(Writer out, boolean useWhitespace, boolean trimStrings, char quoteChar, String uriContext, String uriAuthority, UriContext uriContext2) {
-		super(out, useWhitespace, trimStrings, quoteChar, uriContext, uriAuthority, uriContext2, false, null);
+	public HtmlWriter(Writer out, boolean useWhitespace, boolean trimStrings, char quoteChar, UriResolver uriResolver) {
+		super(out, useWhitespace, trimStrings, quoteChar, uriResolver, false, null);
 	}
 
 	/**
@@ -260,14 +257,14 @@ public class HtmlWriter extends XmlWriter {
 	}
 
 	@Override /* XmlSerializerWriter */
-	public HtmlWriter attr(String ns, String name, Object value, boolean needsEncoding) throws IOException {
-		super.attr(ns, name, value, needsEncoding);
+	public HtmlWriter attr(String ns, String name, Object value, boolean valNeedsEncoding) throws IOException {
+		super.attr(ns, name, value, valNeedsEncoding);
 		return this;
 	}
 
 	@Override /* XmlSerializerWriter */
-	public HtmlWriter attr(String name, Object value, boolean needsEncoding) throws IOException {
-		super.attr(null, name, value, needsEncoding);
+	public HtmlWriter attr(String name, Object value, boolean valNeedsEncoding) throws IOException {
+		super.attr(null, name, value, valNeedsEncoding);
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/html/SimpleHtmlWriter.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/SimpleHtmlWriter.java b/juneau-core/src/main/java/org/apache/juneau/html/SimpleHtmlWriter.java
index b0b6cc3..f122b36 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/SimpleHtmlWriter.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/SimpleHtmlWriter.java
@@ -28,7 +28,7 @@ public class SimpleHtmlWriter extends HtmlWriter {
 	 * Constructor.
 	 */
 	public SimpleHtmlWriter() {
-		super(new StringWriter(), true, false, '\'', null, null, null);
+		super(new StringWriter(), true, false, '\'', null);
 	}
 
 	@Override /* Object */

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/internal/AsciiMap.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/internal/AsciiMap.java b/juneau-core/src/main/java/org/apache/juneau/internal/AsciiMap.java
new file mode 100644
index 0000000..4f63f77
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/internal/AsciiMap.java
@@ -0,0 +1,82 @@
+// ***************************************************************************************************************************
+// * 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.internal;
+
+/**
+ * Stores a Map of ASCII characters to Strings in a quick-lookup array.
+ */
+public final class AsciiMap {
+	final String[] store = new String[128];
+
+	/**
+	 * Adds an entry to this map.
+	 *
+	 * @param c The key.
+	 * @param s The value.
+	 * @return This object (for method chaining).
+	 */
+	public AsciiMap append(char c, String s) {
+		if (c <= 127)
+			store[c] = s;
+		return this;
+	}
+
+	/**
+	 * Returns the value for the specified key.
+	 *
+	 * @param c The key.
+	 * @return The value.
+	 */
+	public String get(char c) {
+		return store[c];
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the specified character is in this store.
+	 *
+	 * @param c The character to check.
+	 * @return <jk>true</jk> if the specified character is in this store.
+	 */
+	public boolean contains(char c) {
+		if (c > 127)
+			return false;
+		return store[c] != null;
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the specified character is in this store.
+	 *
+	 * @param c The character to check.
+	 * @return <jk>true</jk> if the specified character is in this store.
+	 */
+	public boolean contains(int c) {
+		if (c < 0 || c > 127)
+			return false;
+		return store[c] != null;
+	}
+
+	/**
+	 * Returns <jk>true</jk> if the specified string contains at least one character in this set.
+	 *
+	 * @param s The string to test.
+	 * @return <jk>true</jk> if the string is not null and contains at least one character in this set.
+	 */
+	public boolean contains(CharSequence s) {
+		if (s == null)
+			return false;
+		for (int i = 0; i < s.length(); i++)
+			if (contains(s.charAt(i)))
+				return true;
+		return false;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
index 88d89c5..3508985 100644
--- a/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
@@ -127,14 +127,20 @@ public class JsoSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public JsoSerializerBuilder relativeUriBase(String value) {
-		super.relativeUriBase(value);
+	public JsoSerializerBuilder uriContext(UriContext value) {
+		super.uriContext(value);
 		return this;
 	}
 
 	@Override /* SerializerBuilder */
-	public JsoSerializerBuilder absolutePathUriBase(String value) {
-		super.absolutePathUriBase(value);
+	public JsoSerializerBuilder uriResolution(UriResolution value) {
+		super.uriResolution(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public JsoSerializerBuilder uriRelativity(UriRelativity value) {
+		super.uriRelativity(value);
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
index eb4a1ea..112cbee 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSchemaSerializerBuilder.java
@@ -144,14 +144,20 @@ public class JsonSchemaSerializerBuilder extends JsonSerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public JsonSchemaSerializerBuilder relativeUriBase(String value) {
-		super.relativeUriBase(value);
+	public JsonSchemaSerializerBuilder uriContext(UriContext value) {
+		super.uriContext(value);
 		return this;
 	}
 
 	@Override /* SerializerBuilder */
-	public JsonSchemaSerializerBuilder absolutePathUriBase(String value) {
-		super.absolutePathUriBase(value);
+	public JsonSchemaSerializerBuilder uriResolution(UriResolution value) {
+		super.uriResolution(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public JsonSchemaSerializerBuilder uriRelativity(UriRelativity value) {
+		super.uriRelativity(value);
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
index e857b15..1037e60 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
@@ -253,7 +253,7 @@ public class JsonSerializer extends WriterSerializer {
 		else if (sType.isBean())
 			serializeBeanMap(session, out, session.toBeanMap(o), typeName);
 		else if (sType.isUri() || (pMeta != null && pMeta.isUri()))
-			out.q().appendUri(o).q();
+			out.uriValue(o);
 		else if (sType.isMap()) {
 			if (o instanceof BeanMap)
 				serializeBeanMap(session, out, (BeanMap)o, typeName);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
index 0715dd1..33be93f 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
@@ -192,14 +192,20 @@ public class JsonSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public JsonSerializerBuilder relativeUriBase(String value) {
-		super.relativeUriBase(value);
+	public JsonSerializerBuilder uriContext(UriContext value) {
+		super.uriContext(value);
 		return this;
 	}
 
 	@Override /* SerializerBuilder */
-	public JsonSerializerBuilder absolutePathUriBase(String value) {
-		super.absolutePathUriBase(value);
+	public JsonSerializerBuilder uriResolution(UriResolution value) {
+		super.uriResolution(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public JsonSerializerBuilder uriRelativity(UriRelativity value) {
+		super.uriRelativity(value);
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
index cb6783d..7cda1e9 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
@@ -96,6 +96,6 @@ public final class JsonSerializerSession extends SerializerSession {
 		Object output = getOutput();
 		if (output instanceof JsonWriter)
 			return (JsonWriter)output;
-		return new JsonWriter(super.getWriter(), isUseWhitespace(), isEscapeSolidus(), getQuoteChar(), isSimpleMode(), isTrimStrings(), getRelativeUriBase(), getAbsolutePathUriBase(), getUriContext());
+		return new JsonWriter(super.getWriter(), isUseWhitespace(), isEscapeSolidus(), getQuoteChar(), isSimpleMode(), isTrimStrings(), getUriResolver());
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/json/JsonWriter.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonWriter.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonWriter.java
index d08439c..2644123 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonWriter.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonWriter.java
@@ -61,13 +61,10 @@ public final class JsonWriter extends SerializerWriter {
 	 * @param quoteChar The quote character to use (i.e. <js>'\''</js> or <js>'"'</js>)
 	 * @param laxMode If <jk>true</jk>, JSON attributes will only be quoted when necessary.
 	 * @param trimStrings If <jk>true</jk>, strings will be trimmed before being serialized.
-	 * @param relativeUriBase The base (e.g. <js>https://localhost:9443/contextPath"</js>) for relative URIs (e.g. <js>"my/path"</js>).
-	 * @param absolutePathUriBase The base (e.g. <js>https://localhost:9443"</js>) for relative URIs with absolute paths (e.g. <js>"/contextPath/my/path"</js>).
-	 * @param uriContext The URI context.
-	 * 	Identifies the current request URI used for resolution of URIs to absolute or root-relative form.
+	 * @param uriResolver The URI resolver for resolving URIs to absolute or root-relative form.
 	 */
-	protected JsonWriter(Writer out, boolean useWhitespace, boolean escapeSolidus, char quoteChar, boolean laxMode, boolean trimStrings, String relativeUriBase, String absolutePathUriBase, UriContext uriContext) {
-		super(out, useWhitespace, trimStrings, quoteChar, relativeUriBase, absolutePathUriBase, uriContext);
+	protected JsonWriter(Writer out, boolean useWhitespace, boolean escapeSolidus, char quoteChar, boolean laxMode, boolean trimStrings, UriResolver uriResolver) {
+		super(out, useWhitespace, trimStrings, quoteChar, uriResolver);
 		this.laxMode = laxMode;
 		this.escapeSolidus = escapeSolidus;
 		this.ec = escapeSolidus ? encodedChars2 : encodedChars;
@@ -166,6 +163,16 @@ public final class JsonWriter extends SerializerWriter {
 		return this;
 	}
 
+	/**
+	 * Appends a URI to the output.
+	 *
+	 * @param uri The URI to append to the output.
+	 * @return This object (for method chaining).
+	 * @throws IOException
+	 */
+	public SerializerWriter uriValue(Object uri) throws IOException {
+		return stringValue(uriResolver.resolve(uri));
+	}
 
 	//--------------------------------------------------------------------------------
 	// Overridden methods

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
index 2c29538..36ebe9f 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
@@ -127,14 +127,20 @@ public class MsgPackSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public MsgPackSerializerBuilder relativeUriBase(String value) {
-		super.relativeUriBase(value);
+	public MsgPackSerializerBuilder uriContext(UriContext value) {
+		super.uriContext(value);
 		return this;
 	}
 
 	@Override /* SerializerBuilder */
-	public MsgPackSerializerBuilder absolutePathUriBase(String value) {
-		super.absolutePathUriBase(value);
+	public MsgPackSerializerBuilder uriResolution(UriResolution value) {
+		super.uriResolution(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public MsgPackSerializerBuilder uriRelativity(UriRelativity value) {
+		super.uriRelativity(value);
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/c4952d2c/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
index c91c1ba..596fed2 100644
--- a/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
@@ -127,14 +127,20 @@ public class PlainTextSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public PlainTextSerializerBuilder relativeUriBase(String value) {
-		super.relativeUriBase(value);
+	public PlainTextSerializerBuilder uriContext(UriContext value) {
+		super.uriContext(value);
 		return this;
 	}
 
 	@Override /* SerializerBuilder */
-	public PlainTextSerializerBuilder absolutePathUriBase(String value) {
-		super.absolutePathUriBase(value);
+	public PlainTextSerializerBuilder uriResolution(UriResolution value) {
+		super.uriResolution(value);
+		return this;
+	}
+
+	@Override /* SerializerBuilder */
+	public PlainTextSerializerBuilder uriRelativity(UriRelativity value) {
+		super.uriRelativity(value);
 		return this;
 	}