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> </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> </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>"