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/11/21 13:54:40 UTC

juneau git commit: Add maxInput REST setting for DoS attacks.

Repository: juneau
Updated Branches:
  refs/heads/master c0a503889 -> f67c7f285


Add maxInput REST setting for DoS attacks.

Project: http://git-wip-us.apache.org/repos/asf/juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/juneau/commit/f67c7f28
Tree: http://git-wip-us.apache.org/repos/asf/juneau/tree/f67c7f28
Diff: http://git-wip-us.apache.org/repos/asf/juneau/diff/f67c7f28

Branch: refs/heads/master
Commit: f67c7f28570ede9ceae33229f6faddb9fd8d76ef
Parents: c0a5038
Author: JamesBognar <ja...@apache.org>
Authored: Tue Nov 21 08:54:33 2017 -0500
Committer: JamesBognar <ja...@apache.org>
Committed: Tue Nov 21 08:54:33 2017 -0500

----------------------------------------------------------------------
 .../java/org/apache/juneau/ini/ConfigFile.java  |  50 +++--
 .../juneau/a/rttests/RoundTripBeanMapsTest.java |   4 +-
 .../org/apache/juneau/xml/XmlContentTest.java   |   8 +-
 .../java/org/apache/juneau/BeanContext.java     |  35 +++-
 .../org/apache/juneau/BeanPropertyMeta.java     |  12 +-
 .../java/org/apache/juneau/BeanRegistry.java    |   4 +-
 .../java/org/apache/juneau/BeanSession.java     |  33 ++++
 .../main/java/org/apache/juneau/ClassMeta.java  |   4 +-
 .../org/apache/juneau/CoreObjectBuilder.java    |   5 +-
 .../java/org/apache/juneau/PropertyStore.java   |   2 +-
 .../juneau/encoders/EncoderGroupBuilder.java    |   8 +-
 .../juneau/html/HtmlBeanPropertyMeta.java       |   3 +-
 .../org/apache/juneau/html/HtmlClassMeta.java   |   2 +-
 .../juneau/html/HtmlDocSerializerSession.java   |   3 +-
 .../org/apache/juneau/internal/ClassUtils.java  | 188 +++++--------------
 .../org/apache/juneau/internal/StringUtils.java |  62 ++++++
 .../juneau/parser/ParserGroupBuilder.java       |   3 +-
 .../org/apache/juneau/parser/ParserSession.java |   1 -
 .../OutputStreamSerializerSession.java          |   2 +-
 .../serializer/SerializerGroupBuilder.java      |   3 +-
 .../juneau/serializer/SerializerSession.java    |   2 +-
 .../serializer/WriterSerializerSession.java     |   2 +-
 .../transform/AnnotationBeanFilterBuilder.java  |   9 +-
 .../juneau/transform/BeanFilterBuilder.java     |   9 +-
 .../transform/InterfaceBeanFilterBuilder.java   |   7 +-
 .../urlencoding/UrlEncodingSerializer.java      |   2 +-
 .../org/apache/juneau/xml/XmlParserSession.java |   5 +-
 juneau-doc/src/main/javadoc/overview.html       |  32 +++-
 .../juneau/rest/client/RestRequestEntity.java   |   2 +-
 .../apache/juneau/rest/jaxrs/BaseProvider.java  |   2 +-
 .../java/org/apache/juneau/rest/CallMethod.java |  18 +-
 .../org/apache/juneau/rest/RequestBody.java     | 102 ++++++++--
 .../java/org/apache/juneau/rest/RestConfig.java |  18 +-
 .../org/apache/juneau/rest/RestContext.java     |  23 +++
 .../org/apache/juneau/rest/RestRequest.java     |   5 +-
 .../juneau/rest/annotation/RestMethod.java      |  18 ++
 .../juneau/rest/annotation/RestResource.java    |  18 ++
 .../juneau/rest/response/DefaultHandler.java    |   6 +-
 .../juneau/rest/widget/MenuItemWidget.java      |   2 +-
 39 files changed, 474 insertions(+), 240 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigFile.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigFile.java b/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigFile.java
index 2e197a8..914f106 100644
--- a/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigFile.java
+++ b/juneau-core/juneau-config/src/main/java/org/apache/juneau/ini/ConfigFile.java
@@ -672,7 +672,7 @@ public abstract class ConfigFile implements Map<String,Section> {
 	 * Convenience method for getting int config values.
 	 *
 	 * <p>
-	 * <js>"M"</js> and <js>"K"</js> can be used to identify millions and thousands.
+	 * <js>"K"</js>, <js>"M"</js>, and <js>"G"</js> can be used to identify kilo, mega, and giga.
 	 *
 	 * <h5 class='section'>Example:</h5>
 	 * <ul class='spaced-list'>
@@ -694,6 +694,41 @@ public abstract class ConfigFile implements Map<String,Section> {
 	}
 
 	/**
+	 * Convenience method for getting long config values.
+	 *
+	 * @param key The key.  See {@link #getString(String)} for a description of the key.
+	 * @return The value, or <code>0</code> if the section or key does not exist or cannot be parsed as a long.
+	 */
+	public final long getLong(String key) {
+		return getLong(key, 0);
+	}
+
+	/**
+	 * Convenience method for getting long config values.
+	 *
+	 * <p>
+	 * <js>"K"</js>, <js>"M"</js>, and <js>"G"</js> can be used to identify kilo, mega, and giga.
+	 *
+	 * <h5 class='section'>Example:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>
+	 * 		<code><js>"100K"</js> => 1024000</code>
+	 * 	<li>
+	 * 		<code><js>"100M"</js> => 104857600</code>
+	 * </ul>
+	 *
+	 * @param key The key.  See {@link #getString(String)} for a description of the key.
+	 * @param def The default value if config file or value does not exist.
+	 * @return The value, or the default value if the section or key does not exist or cannot be parsed as an integer.
+	 */
+	public final long getLong(String key, long def) {
+		String s = getString(key);
+		if (StringUtils.isEmpty(s))
+			return def;
+		return parseLongWithSuffix(s);
+	}
+
+	/**
 	 * Convenience method for getting boolean config values.
 	 *
 	 * @param key The key.  See {@link #getString(String)} for a description of the key.
@@ -1212,17 +1247,4 @@ public abstract class ConfigFile implements Map<String,Section> {
 		// Only ConfigFileWrapped returns a value.
 		return null;
 	}
-
-	private static int parseIntWithSuffix(String s) {
-		assertFieldNotNull(s, "s");
-		int m = 1;
-		if (s.endsWith("M")) {
-			m = 1024*1024;
-			s = s.substring(0, s.length()-1).trim();
-		} else if (s.endsWith("K")) {
-			m = 1024;
-			s = s.substring(0, s.length()-1).trim();
-		}
-		return Integer.parseInt(s) * m;
-	}
 }

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
index 3ae522b..9fc3671 100755
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
@@ -678,12 +678,12 @@ public class RoundTripBeanMapsTest extends RoundTripTest {
 	}
 	public static class FB1Filter extends InterfaceBeanFilterBuilder {
 		public FB1Filter() {
-			super(FB1.class);
+			super(BeanContext.DEFAULT, FB1.class);
 		}
 	}
 	public static class FB2Filter extends InterfaceBeanFilterBuilder {
 		public FB2Filter() {
-			super(FB1.class);
+			super(BeanContext.DEFAULT, FB1.class);
 		}
 	}
 

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/xml/XmlContentTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/xml/XmlContentTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/xml/XmlContentTest.java
index 7f832db..8b9f7b1 100755
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/xml/XmlContentTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/xml/XmlContentTest.java
@@ -48,7 +48,7 @@ public class XmlContentTest {
 
 		sw = new StringWriter();
 		session = s1.createSession(new SerializerSessionArgs(new ObjectMap("{"+SERIALIZER_trimNullProperties+":false}"), null, null, null, null, null));
-		session.serialize(sw, t);
+		session.serialize(t, sw);
 		r = sw.toString();
 		assertEquals("<A f1='f1'>_x0000_</A>", r);
 		t2 = p.parse(r, A.class);
@@ -56,7 +56,7 @@ public class XmlContentTest {
 
 		sw = new StringWriter();
 		session = s2.createSession(new SerializerSessionArgs(new ObjectMap("{"+SERIALIZER_trimNullProperties+":false}"), null, null, null, null, null));
-		session.serialize(sw, t);
+		session.serialize(t, sw);
 		r = sw.toString();
 		assertEquals("<A f1='f1'>_x0000_</A>\n", r);
 		t2 = p.parse(r, A.class);
@@ -156,7 +156,7 @@ public class XmlContentTest {
 
 		sw = new StringWriter();
 		session = s1.createSession(new SerializerSessionArgs(new ObjectMap("{"+SERIALIZER_trimNullProperties+":false}"), null, null, null, null, null));
-		session.serialize(sw, t);
+		session.serialize(t, sw);
 		r = sw.toString();
 		assertEquals("<A f1='f1'>_x0000_</A>", r);
 		t2 = p.parse(r, B.class);
@@ -164,7 +164,7 @@ public class XmlContentTest {
 
 		sw = new StringWriter();
 		session = s2.createSession(new SerializerSessionArgs(new ObjectMap("{"+SERIALIZER_trimNullProperties+":false}"), null, null, null, null, null));
-		session.serialize(sw, t);
+		session.serialize(t, sw);
 		r = sw.toString();
 		assertEquals("<A f1='f1'>_x0000_</A>\n", r);
 		t2 = p.parse(r, B.class);

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
index d7aaf79..81df6e7 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
@@ -1038,7 +1038,7 @@ public class BeanContext extends Context {
 			else if (isParentClass(BeanFilterBuilder.class, c))
 				lbf.add(newInstance(BeanFilterBuilder.class, c).build());
 			else
-				lbf.add(new InterfaceBeanFilterBuilder(c).build());
+				lbf.add(new InterfaceBeanFilterBuilder(this, c).build());
 		}
 		beanFilters = lbf.toArray(new BeanFilter[0]);
 
@@ -1691,6 +1691,39 @@ public class BeanContext extends Context {
 	}
 
 	/**
+	 * Creates an instance of the specified class without throwing exceptions.
+	 *
+	 * @param c The class to cast to.
+	 * @param c2
+	 * 	The class to instantiate.
+	 * 	Can also be an instance of the class.
+	 * @param args The arguments to pass to the constructor.
+	 * @return The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface.
+	 * @throws RuntimeException if constructor could not be found or called.
+	 */
+	public <T> T newInstance(Class<T> c, Object c2, Object...args) {
+		return newInstanceFromOuter(null, c, c2, args);
+	}
+
+	/**
+	 * Creates an instance of the specified class from within the context of another object.
+	 *
+	 * @param outer
+	 * 	The outer object.
+	 * 	Can be <jk>null</jk>.
+	 * @param c The class to cast to.
+	 * @param c2
+	 * 	The class to instantiate.
+	 * 	Can also be an instance of the class.
+	 * @param args The arguments to pass to the constructor.
+	 * @return The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface.
+	 * @throws RuntimeException if constructor could not be found or called.
+	 */
+	public <T> T newInstanceFromOuter(Object outer, Class<T> c, Object c2, Object...args) {
+		return ClassUtils.newInstanceFromOuter(outer, c, c2, args);
+	}
+	
+	/**
 	 * Returns a reusable {@link ClassMeta} representation for the class <code>Object</code>.
 	 *
 	 * <p>

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
index 412cc9c..e157275 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
@@ -268,20 +268,20 @@ public final class BeanPropertyMeta {
 			return new BeanPropertyMeta(this);
 		}
 
-		private static PojoSwap getPropertyPojoSwap(BeanProperty p) throws Exception {
+		private PojoSwap getPropertyPojoSwap(BeanProperty p) throws Exception {
 			if (! p.format().isEmpty())
-				return newInstance(PojoSwap.class, StringFormatSwap.class, p.format());
+				return beanContext.newInstance(PojoSwap.class, StringFormatSwap.class, p.format());
 			return null;
 		}
 
-		private static PojoSwap getPropertyPojoSwap(Swap s) throws Exception {
+		private PojoSwap getPropertyPojoSwap(Swap s) throws Exception {
 			Class<?> c = s.value();
 			if (c == Null.class)
 				c = s.impl();
 			if (c == Null.class)
 				return null;
 			if (isParentClass(PojoSwap.class, c)) {
-				PojoSwap ps = newInstance(PojoSwap.class, c);
+				PojoSwap ps = beanContext.newInstance(PojoSwap.class, c);
 				if (ps.forMediaTypes() != null)
 					throw new RuntimeException("TODO - Media types on swaps not yet supported on bean properties.");
 				if (ps.withTemplate() != null)
@@ -639,7 +639,7 @@ public final class BeanPropertyMeta {
 						}
 					} else {
 						if (propMap == null) {
-							propMap = newInstance(Map.class, propertyClass);
+							propMap = beanContext.newInstance(Map.class, propertyClass);
 						} else {
 							propMap.clear();
 						}
@@ -695,7 +695,7 @@ public final class BeanPropertyMeta {
 						propList.clear();
 					} else {
 						if (propList == null) {
-							propList = newInstance(Collection.class, propertyClass);
+							propList = beanContext.newInstance(Collection.class, propertyClass);
 							invokeSetter(bean, pName, propList);
 						} else {
 							propList.clear();

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanRegistry.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanRegistry.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanRegistry.java
index 819b536..7839f8b 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanRegistry.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanRegistry.java
@@ -65,7 +65,7 @@ public class BeanRegistry {
 			if (c != null) {
 				if (isParentClass(Collection.class, c)) {
 					@SuppressWarnings("rawtypes")
-					Collection cc = newInstance(Collection.class, c);
+					Collection cc = beanContext.newInstance(Collection.class, c);
 					for (Object o : cc) {
 						if (o instanceof Class)
 							addClass((Class<?>)o);
@@ -73,7 +73,7 @@ public class BeanRegistry {
 							throw new BeanRuntimeException("Collection class ''{0}'' passed to BeanRegistry does not contain Class objects.", c.getName());
 					}
 				} else if (isParentClass(Map.class, c)) {
-					Map<?,?> m = newInstance(Map.class, c);
+					Map<?,?> m = beanContext.newInstance(Map.class, c);
 					for (Map.Entry<?,?> e : m.entrySet()) {
 						String typeName = StringUtils.toString(e.getKey());
 						Object v = e.getValue();

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java
index eabbdee..3f54c45 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanSession.java
@@ -994,8 +994,41 @@ public class BeanSession extends Session {
 	public final BeanRegistry getBeanRegistry() {
 		return ctx.beanRegistry;
 	}
+	
+	/**
+	 * Shortcut for calling {@link BeanContext#newInstance(Class, Object, Object...)}.
+	 *
+	 * @param c The class to cast to.
+	 * @param c2
+	 * 	The class to instantiate.
+	 * 	Can also be an instance of the class.
+	 * @param args The arguments to pass to the constructor.
+	 * @return The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface.
+	 * @throws RuntimeException if constructor could not be found or called.
+	 */
+	public <T> T newInstance(Class<T> c, Object c2, Object...args) {
+		return ctx.newInstance(c, c2, args);
+	}
 
 	/**
+	 * Shortcut for calling {@link BeanContext#newInstanceFromOuter(Object, Class, Object, Object...)}.
+	 *
+	 * @param outer
+	 * 	The outer object.
+	 * 	Can be <jk>null</jk>.
+	 * @param c The class to cast to.
+	 * @param c2
+	 * 	The class to instantiate.
+	 * 	Can also be an instance of the class.
+	 * @param args The arguments to pass to the constructor.
+	 * @return The new class instance, or <jk>null</jk> if the class was <jk>null</jk> or is abstract or an interface.
+	 * @throws RuntimeException if constructor could not be found or called.
+	 */
+	public <T> T newInstanceFromOuter(Object outer, Class<T> c, Object c2, Object...args) {
+		return ctx.newInstanceFromOuter(outer, c, c2, args);
+	}
+	
+	/**
 	 * Creates a reusable {@link StringBuilder} object from an internal pool.
 	 *
 	 * <p>

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
index ee5dd7f..c515962 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
@@ -661,7 +661,7 @@ public final class ClassMeta<T> implements Type {
 			try {
 				Map<Class<?>,Bean> ba = findAnnotationsMap(Bean.class, innerClass);
 				if (! ba.isEmpty())
-					return new AnnotationBeanFilterBuilder(innerClass, ba).build();
+					return new AnnotationBeanFilterBuilder(beanContext, innerClass, ba).build();
 			} catch (Exception e) {
 				throw new RuntimeException(e);
 			}
@@ -684,7 +684,7 @@ public final class ClassMeta<T> implements Type {
 				c = s.impl();
 
 			if (isParentClass(PojoSwap.class, c)) {
-				PojoSwap ps = ClassUtils.newInstance(PojoSwap.class, c);
+				PojoSwap ps = beanContext.newInstance(PojoSwap.class, c);
 				if (s.mediaTypes().length > 0)
 					ps.forMediaTypes(MediaType.forStrings(s.mediaTypes()));
 				if (! s.template().isEmpty())

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/CoreObjectBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/CoreObjectBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/CoreObjectBuilder.java
index 74bbdb8..cf747f6 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/CoreObjectBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/CoreObjectBuilder.java
@@ -13,7 +13,6 @@
 package org.apache.juneau;
 
 import static org.apache.juneau.BeanContext.*;
-import static org.apache.juneau.internal.ClassUtils.*;
 
 import java.beans.*;
 import java.io.*;
@@ -78,7 +77,7 @@ public abstract class CoreObjectBuilder {
 	 */
 	@SuppressWarnings("unchecked")
 	public <T extends CoreObject> T build(Class<T> c) {
-		return (T)newInstance(CoreObject.class, c, propertyStore);
+		return (T)propertyStore.getBeanContext().newInstance(CoreObject.class, c, propertyStore);
 	}
 
 	//--------------------------------------------------------------------------------
@@ -1577,7 +1576,7 @@ public abstract class CoreObjectBuilder {
 	public CoreObjectBuilder mediaType(MediaType value) {
 		return property(BEAN_mediaType, value);
 	}
-
+	
 	/**
 	 * <b>Configuration property:</b>  Debug mode.
 	 *

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyStore.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyStore.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyStore.java
index d7cf23e..c8d4325 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyStore.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyStore.java
@@ -719,7 +719,7 @@ public final class PropertyStore {
 			if (pm != null)
 				o = pm.get(name, type, null);
 			if (o == null && def != null)
-				o = ClassUtils.newInstance(type, def, args);
+				o = getBeanSession().newInstance(type, def, args);
 			if (o == null)
 				return null;
 			if (ClassUtils.isParentClass(type, o.getClass()))

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
index 6e05a5a..80e3044 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/encoders/EncoderGroupBuilder.java
@@ -13,16 +13,18 @@
 package org.apache.juneau.encoders;
 
 import static org.apache.juneau.internal.CollectionUtils.*;
-import static org.apache.juneau.internal.ClassUtils.*;
 
 import java.util.*;
 
+import org.apache.juneau.*;
+
 /**
  * Builder class for creating instances of {@link EncoderGroup}.
  */
 public class EncoderGroupBuilder {
 
 	private final List<Encoder> encoders;
+	private BeanContext beanContext = BeanContext.DEFAULT;
 
 	/**
 	 * Create an empty encoder group builder.
@@ -49,7 +51,7 @@ public class EncoderGroupBuilder {
 	 */
 	public EncoderGroupBuilder append(Class<?>...e) {
 		for (int i = e.length-1; i >= 0; i--)
-			encoders.add(newInstance(Encoder.class, e[i]));
+			encoders.add(beanContext.newInstance(Encoder.class, e[i]));
 		return this;
 	}
 
@@ -97,7 +99,7 @@ public class EncoderGroupBuilder {
 	public EncoderGroup build() {
 		List<Encoder> l = new ArrayList<>();
 		for (Object e : encoders)
-			l.add(newInstance(Encoder.class, e));
+			l.add(beanContext.newInstance(Encoder.class, e));
 		Collections.reverse(l);
 		return new EncoderGroup(l.toArray(new Encoder[l.size()]));
 	}

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
index 4ffc57e..b457d4c 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlBeanPropertyMeta.java
@@ -14,7 +14,6 @@ package org.apache.juneau.html;
 
 import org.apache.juneau.*;
 import org.apache.juneau.html.annotation.*;
-import org.apache.juneau.internal.*;
 
 /**
  * Metadata on bean properties specific to the HTML serializers and parsers pulled from the {@link Html @Html}
@@ -47,7 +46,7 @@ public final class HtmlBeanPropertyMeta extends BeanPropertyMetaExtended {
 		this.noTables = b.noTables;
 		this.noTableHeaders = b.noTableHeaders;
 		this.asPlainText = b.asPlainText;
-		this.render = ClassUtils.newInstance(HtmlRender.class, b.render);
+		this.render = bpm.getBeanMeta().getClassMeta().getBeanContext().newInstance(HtmlRender.class, b.render);
 		this.link = b.link;
 		this.anchorText = b.anchorText;
 	}

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlClassMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlClassMeta.java
index a30d977..7db2840 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlClassMeta.java
@@ -39,7 +39,7 @@ public class HtmlClassMeta extends ClassMetaExtended {
 			noTables = html.noTables();
 			noTableHeaders = html.noTableHeaders();
 			asPlainText = html.asPlainText();
-			render = ClassUtils.newInstance(HtmlRender.class, html.render());
+			render = cm.getBeanContext().newInstance(HtmlRender.class, html.render());
 		} else {
 			asXml = false;
 			noTables = false;

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
index f107823..6a7dd94 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializerSession.java
@@ -15,7 +15,6 @@ package org.apache.juneau.html;
 import static org.apache.juneau.html.HtmlDocSerializer.*;
 
 import org.apache.juneau.*;
-import org.apache.juneau.internal.*;
 import org.apache.juneau.serializer.*;
 
 /**
@@ -58,7 +57,7 @@ public class HtmlDocSerializerSession extends HtmlStrippedDocSerializerSession {
 		head = p.getStringArray(HTMLDOC_head, ctx.head);
 		nowrap = p.getBoolean(HTMLDOC_nowrap, ctx.nowrap);
 		noResultsMessage = p.getString(HTMLDOC_noResultsMessage, ctx.noResultsMessage);
-		template = ClassUtils.newInstance(HtmlDocTemplate.class, p.getWithDefault(HTMLDOC_template, ctx.template));
+		template = ctx.newInstance(HtmlDocTemplate.class, p.getWithDefault(HTMLDOC_template, ctx.template));
 	}
 
 	@Override /* Session */

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java
index 2858649..408548a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/ClassUtils.java
@@ -16,6 +16,7 @@ import java.io.*;
 import java.lang.annotation.*;
 import java.lang.reflect.*;
 import java.util.*;
+import java.util.concurrent.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.utils.*;
@@ -540,31 +541,19 @@ public final class ClassUtils {
 	 * 	Can be a super type of the actual return type.
 	 * 	For example, if the actual return type is <code>CharSequence</code>, then <code>Object</code> will match but
 	 * 	<code>String</code> will not.
-	 * @param parameterTypes
-	 * 	The parameter types of the method.
+	 * @param argTypes
+	 * 	The argument types of the method.
 	 * 	Can be subtypes of the actual parameter types.
 	 * 	For example, if the parameter type is <code>CharSequence</code>, then <code>String</code> will match but
 	 * 	<code>Object</code> will not.
 	 * @return The matched method, or <jk>null</jk> if no match was found.
 	 */
-	public static Method findPublicMethod(Class<?> c, String name, Class<?> returnType, Class<?>...parameterTypes) {
+	public static Method findPublicMethod(Class<?> c, String name, Class<?> returnType, Class<?>...argTypes) {
 		for (Method m : c.getMethods()) {
 			if (isPublic(m) && m.getName().equals(name)) {
 				Class<?> rt = m.getReturnType();
-				if (isParentClass(returnType, rt)) {
-					Class<?>[] pt = m.getParameterTypes();
-					if (pt.length == parameterTypes.length) {
-						boolean matches = true;
-						for (int i = 0; i < pt.length; i++) {
-							if (! isParentClass(pt[i], parameterTypes[i])) {
-								matches = false;
-								break;
-							}
-						}
-						if (matches)
-							return m;
-					}
-				}
+				if (isParentClass(returnType, rt) && argsMatch(m.getParameterTypes(), argTypes)) 
+					return m;
 			}
 		}
 		return null;
@@ -574,31 +563,55 @@ public final class ClassUtils {
 	 * Finds a public constructor with the specified parameters without throwing an exception.
 	 *
 	 * @param c The class to search for a constructor.
-	 * @param parameterTypes
-	 * 	The parameter types in the constructor.
+	 * @param argTypes
+	 * 	The argument types in the constructor.
 	 * 	Can be subtypes of the actual constructor argument types.
 	 * @return The matching constructor, or <jk>null</jk> if constructor could not be found.
 	 */
 	@SuppressWarnings("unchecked")
-	public static <T> Constructor<T> findPublicConstructor(Class<T> c, Class<?>...parameterTypes) {
+	public static <T> Constructor<T> findPublicConstructor(Class<T> c, Class<?>...argTypes) {
+		ConstructorCacheEntry cce = CONSTRUCTOR_CACHE.get(c);
+		if (cce != null && argsMatch(cce.paramTypes, argTypes)) 
+			return (Constructor<T>)cce.constructor;
+		
 		for (Constructor<?> n : c.getConstructors()) {
-			if (isPublic(n)) {
-				Class<?>[] pt = n.getParameterTypes();
-				if (pt.length == parameterTypes.length) {
-					boolean matches = true;
-					for (int i = 0; i < pt.length; i++) {
-						if (! isParentClass(pt[i], parameterTypes[i])) {
-							matches = false;
-							break;
-						}
-					}
-					if (matches)
-						return (Constructor<T>)n;
-				}
+			if (isPublic(n) && argsMatch(n.getParameterTypes(), argTypes)) {
+				CONSTRUCTOR_CACHE.put(c, new ConstructorCacheEntry(c, n));
+				return (Constructor<T>)n;
 			}
 		}
 		return null;
 	}
+	
+	private static final class ConstructorCacheEntry {
+		final Constructor<?> constructor;
+		final Class<?>[] paramTypes;
+		
+		ConstructorCacheEntry(Class<?> forClass, Constructor<?> constructor) {
+			this.constructor = constructor;
+			this.paramTypes = constructor.getParameterTypes();
+		}
+	}
+	
+	private static final Map<Class<?>,ConstructorCacheEntry> CONSTRUCTOR_CACHE = new ConcurrentHashMap<>();
+	
+	/**
+	 * Returns <jk>true</jk> if the specified argument types are valid for the specified parameter types.
+	 * 
+	 * @param paramTypes The parameters types specified on a method.
+	 * @param argTypes The class types of the arguments being passed to the method.
+	 * @return <jk>true</jk> if the arguments match the parameters.
+	 */
+	public static boolean argsMatch(Class<?>[] paramTypes, Class<?>[] argTypes) {
+		if (paramTypes.length == argTypes.length) {
+			for (int i = 0; i < paramTypes.length; i++) 
+				if (! isParentClass(paramTypes[i], argTypes[i])) 
+					return false;
+			return true;
+		}
+		return false;
+	}
+	
 
 	/**
 	 * Finds the public constructor that can take in the specified arguments.
@@ -626,115 +639,6 @@ public final class ClassUtils {
 		return pt;
 	}
 
-// This code is inherently unsafe (but still potentially useful?)
-//
-//	/**
-//	 * Converts class name strings to ClassMeta objects.
-//	 *
-//	 * <h5 class='section'>Example:</h5>
-//	 * <ul>
-//	 * 	<li><js>"java.lang.String"</js>
-//	 * 	<li><js>"com.foo.sample.MyBean[]"</js>
-//	 * 	<li><js>"java.util.HashMap<java.lang.String,java.lang.Integer>"</js>
-//	 * 	<li><js>"[Ljava.lang.String;"</js> (i.e. the value of <code>String[].<jk>class</jk>.getName()</code>)
-//	 * </ul>
-//	 *
-//	 * @param s The class name.
-//	 * @return The ClassMeta corresponding to the class name string.
-//	 */
-//	protected final ClassMeta<?> getClassMetaFromString(String s) {
-//		int d = 0;
-//		if (s == null || s.isEmpty())
-//			return null;
-//
-//		// Check for Class.getName() on array class types.
-//		if (s.charAt(0) == '[') {
-//			try {
-//				return getClassMeta(findClass(s));
-//			} catch (ClassNotFoundException e) {
-//				throw new RuntimeException(e);
-//			}
-//		}
-//
-//		int i1 = 0;
-//		int i2 = 0;
-//		int dim = 0;
-//		List<ClassMeta<?>> p = null;
-//		for (int i = 0; i < s.length(); i++) {
-//			char c = s.charAt(i);
-//			if (c == '<') {
-//				if (d == 0) {
-//					i1 = i;
-//					i2 = i+1;
-//					p = new LinkedList<ClassMeta<?>>();
-//				}
-//				d++;
-//			} else if (c == '>') {
-//				d--;
-//				if (d == 0 && p != null)
-//					p.add(getClassMetaFromString(s.substring(i2, i)));
-//			} else if (c == ',' && d == 1) {
-//				if (p != null)
-//					p.add(getClassMetaFromString(s.substring(i2, i)));
-//				i2 = i+1;
-//			}
-//			if (c == '[') {
-//				if (i1 == 0)
-//					i1 = i;
-//				dim++;
-//			}
-//		}
-//		if (i1 == 0)
-//			i1 = s.length();
-//		try {
-//			String name = s.substring(0, i1).trim();
-//			char x = name.charAt(0);
-//			Class<?> c = null;
-//			if (x >= 'b' && x <= 's') {
-//				if (x == 'b' && name.equals("boolean"))
-//					c = boolean.class;
-//				else if (x == 'b' && name.equals("byte"))
-//					c = byte.class;
-//				else if (x == 'c' && name.equals("char"))
-//					c = char.class;
-//				else if (x == 'd' && name.equals("double"))
-//					c = double.class;
-//				else if (x == 'i' && name.equals("int"))
-//					c = int.class;
-//				else if (x == 'l' && name.equals("long"))
-//					c = long.class;
-//				else if (x == 's' && name.equals("short"))
-//					c = short.class;
-//				else
-//					c = findClass(name);
-//			} else {
-//				c = findClass(name);
-//			}
-//
-//			ClassMeta<?> cm = getClassMeta(c);
-//
-//			if (p != null) {
-//				if (cm.isMap())
-//					cm = new ClassMeta(c, this).setKeyType(p.get(0)).setValueType(p.get(1));
-//				if (cm.isCollection())
-//					cm = new ClassMeta(c, this).setElementType(p.get(0));
-//			}
-//
-//			while (dim > 0) {
-//				cm = new ClassMeta(Array.newInstance(cm.getInnerClass(), 0).getClass(), this);
-//				dim--;
-//			}
-//
-//			return cm;
-//		} catch (ClassNotFoundException e) {
-//			throw new RuntimeException(e);
-//		}
-//	}
-//
-//	private Class<?> findClass(String name) throws ClassNotFoundException {
-//		return classLoader == null ? Class.forName(name) : Class.forName(name, true, classLoader);
-//	}
-
 	/**
 	 * Returns a {@link MethodInfo} bean that describes the specified method.
 	 *

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
index d237331..5e6d058 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
@@ -1686,6 +1686,8 @@ public final class StringUtils {
 			return null;
 		if (o instanceof ClassMeta)
 			return ((ClassMeta<?>)o).getReadableName();
+		if (BeanContext.DEFAULT == null)
+			return o.toString();
 		ClassMeta<?> cm = BeanContext.DEFAULT.getClassMetaForObject(o);
 		if (cm.isMapOrBean() || cm.isCollectionOrArray())
 			return JsonSerializer.DEFAULT_LAX.toString(o);
@@ -1695,4 +1697,64 @@ public final class StringUtils {
 			return ClassUtils.toString((Method)o);
 		return o.toString();
 	}
+	
+	/**
+	 * Converts a string containing a possible multiplier suffix to an integer.
+	 * 
+	 * <p>
+	 * The string can contain any of the following multiplier suffixes:
+	 * <ul>
+	 * 	<li><js>"K"</js> - x 1024
+	 * 	<li><js>"M"</js> - x 1024*1024
+	 * 	<li><js>"G"</js> - x 1024*1024*1024
+	 * </ul>
+	 * 
+	 * @param s The string to parse.
+	 * @return The parsed value.
+	 */
+	public static int parseIntWithSuffix(String s) {
+		assertFieldNotNull(s, "s");
+		int m = 1;
+		if (s.endsWith("G")) {
+			m = 1024*1024*1024;
+			s = s.substring(0, s.length()-1).trim();
+		} else if (s.endsWith("M")) {
+			m = 1024*1024;
+			s = s.substring(0, s.length()-1).trim();
+		} else if (s.endsWith("K")) {
+			m = 1024;
+			s = s.substring(0, s.length()-1).trim();
+		}
+		return Integer.parseInt(s) * m;
+	}
+	
+	/**
+	 * Converts a string containing a possible multiplier suffix to a long.
+	 * 
+	 * <p>
+	 * The string can contain any of the following multiplier suffixes:
+	 * <ul>
+	 * 	<li><js>"K"</js> - x 1024
+	 * 	<li><js>"M"</js> - x 1024*1024
+	 * 	<li><js>"G"</js> - x 1024*1024*1024
+	 * </ul>
+	 * 
+	 * @param s The string to parse.
+	 * @return The parsed value.
+	 */
+	public static long parseLongWithSuffix(String s) {
+		assertFieldNotNull(s, "s");
+		int m = 1;
+		if (s.endsWith("G")) {
+			m = 1024*1024*1024;
+			s = s.substring(0, s.length()-1).trim();
+		} else if (s.endsWith("M")) {
+			m = 1024*1024;
+			s = s.substring(0, s.length()-1).trim();
+		} else if (s.endsWith("K")) {
+			m = 1024;
+			s = s.substring(0, s.length()-1).trim();
+		}
+		return Long.parseLong(s) * m;
+	}
 }

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
index cf0568e..38d74fa 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
@@ -14,7 +14,6 @@ package org.apache.juneau.parser;
 
 import static org.apache.juneau.BeanContext.*;
 import static org.apache.juneau.internal.CollectionUtils.*;
-import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.parser.Parser.*;
 
 import java.util.*;
@@ -117,7 +116,7 @@ public class ParserGroupBuilder {
 				ps = p2.createPropertyStore().copyFrom(propertyStore);
 				c = p2.getClass();
 			}
-			l.add(newInstance(Parser.class, c, ps));
+			l.add(propertyStore.getBeanContext().newInstance(Parser.class, c, ps));
 		}
 		Collections.reverse(l);
 		return new ParserGroup(propertyStore, l.toArray(new Parser[l.size()]));

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java
index c18146f..3ed5fba 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java
@@ -13,7 +13,6 @@
 package org.apache.juneau.parser;
 
 import static org.apache.juneau.parser.Parser.*;
-import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
 
 import java.io.*;

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerSession.java
index f0637f5..b03688e 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerSession.java
@@ -68,7 +68,7 @@ public abstract class OutputStreamSerializerSession extends SerializerSession {
 	@Override /* SerializerSession */
 	public final byte[] serialize(Object o) throws SerializeException {
 		ByteArrayOutputStream baos = new ByteArrayOutputStream();
-		serialize(baos, o);
+		serialize(o, baos);
 		return baos.toByteArray();
 	}
 }

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
index 3c49f23..b744cf9 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
@@ -14,7 +14,6 @@ package org.apache.juneau.serializer;
 
 import static org.apache.juneau.BeanContext.*;
 import static org.apache.juneau.internal.CollectionUtils.*;
-import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.serializer.Serializer.*;
 
 import java.util.*;
@@ -117,7 +116,7 @@ public class SerializerGroupBuilder {
 				ps = s2.createPropertyStore().copyFrom(propertyStore);
 				c = s2.getClass();
 			}
-			l.add(newInstance(Serializer.class, c, ps));
+			l.add(propertyStore.getBeanContext().newInstance(Serializer.class, c, ps));
 		}
 		Collections.reverse(l);
 		return new SerializerGroup(propertyStore, l.toArray(new Serializer[l.size()]));

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java
index e2251dc..6495128 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java
@@ -229,7 +229,7 @@ public abstract class SerializerSession extends BeanSession {
 	 * @param o The object to serialize.
 	 * @throws SerializeException If a problem occurred trying to convert the output.
 	 */
-	public final void serialize(Object out, Object o) throws SerializeException {
+	public final void serialize(Object o, Object out) throws SerializeException {
 		try (SerializerPipe pipe = createPipe(out)) {
 			doSerialize(pipe, o);
 		} catch (SerializeException e) {

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerSession.java
index fdea9d3..accf31c 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerSession.java
@@ -73,7 +73,7 @@ public abstract class WriterSerializerSession extends SerializerSession {
 	@Override /* SerializerSession */
 	public final String serialize(Object o) throws SerializeException {
 		StringWriter w = new StringWriter();
-		serialize(w, o);
+		serialize(o, w);
 		return w.toString();
 	}
 }

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/AnnotationBeanFilterBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/AnnotationBeanFilterBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/AnnotationBeanFilterBuilder.java
index c5b0fee..b99409b 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/AnnotationBeanFilterBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/AnnotationBeanFilterBuilder.java
@@ -29,13 +29,16 @@ public final class AnnotationBeanFilterBuilder extends BeanFilterBuilder {
 
 	/**
 	 * Constructor.
-	 *
+	 * 
+	 * @param bc 
+	 * 	The bean context creating this builder.  
+	 * 	Used to instantiate {@link PropertyNamer PropertyNamers}. 
 	 * @param annotatedClass The class found to have a {@link Bean @Bean} annotation.
 	 * @param annotations
 	 * 	The {@link Bean @Bean} annotations found on the class and all parent classes in child-to-parent order.
 	 * @throws Exception Thrown from property namer constructor.
 	 */
-	public AnnotationBeanFilterBuilder(Class<?> annotatedClass, Map<Class<?>,Bean> annotations) throws Exception {
+	public AnnotationBeanFilterBuilder(BeanContext bc, Class<?> annotatedClass, Map<Class<?>,Bean> annotations) throws Exception {
 		super(annotatedClass);
 
 		ListIterator<Bean> li = new ArrayList<>(annotations.values()).listIterator(annotations.size());
@@ -55,7 +58,7 @@ public final class AnnotationBeanFilterBuilder extends BeanFilterBuilder {
 				excludeProperties(split(b.excludeProperties()));
 
 			if (b.propertyNamer() != PropertyNamerDefault.class)
-				propertyNamer(b.propertyNamer());
+				propertyNamer(bc, b.propertyNamer());
 
 			if (b.interfaceClass() != Object.class)
 				interfaceClass(b.interfaceClass());

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/BeanFilterBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/BeanFilterBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/BeanFilterBuilder.java
index 2b472ba..71003e7 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/BeanFilterBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/BeanFilterBuilder.java
@@ -12,8 +12,6 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.transform;
 
-import static org.apache.juneau.internal.ClassUtils.*;
-
 import java.beans.*;
 import java.util.*;
 
@@ -205,13 +203,14 @@ public abstract class BeanFilterBuilder {
 
 	/**
 	 * The property namer to use to name bean properties.
-	 *
+	 * 
+	 * @param bc The bean context used to instantiate the property namer. 
 	 * @param c The property namer class.  Must have a public no-arg constructor.
 	 * @return This object (for method chaining).
 	 * @throws Exception Thrown from constructor method.
 	 */
-	public BeanFilterBuilder propertyNamer(Class<? extends PropertyNamer> c) throws Exception {
-		this.propertyNamer = newInstance(PropertyNamer.class, c);
+	public BeanFilterBuilder propertyNamer(BeanContext bc, Class<? extends PropertyNamer> c) throws Exception {
+		this.propertyNamer = bc.newInstance(PropertyNamer.class, c);
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/InterfaceBeanFilterBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/InterfaceBeanFilterBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/InterfaceBeanFilterBuilder.java
index bfcfa63..685789d 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/InterfaceBeanFilterBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/InterfaceBeanFilterBuilder.java
@@ -32,10 +32,11 @@ public class InterfaceBeanFilterBuilder extends BeanFilterBuilder {
 
 	/**
 	 * Constructor.
-	 *
+	 * 
+	 * @param bc Bean context used for instantiating {@link PropertyNamer} instances. 
 	 * @param interfaceClass The class to use as an interface on all child classes.
 	 */
-	public InterfaceBeanFilterBuilder(Class<?> interfaceClass) {
+	public InterfaceBeanFilterBuilder(BeanContext bc, Class<?> interfaceClass) {
 		super(interfaceClass);
 		interfaceClass(interfaceClass);
 		Map<Class<?>,Bean> annotations = ReflectionUtils.findAnnotationsMap(Bean.class, interfaceClass);
@@ -58,7 +59,7 @@ public class InterfaceBeanFilterBuilder extends BeanFilterBuilder {
 
 			try {
 				if (b.propertyNamer() != PropertyNamerDefault.class)
-					propertyNamer(b.propertyNamer());
+					propertyNamer(bc, b.propertyNamer());
 			} catch (Exception e) {
 				throw new RuntimeException(e);
 			}

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
index a26c059..22e5c66 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
@@ -325,7 +325,7 @@ public class UrlEncodingSerializer extends UonSerializer implements PartSerializ
 
 			StringWriter w = new StringWriter();
 			UonSerializerSession s = new UonSerializerSession(ctx, urlEncode, createDefaultSessionArgs());
-			s.serialize(w, o);
+			s.serialize(o, w);
 			return w.toString();
 		} catch (Exception e) {
 			throw new RuntimeException(e);

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java
index 232f722..f39c6e2 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java
@@ -475,11 +475,12 @@ public class XmlParserSession extends ReaderParserSession {
 		for (int i = 0; i < r.getAttributeCount(); i++) {
 			String key = getAttributeName(r, i);
 			String val = r.getAttributeValue(i);
+			String ns = r.getAttributeNamespace(i);
 			BeanPropertyMeta bpm = xmlMeta.getPropertyMeta(key);
 			if (bpm == null) {
 				if (xmlMeta.getAttrsProperty() != null) {
 					xmlMeta.getAttrsProperty().add(m, key, key, val);
-				} else {
+				} else if (ns == null) {
 					Location l = r.getLocation();
 					onUnknownProperty(r.getPipe(), key, m, l.getLineNumber(), l.getColumnNumber());
 				}
@@ -593,6 +594,8 @@ public class XmlParserSession extends ReaderParserSession {
 						throw new ParseException("End element found where one was not expected.  {0}", XmlUtils.toReadableEvent(r));
 				}
 				depth--;
+			} else if (event == COMMENT) {
+				// Ignore comments.
 			} else {
 				throw new ParseException("Unexpected event type: {0}", XmlUtils.toReadableEvent(r));
 			}

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-doc/src/main/javadoc/overview.html
----------------------------------------------------------------------
diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html
index b2b84ec..585fd3f 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -1862,7 +1862,7 @@
 				<tr><th>Group</th><th>Description</th><th>Examples</th><th>Can<br>serialize?</th><th>Can<br>parse?</th></tr>
 				<tr class='dark bb' style='background-color:lightyellow;'>
 					<td style='text-align:center'>1</td>
-					<td><b>Java primitive objects</b></td>
+					<td><b>Java primitives and primitive objects</b></td>
 					<td>
 						<ul class='normal'>
 							<li>{@code String}
@@ -1926,8 +1926,9 @@
 					<td style='text-align:center'>3a</td>
 					<td>
 						<b>With standard properties</b>
-						<br>These are beans that have no-arg constructors and one or more properties defined by public getter 
-						and setter methods or public fields.
+						<br>These are beans that have one or more properties defined by public getter 
+						or public fields.
+						<br>Properties can also be defined as final read-only fields and passed in as constructor args.
 						<br>Property values are group [1, 2, 3ac, 4a, 6a] objects.
 					</td>
 					<td>&nbsp;</td>
@@ -1938,7 +1939,7 @@
 					<td style='text-align:center'>3b</td>
 					<td>
 						<b>With non-standard properties or not true beans</b>
-						<br>These include true beans that have no-arg constructors and one or more properties defined by getter 
+						<br>These include true beans that have one or more properties defined by getter 
 						and setter methods or properties, but property types include group [3b, 4b, 5, 6b, 7] objects.
 						<br>This also includes classes that look like beans but aren't true beans.  
 						For example, classes that have getters but not setters, or classes without no-arg constructors.	
@@ -1958,6 +1959,16 @@
 					<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
 					<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
 				</tr>		
+				<tr class='light bb'>
+					<td style='text-align:center'>3d</td>
+					<td>
+						<b>Read-only beans without setters</b>
+						<br>The same as 3a, but without property setters or constructor args.
+					</td>
+					<td>&nbsp;</td>
+					<td style='background-color:lightgreen;text-align:center'><b>yes</b></td>
+					<td style='background-color:salmon;text-align:center'><b>no</b></td>
+				</tr>		
 				<tr class='dark bb' style='background-color:lightyellow'>
 					<td style='text-align:center'>4</td>
 					<td>
@@ -2009,6 +2020,8 @@
 					<td>
 						<b>Readers and InputStreams</b>
 						<br>Contents are serialized directly to the output stream or writer.
+						<br>Typically used for low-level language-specific replacement of POJOs using per-Media-Type 
+						POJO swaps.
 					</td>
 					<td>					
 						<ul class='normal'>
@@ -7469,6 +7482,9 @@
 					<li>{@link org.apache.juneau.rest.client.RestClient#create()}
 					<li>{@link org.apache.juneau.ini.ConfigFile#create()}
 				</ul>
+			<li>
+				The order of the parameters in {@link org.apache.juneau.serializer.SerializerSession#serialize(Object,Object)}
+				has been change to match {@link org.apache.juneau.serializer.Serializer#serialize(Object,Object)}.	
 		</ul>
 
 		<h6 class='topic'>juneau-marshall-rdf</h6>
@@ -7485,6 +7501,14 @@
 				</ul>
 		</ul>
 
+		<h6 class='topic'>juneau-rest-server</h6>
+		<ul class='spaced-list'>
+			<li>
+				New {@link org.apache.juneau.rest.annotation.RestResource#maxInput() @RestResource.maxInput()} and 
+				{@link org.apache.juneau.rest.annotation.RestMethod#maxInput() @RestMethod.maxInput()} for alleviating
+				potential DoS attacks.
+		</ul>
+
 	</div>
 	
 	<!-- =========================================================================================================== -->

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequestEntity.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequestEntity.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequestEntity.java
index 09275f5..46adfaf 100644
--- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequestEntity.java
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequestEntity.java
@@ -60,7 +60,7 @@ public final class RestRequestEntity extends BasicHttpEntity {
 				} else {
 					SerializerSession session = serializer.createSession();
 					try (Closeable c = session.isWriterSerializer() ? new OutputStreamWriter(os, UTF8) : os) {
-						session.serialize(c, output);
+						session.serialize(output, c);
 					}
 				}
 			} catch (SerializeException e) {

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-rest/juneau-rest-server-jaxrs/src/main/java/org/apache/juneau/rest/jaxrs/BaseProvider.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server-jaxrs/src/main/java/org/apache/juneau/rest/jaxrs/BaseProvider.java b/juneau-rest/juneau-rest-server-jaxrs/src/main/java/org/apache/juneau/rest/jaxrs/BaseProvider.java
index 933a87b..4c29866 100644
--- a/juneau-rest/juneau-rest-server-jaxrs/src/main/java/org/apache/juneau/rest/jaxrs/BaseProvider.java
+++ b/juneau-rest/juneau-rest-server-jaxrs/src/main/java/org/apache/juneau/rest/jaxrs/BaseProvider.java
@@ -120,7 +120,7 @@ public class BaseProvider implements MessageBodyReader<Object>, MessageBodyWrite
 			
 			// Leave this open in case an error occurs.
 			Closeable c = s.isWriterSerializer() ? new OutputStreamWriter(os, UTF8) : os;
-			session.serialize(c, o);
+			session.serialize(o, c);
 
 		} catch (SerializeException e) {
 			throw new IOException(e);

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java
index c724d5f..29044ec 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/CallMethod.java
@@ -57,6 +57,7 @@ class CallMethod implements Comparable<CallMethod>  {
 	private final ObjectMap properties;
 	private final Map<String,String> defaultRequestHeaders, defaultQuery, defaultFormData;
 	private final String defaultCharset;
+	private final long maxInput;
 	private final boolean deprecated;
 	private final String description, tags, summary, externalDocs;
 	private final Integer priority;
@@ -88,6 +89,7 @@ class CallMethod implements Comparable<CallMethod>  {
 		this.defaultQuery = b.defaultQuery;
 		this.defaultFormData = b.defaultFormData;
 		this.defaultCharset = b.defaultCharset;
+		this.maxInput = b.maxInput;
 		this.deprecated = b.deprecated;
 		this.description = b.description;
 		this.tags = b.tags;
@@ -115,6 +117,7 @@ class CallMethod implements Comparable<CallMethod>  {
 		ObjectMap properties;
 		Map<String,String> defaultRequestHeaders, defaultQuery, defaultFormData;
 		boolean plainParams, deprecated;
+		long maxInput;
 		Integer priority;
 		org.apache.juneau.rest.annotation.Parameter[] parameters;
 		Response[] responses;
@@ -149,10 +152,13 @@ class CallMethod implements Comparable<CallMethod>  {
 				encoders = context.getEncoders();
 				properties = new ObjectMap().setInner(context.getProperties());
 				defaultCharset = context.getDefaultCharset();
+				maxInput = context.getMaxInput();
 				String paramFormat = context.getParamFormat();
 
 				if (! m.defaultCharset().isEmpty())
 					defaultCharset = context.getVarResolver().resolve(m.defaultCharset());
+				if (! m.maxInput().isEmpty())
+					maxInput = StringUtils.parseLongWithSuffix(context.getVarResolver().resolve(m.maxInput()));
 				if (! m.paramFormat().isEmpty())
 					paramFormat = context.getVarResolver().resolve(m.paramFormat());
 
@@ -163,7 +169,7 @@ class CallMethod implements Comparable<CallMethod>  {
 
 				widgets = new HashMap<>(context.getWidgets());
 				for (Class<? extends Widget> wc : hd.widgets()) {
-					Widget w = ClassUtils.newInstance(Widget.class, wc);
+					Widget w = beanContext.newInstance(Widget.class, wc);
 					widgets.put(w.getName(), w);
 					hdb.script("INHERIT", "$W{"+w.getName()+".script}");
 					hdb.style("INHERIT", "$W{"+w.getName()+".style}");
@@ -203,20 +209,20 @@ class CallMethod implements Comparable<CallMethod>  {
 				String p = m.path();
 				converters = new RestConverter[m.converters().length];
 				for (int i = 0; i < converters.length; i++)
-					converters[i] = newInstance(RestConverter.class, m.converters()[i]);
+					converters[i] = beanContext.newInstance(RestConverter.class, m.converters()[i]);
 
 				guards = new RestGuard[m.guards().length];
 				for (int i = 0; i < guards.length; i++)
-					guards[i] = newInstance(RestGuard.class, m.guards()[i]);
+					guards[i] = beanContext.newInstance(RestGuard.class, m.guards()[i]);
 
 				List<RestMatcher> optionalMatchers = new LinkedList<>(), requiredMatchers = new LinkedList<>();
 				for (int i = 0; i < m.matchers().length; i++) {
 					Class<? extends RestMatcher> c = m.matchers()[i];
 					RestMatcher matcher = null;
 					if (isParentClass(RestMatcherReflecting.class, c))
-						matcher = newInstance(RestMatcherReflecting.class, c, servlet, method);
+						matcher = beanContext.newInstance(RestMatcherReflecting.class, c, servlet, method);
 					else
-						matcher = newInstance(RestMatcher.class, c);
+						matcher = beanContext.newInstance(RestMatcher.class, c);
 					if (matcher.mustMatch())
 						requiredMatchers.add(matcher);
 					else
@@ -762,7 +768,7 @@ class CallMethod implements Comparable<CallMethod>  {
 		ObjectMap requestProperties = new ResolvingObjectMap(req.getVarResolverSession()).setInner(properties);
 
 		req.init(method, requestProperties, defaultRequestHeaders, defaultQuery, defaultFormData, defaultCharset,
-			serializers, parsers, urlEncodingParser, beanContext, encoders, widgets);
+			maxInput, serializers, parsers, urlEncodingParser, beanContext, encoders, widgets);
 		res.init(requestProperties, defaultCharset, serializers, urlEncodingSerializer, encoders);
 
 		// Class-level guards

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
index e7f077c..6a35428 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RequestBody.java
@@ -41,6 +41,7 @@ public class RequestBody {
 	private Encoder encoder;
 	private ParserGroup parsers;
 	private UrlEncodingParser urlEncodingParser;
+	private long maxInput;
 	private RequestHeaders headers;
 	private BeanSession beanSession;
 	private int contentLength = 0;
@@ -69,6 +70,11 @@ public class RequestBody {
 		return this;
 	}
 
+	RequestBody setMaxInput(long maxInput) {
+		this.maxInput = maxInput;
+		return this;
+	}
+
 	RequestBody setBeanSession(BeanSession beanSession) {
 		this.beanSession = beanSession;
 		return this;
@@ -284,20 +290,17 @@ public class RequestBody {
 	 * @return The negotiated input stream.
 	 * @throws IOException If any error occurred while trying to get the input stream or wrap it in the GZIP wrapper.
 	 */
-	@SuppressWarnings("resource")
 	public ServletInputStream getInputStream() throws IOException {
 
 		if (body != null)
-			return new ServletInputStream2(body);
+			return new BoundedServletInputStream(body);
 
 		Encoder enc = getEncoder();
 
-		ServletInputStream is = req.getRawInputStream();
-		if (enc != null) {
-			final InputStream is2 = enc.getInputStream(is);
-			return new ServletInputStream2(is2);
-		}
-		return is;
+		if (enc == null)
+			return new BoundedServletInputStream(req.getRawInputStream(), maxInput);
+		
+		return new BoundedServletInputStream(enc.getInputStream(req.getRawInputStream()), maxInput);
 	}
 
 	/**
@@ -430,41 +433,110 @@ public class RequestBody {
 	/**
 	 * ServletInputStream wrapper around a normal input stream.
 	 */
-	static final class ServletInputStream2 extends ServletInputStream {
+	static final class BoundedServletInputStream extends ServletInputStream {
 
 		private final InputStream is;
+		private final ServletInputStream sis;
+		private long remain;
 
-		ServletInputStream2(InputStream is) {
+		BoundedServletInputStream(InputStream is, long max) {
 			this.is = is;
+			this.sis = null;
+			this.remain = max;
 		}
 
-		ServletInputStream2(byte[] b) {
-			this(new ByteArrayInputStream(b));
+		BoundedServletInputStream(ServletInputStream sis, long max) {
+			this.sis = sis;
+			this.is = sis;
+			this.remain = max;
+		}
+
+		BoundedServletInputStream(byte[] b) {
+			this(new ByteArrayInputStream(b), Long.MAX_VALUE);
 		}
 
 		@Override /* InputStream */
 		public final int read() throws IOException {
+			decrement();
 			return is.read();
 		}
 
 		@Override /* InputStream */
+		public int read(byte[] b) throws IOException {
+			return read(b, 0, b.length);
+		}
+
+		@Override /* InputStream */
+		public int read(final byte[] b, final int off, final int len) throws IOException {
+			long numBytes = Math.min(len, remain);
+			int r = is.read(b, off, (int) numBytes);
+			if (r == -1) 
+				return -1;
+			decrement(numBytes);
+			return r;
+		}
+
+		@Override /* InputStream */
+		public long skip(final long n) throws IOException {
+			long toSkip = Math.min(n, remain);
+			long r = is.skip(toSkip);
+			decrement(r);
+			return r;
+		}
+
+		@Override /* InputStream */
+		public int available() throws IOException {
+			if (remain <= 0)
+				return 0;
+			return is.available();
+		}
+
+		@Override /* InputStream */
+		public synchronized void reset() throws IOException {
+			is.reset();
+		}
+
+		@Override /* InputStream */
+		public synchronized void mark(int limit) {
+			is.mark(limit);
+		}
+
+		@Override /* InputStream */
+		public boolean markSupported() {
+			return is.markSupported();
+		}
+
+		@Override /* InputStream */
 		public final void close() throws IOException {
 			is.close();
 		}
 
 		@Override /* ServletInputStream */
 		public boolean isFinished() {
-			return false;
+			return sis == null ? false : sis.isFinished();
 		}
 
 		@Override /* ServletInputStream */
 		public boolean isReady() {
-			return true;
+			return sis == null ? true : sis.isReady();
 		}
 
 		@Override /* ServletInputStream */
 		public void setReadListener(ReadListener arg0) {
-			throw new NoSuchMethodError();
+			if (sis != null)
+				sis.setReadListener(arg0);
+		}
+		
+		private void decrement() throws IOException {
+			remain--;
+			if (remain < 0)
+				throw new IOException("Input limit exceeded.  See @RestResource.maxInput().");
+		}
+
+		private void decrement(long count) throws IOException {
+			remain -= count;
+			if (remain < 0)
+				throw new IOException("Input limit exceeded.  See @RestResource.maxInput().");
 		}
 	}
 }

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestConfig.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestConfig.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestConfig.java
index 4da4058..77dd340 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestConfig.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestConfig.java
@@ -120,7 +120,7 @@ public class RestConfig implements ServletConfig {
 	Object logger = RestLogger.Normal.class;
 	Object callHandler = RestCallHandler.class;
 	Object infoProvider = RestInfoProvider.class;
-	Object allowHeaderParams, allowMethodParam, allowBodyParam, renderResponseStackTraces, useStackTraceHashes, defaultCharset, paramFormat;
+	Object allowHeaderParams, allowMethodParam, allowBodyParam, renderResponseStackTraces, useStackTraceHashes, defaultCharset, paramFormat, maxInput;
 
 	Class<?> resourceClass;
 
@@ -246,6 +246,8 @@ public class RestConfig implements ServletConfig {
 					setDefaultCharset(vr.resolve(r.defaultCharset()));
 				if (! r.paramFormat().isEmpty())
 					setParamFormat(vr.resolve(r.paramFormat()));
+				if (! r.maxInput().isEmpty())
+					setMaxInput(vr.resolve(r.maxInput()));
 
 				HtmlDoc hd = r.htmldoc();
 				for (Class<? extends Widget> cw : hd.widgets())
@@ -1151,6 +1153,20 @@ public class RestConfig implements ServletConfig {
 	}
 
 	/**
+	 * Sets the <code>maxInput</code> setting on this resource.
+	 *
+	 * <p>
+	 * This is the programmatic equivalent to the {@link RestResource#maxInput() RestResource.maxInput()} annotation.
+	 *
+	 * @param value The new value for this setting.
+	 * @return This object (for method chaining).
+	 */
+	public RestConfig setMaxInput(String value) {
+		this.maxInput = value;
+		return this;
+	}
+
+	/**
 	 * Sets the URL path of the resource <js>"/foobar"</js>.
 	 *
 	 * <p>

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index bf86b60..0c74c02 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -68,6 +68,8 @@ public final class RestContext extends Context {
 		paramFormat,
 		clientVersionHeader,
 		contextPath;
+	private final long
+		maxInput;
 	
 	final String fullPath;
 
@@ -164,6 +166,7 @@ public final class RestContext extends Context {
 			this.allowMethodParams = Collections.unmodifiableSet(b.allowMethodParams);
 			this.defaultCharset = b.defaultCharset;
 			this.paramFormat = b.paramFormat;
+			this.maxInput = b.maxInput;
 			this.varResolver = b.varResolver;
 			this.configFile = b.configFile;
 			this.properties = b.properties;
@@ -459,6 +462,7 @@ public final class RestContext extends Context {
 		UrlEncodingParser urlEncodingParser;
 		EncoderGroup encoders;
 		String clientVersionHeader = "", defaultCharset, paramFormat;
+		long maxInput;
 
 		List<MediaType> supportedContentTypes, supportedAcceptTypes;
 		Map<String,String> defaultRequestHeaders = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
@@ -492,6 +496,7 @@ public final class RestContext extends Context {
 			defaultCharset = getString(sc.defaultCharset, "juneau.defaultCharset", "utf-8");
 			paramFormat = getString(sc.paramFormat, "juneau.paramFormat", "UON");
 			resourceResolver = sc.resourceResolver;
+			maxInput = getLong(sc.maxInput, "juneau.maxInput", 100_000_000l);
 
 			String amp = getString(sc.allowMethodParam, "juneau.allowMethodParam", "HEAD,OPTIONS");
 			if ("true".equals(amp))
@@ -604,6 +609,15 @@ public final class RestContext extends Context {
 		return o.toString();
 	}
 
+	static final long getLong(Object o, String systemProperty, long def) {
+		String s = StringUtils.toString(o);
+		if (s == null)
+			s = System.getProperty(systemProperty);
+		if (StringUtils.isEmpty(s))
+			return def;
+		return StringUtils.parseLongWithSuffix(s);
+	}
+
 	/**
 	 * Returns the resource resolver associated with this context.
 	 *
@@ -1127,6 +1141,15 @@ public final class RestContext extends Context {
 	}
 
 	/**
+	 * Returns the value of the {@link RestResource#maxInput()} setting.
+	 *
+	 * @return The value of the {@link RestResource#maxInput()} setting.
+	 */
+	protected long getMaxInput() {
+		return maxInput;
+	}
+
+	/**
 	 * Returns the name of the client version header name used by this resource.
 	 *
 	 * <p>

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
index c610318..1d6ceb2 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestRequest.java
@@ -159,7 +159,7 @@ public final class RestRequest extends HttpServletRequestWrapper {
 	 * Called from RestServlet after a match has been made but before the guard or method invocation.
 	 */
 	final void init(Method javaMethod, ObjectMap properties, Map<String,String> defHeader,
-			Map<String,String> defQuery, Map<String,String> defFormData, String defaultCharset,
+			Map<String,String> defQuery, Map<String,String> defFormData, String defaultCharset, long maxInput,
 			SerializerGroup mSerializers, ParserGroup mParsers, UrlEncodingParser mUrlEncodingParser,
 			BeanContext beanContext, EncoderGroup encoders, Map<String,Widget> widgets) {
 		this.javaMethod = javaMethod;
@@ -183,7 +183,8 @@ public final class RestRequest extends HttpServletRequestWrapper {
 			.setParsers(mParsers)
 			.setHeaders(headers)
 			.setBeanSession(beanSession)
-			.setUrlEncodingParser(mUrlEncodingParser);
+			.setUrlEncodingParser(mUrlEncodingParser)
+			.setMaxInput(maxInput);
 		this.serializerGroup = mSerializers;
 		this.parserGroup = mParsers;
 		this.defaultCharset = defaultCharset;

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
index 90bb10f..4d10228 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestMethod.java
@@ -680,4 +680,22 @@ public @interface RestMethod {
 	 * </ul>
 	 */
 	String paramFormat() default "";
+	
+	/**
+	 * The maximum allowed input size (in bytes) on HTTP requests.
+	 * 
+	 * <p>
+	 * Useful for alleviating DoS attacks by throwing an exception when too much input is received instead of resulting
+	 * in out-of-memory errors which could affect system stability.
+	 * 
+	 * <ul>
+	 * 	<li>String value that gets resolved to a <jk>long</jk>.
+	 * 	<li>Can contain variables.
+	 * 	<li>Can be suffixed with any of the following representing kilobytes, megabytes, and gigabytes:  
+	 * 		<js>'K'</js>, <js>'M'</js>, <js>'G'</js>.
+	 * 	<li>Defaults to <js>"100M"</js>.
+	 * 	<li>A value of <js>"-1"</js> can be used to represent no limit.
+	 * </ul>
+	 */
+	String maxInput() default "";
 }

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java
index 66e9561..d27c495 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestResource.java
@@ -860,4 +860,22 @@ public @interface RestResource {
 	 * </ul>
 	 */
 	String paramFormat() default "";
+	
+	/**
+	 * The maximum allowed input size (in bytes) on HTTP requests.
+	 * 
+	 * <p>
+	 * Useful for alleviating DoS attacks by throwing an exception when too much input is received instead of resulting
+	 * in out-of-memory errors which could affect system stability.
+	 * 
+	 * <ul>
+	 * 	<li>String value that gets resolved to a <jk>long</jk>.
+	 * 	<li>Can contain variables.
+	 * 	<li>Can be suffixed with any of the following representing kilobytes, megabytes, and gigabytes:  
+	 * 		<js>'K'</js>, <js>'M'</js>, <js>'G'</js>.
+	 * 	<li>Defaults to <js>"100M"</js>.
+	 * 	<li>A value of <js>"-1"</js> can be used to represent no limit.
+	 * </ul>
+	 */
+	String maxInput() default "";
 }

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/DefaultHandler.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/DefaultHandler.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/DefaultHandler.java
index 70b24a8..93e4aa6 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/DefaultHandler.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/response/DefaultHandler.java
@@ -67,17 +67,17 @@ public class DefaultHandler implements ResponseHandler {
 					if (req.isPlainText()) {
 						Writer w = res.getNegotiatedWriter();
 						ByteArrayOutputStream baos = new ByteArrayOutputStream();
-						session.serialize(baos, output);
+						session.serialize(output, baos);
 						w.write(StringUtils.toSpacedHex(baos.toByteArray()));
 						w.close();  // Leave open if exception occurs.
 					} else {
 						OutputStream os = res.getNegotiatedOutputStream();
-						session.serialize(os, output);
+						session.serialize(output, os);
 						os.close();  // Leave open if exception occurs.
 					}
 				} else {
 					Writer w = res.getNegotiatedWriter();
-					session.serialize(w, output);
+					session.serialize(output, w);
 					w.close();  // Leave open if exception occurs.
 				}
 			} catch (SerializeException e) {

http://git-wip-us.apache.org/repos/asf/juneau/blob/f67c7f28/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/MenuItemWidget.java
----------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/MenuItemWidget.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/MenuItemWidget.java
index 2117e97..ea1b114 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/MenuItemWidget.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/widget/MenuItemWidget.java
@@ -92,7 +92,7 @@ public abstract class MenuItemWidget extends Widget {
 			SerializerSessionArgs args = new SerializerSessionArgs(req.getProperties(), null, req.getLocale(), null, null, req.getUriContext());
 			WriterSerializerSession session = HtmlSerializer.DEFAULT.createSession(args);
 			session.indent = 2;
-			session.serialize(sb, o);
+			session.serialize(o, sb);
 		}
 		sb.append(""
 			+ "\n\t</div>"