http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2a37f310/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
 
b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
index 6ceb906..9f872c0 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
@@ -14,19 +14,15 @@ package org.apache.juneau.urlencoding;
 
 import static org.apache.juneau.serializer.SerializerContext.*;
 import static org.apache.juneau.uon.UonSerializerContext.*;
-import static org.apache.juneau.internal.ArrayUtils.*;
+import static org.apache.juneau.urlencoding.UrlEncodingContext.*;
 import static org.apache.juneau.internal.StringUtils.*;
 
 import java.io.*;
-import java.lang.reflect.*;
 import java.net.*;
-import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
-import org.apache.juneau.http.*;
 import org.apache.juneau.serializer.*;
-import org.apache.juneau.transform.*;
 import org.apache.juneau.uon.*;
 
 /**
@@ -158,12 +154,7 @@ public class UrlEncodingSerializer extends UonSerializer 
implements PartSerializ
                 * @param propertyStore The property store containing all the 
settings for this object.
                 */
                public Expanded(PropertyStore propertyStore) {
-                       super(propertyStore);
-               }
-
-               @Override /* CoreObject */
-               protected ObjectMap getOverrideProperties() {
-                       return 
super.getOverrideProperties().append(UrlEncodingContext.URLENC_expandedParams, 
true);
+                       
super(propertyStore.copy().append(URLENC_expandedParams, true));
                }
        }
 
@@ -178,12 +169,7 @@ public class UrlEncodingSerializer extends UonSerializer 
implements PartSerializ
                 * @param propertyStore The property store containing all the 
settings for this object.
                 */
                public Readable(PropertyStore propertyStore) {
-                       super(propertyStore);
-               }
-
-               @Override /* CoreObject */
-               protected ObjectMap getOverrideProperties() {
-                       return 
super.getOverrideProperties().append(SERIALIZER_useWhitespace, true);
+                       
super(propertyStore.copy().append(SERIALIZER_useWhitespace, true));
                }
        }
 
@@ -198,12 +184,7 @@ public class UrlEncodingSerializer extends UonSerializer 
implements PartSerializ
                 * @param propertyStore The property store containing all the 
settings for this object.
                 */
                public PlainText(PropertyStore propertyStore) {
-                       super(propertyStore);
-               }
-
-               @Override /* CoreObject */
-               protected ObjectMap getOverrideProperties() {
-                       return 
super.getOverrideProperties().append(UonSerializerContext.UON_paramFormat, 
"PLAINTEXT");
+                       super(propertyStore.copy().append(UON_paramFormat, 
"PLAINTEXT"));
                }
        }
 
@@ -215,7 +196,7 @@ public class UrlEncodingSerializer extends UonSerializer 
implements PartSerializ
         * @param propertyStore The property store containing all the settings 
for this object.
         */
        public UrlEncodingSerializer(PropertyStore propertyStore) {
-               super(propertyStore);
+               super(propertyStore.copy().append(UON_encodeChars, true));
                this.ctx = createContext(UrlEncodingSerializerContext.class);
        }
 
@@ -224,183 +205,6 @@ public class UrlEncodingSerializer extends UonSerializer 
implements PartSerializ
                return new UrlEncodingSerializerBuilder(propertyStore);
        }
 
-       @Override /* CoreObject */
-       protected ObjectMap getOverrideProperties() {
-               return super.getOverrideProperties().append(UON_encodeChars, 
true);
-       }
-
-       /**
-        * Workhorse method. Determines the type of object, and then calls the 
appropriate type-specific serialization method.
-        */
-       @SuppressWarnings({ "rawtypes", "unchecked" })
-       private SerializerWriter serializeAnything(UrlEncodingSerializerSession 
session, UonWriter out, Object o) throws Exception {
-
-               ClassMeta<?> aType;                     // The actual type
-               ClassMeta<?> sType;                     // The serialized type
-
-               aType = session.push("root", o, object());
-               session.indent--;
-               if (aType == null)
-                       aType = object();
-
-               sType = aType.getSerializedClassMeta();
-               String typeName = session.getBeanTypeName(session.object(), 
aType, null);
-
-               // Swap if necessary
-               PojoSwap swap = aType.getPojoSwap();
-               if (swap != null) {
-                       o = swap.swap(session, o);
-
-                       // If the getSwapClass() method returns Object, we need 
to figure out
-                       // the actual type now.
-                       if (sType.isObject())
-                               sType = session.getClassMetaForObject(o);
-               }
-
-               if (sType.isMap()) {
-                       if (o instanceof BeanMap)
-                               serializeBeanMap(session, out, (BeanMap)o, 
typeName);
-                       else
-                               serializeMap(session, out, (Map)o, sType);
-               } else if (sType.isBean()) {
-                       serializeBeanMap(session, out, session.toBeanMap(o), 
typeName);
-               } else if (sType.isCollection() || sType.isArray()) {
-                       Map m = sType.isCollection() ? 
getCollectionMap((Collection)o) : getCollectionMap(o);
-                       serializeCollectionMap(session, out, m, 
session.getClassMeta(Map.class, Integer.class, Object.class));
-               } else {
-                       // All other types can't be serialized as key/value 
pairs, so we create a
-                       // mock key/value pair with a "_value" key.
-                       out.append("_value=");
-                       super.serializeAnything(session, out, o, null, null, 
null);
-               }
-
-               session.pop();
-               return out;
-       }
-
-       /**
-        * Converts a Collection into an integer-indexed map.
-        */
-       private static Map<Integer,Object> getCollectionMap(Collection<?> c) {
-               Map<Integer,Object> m = new TreeMap<Integer,Object>();
-               int i = 0;
-               for (Object o : c)
-                       m.put(i++, o);
-               return m;
-       }
-
-       /**
-        * Converts an array into an integer-indexed map.
-        */
-       private static Map<Integer,Object> getCollectionMap(Object array) {
-               Map<Integer,Object> m = new TreeMap<Integer,Object>();
-               for (int i = 0; i < Array.getLength(array); i++)
-                       m.put(i, Array.get(array, i));
-               return m;
-       }
-
-       @SuppressWarnings({ "rawtypes", "unchecked" })
-       private SerializerWriter serializeMap(UrlEncodingSerializerSession 
session, UonWriter out, Map m, ClassMeta<?> type) throws Exception {
-
-               m = session.sort(m);
-
-               ClassMeta<?> keyType = type.getKeyType(), valueType = 
type.getValueType();
-
-               int depth = session.getIndent();
-               boolean addAmp = false;
-
-               for (Map.Entry e : (Set<Map.Entry>)m.entrySet()) {
-                       Object key = session.generalize(e.getKey(), keyType);
-                       Object value = e.getValue();
-
-                       if (session.shouldUseExpandedParams(value)) {
-                               Iterator i = value instanceof Collection ? 
((Collection)value).iterator() : iterator(value);
-                               while (i.hasNext()) {
-                                       if (addAmp)
-                                               out.cr(depth).append('&');
-                                       out.appendObject(key, true).append('=');
-                                       super.serializeAnything(session, out, 
i.next(), null, (key == null ? null : key.toString()), null);
-                                       addAmp = true;
-                               }
-                       } else {
-                               if (addAmp)
-                                       out.cr(depth).append('&');
-                               out.appendObject(key, true).append('=');
-                               super.serializeAnything(session, out, value, 
valueType, (key == null ? null : key.toString()), null);
-                               addAmp = true;
-                       }
-               }
-
-               return out;
-       }
-
-       @SuppressWarnings({ "rawtypes", "unchecked" })
-       private SerializerWriter 
serializeCollectionMap(UrlEncodingSerializerSession session, UonWriter out, Map 
m, ClassMeta<?> type) throws Exception {
-
-               ClassMeta<?> valueType = type.getValueType();
-
-               int depth = session.getIndent();
-               boolean addAmp = false;
-
-               for (Map.Entry e : (Set<Map.Entry>)m.entrySet()) {
-                       if (addAmp)
-                               out.cr(depth).append('&');
-                       out.append(e.getKey()).append('=');
-                       super.serializeAnything(session, out, e.getValue(), 
valueType, null, null);
-                       addAmp = true;
-               }
-
-               return out;
-       }
-
-       @SuppressWarnings({ "rawtypes" })
-       private SerializerWriter serializeBeanMap(UrlEncodingSerializerSession 
session, UonWriter out, BeanMap<?> m, String typeName) throws Exception {
-               int depth = session.getIndent();
-
-               boolean addAmp = false;
-
-               for (BeanPropertyValue p : m.getValues(session.isTrimNulls(), 
typeName != null ? session.createBeanTypeNameProperty(m, typeName) : null)) {
-                       BeanPropertyMeta pMeta = p.getMeta();
-                       ClassMeta<?> cMeta = p.getClassMeta();
-
-                       String key = p.getName();
-                       Object value = p.getValue();
-                       Throwable t = p.getThrown();
-                       if (t != null)
-                               session.onBeanGetterException(pMeta, t);
-
-                       if (session.canIgnoreValue(cMeta, key, value))
-                               continue;
-
-                       if (value != null && 
session.shouldUseExpandedParams(pMeta)) {
-                               // Transformed object array bean properties may 
be transformed resulting in ArrayLists,
-                               // so we need to check type if we think it's an 
array.
-                               Iterator i = (cMeta.isCollection() || value 
instanceof Collection) ? ((Collection)value).iterator() : iterator(value);
-                               while (i.hasNext()) {
-                                       if (addAmp)
-                                               out.cr(depth).append('&');
-
-                                       out.appendObject(key, true).append('=');
-
-                                       super.serializeAnything(session, out, 
i.next(), cMeta.getElementType(), key, pMeta);
-
-                                       addAmp = true;
-                               }
-                       } else {
-                               if (addAmp)
-                                       out.cr(depth).append('&');
-
-                               out.appendObject(key, true).append('=');
-
-                               super.serializeAnything(session, out, value, 
cMeta, key, pMeta);
-
-                               addAmp = true;
-                       }
-
-               }
-               return out;
-       }
-
 
        
//--------------------------------------------------------------------------------
        // Methods for constructing individual parameter values.
@@ -438,9 +242,8 @@ public class UrlEncodingSerializer extends UonSerializer 
implements PartSerializ
                        }
 
                        StringWriter w = new StringWriter();
-                       SerializerOutput out = new SerializerOutput(w);
-                       UonSerializerSession s = new 
UrlEncodingSerializerSession(ctx, urlEncode, null, null, null, null, 
MediaType.UON, null);
-                       super.doSerialize(s, out, o);
+                       UonSerializerSession s = new UonSerializerSession(ctx, 
urlEncode, SerializerSessionArgs.DEFAULT);
+                       s.serialize(w, o);
                        return w.toString();
                } catch (Exception e) {
                        throw new RuntimeException(e);
@@ -453,15 +256,8 @@ public class UrlEncodingSerializer extends UonSerializer 
implements PartSerializ
        
//--------------------------------------------------------------------------------
 
        @Override /* Serializer */
-       public UrlEncodingSerializerSession createSession(ObjectMap op, Method 
javaMethod, Locale locale,
-                       TimeZone timeZone, MediaType mediaType, UriContext 
uriContext) {
-               return new UrlEncodingSerializerSession(ctx, null, op, 
javaMethod, locale, timeZone, mediaType, uriContext);
-       }
-
-       @Override /* Serializer */
-       protected void doSerialize(SerializerSession session, SerializerOutput 
out, Object o) throws Exception {
-               UrlEncodingSerializerSession s = 
(UrlEncodingSerializerSession)session;
-               serializeAnything(s, s.getUonWriter(out), o);
+       public WriterSerializerSession createSession(SerializerSessionArgs 
args) {
+               return new UrlEncodingSerializerSession(ctx, null, args);
        }
 
        @Override /* PartSerializer */

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2a37f310/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
 
b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
index 6a0fb21..46e36d2 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
@@ -12,62 +12,56 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.urlencoding;
 
+import static org.apache.juneau.internal.ArrayUtils.*;
+
 import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
-import org.apache.juneau.http.*;
+import org.apache.juneau.serializer.*;
+import org.apache.juneau.transform.*;
 import org.apache.juneau.uon.*;
 
 /**
  * Session object that lives for the duration of a single use of {@link 
UrlEncodingSerializer}.
  *
  * <p>
- * This class is NOT thread safe.  It is meant to be discarded after one-time 
use.
+ * This class is NOT thread safe.
+ * It is typically discarded after one-time use although it can be reused 
within the same thread.
  */
+@SuppressWarnings({ "rawtypes", "unchecked" })
 public class UrlEncodingSerializerSession extends UonSerializerSession {
 
        private final boolean expandedParams;
 
        /**
-        * Create a new session using properties specified in the context.
+        * Constructor.
         *
         * @param ctx
         *      The context creating this session object.
         *      The context contains all the configuration settings for this 
object.
-        * @param encode Overrides the {@link 
UonSerializerContext#UON_encodeChars} setting.
-        * @param op
-        *      The override properties.
-        *      These override any context properties defined in the context.
-        * @param javaMethod The java method that called this serializer, 
usually the method in a REST servlet.
-        * @param locale
-        *      The session locale.
-        *      If <jk>null</jk>, then the locale defined on the context is 
used.
-        * @param timeZone
-        *      The session timezone.
-        *      If <jk>null</jk>, then the timezone defined on the context is 
used.
-        * @param mediaType The session media type (e.g. 
<js>"application/json"</js>).
-        * @param uriContext
-        *      The URI context.
-        *      Identifies the current request URI used for resolution of URIs 
to absolute or root-relative form.
+        * @param encode Override the {@link 
UonSerializerContext#UON_encodeChars} setting.
+        * @param args
+        *      Runtime arguments.
+        *      These specify session-level information such as locale and URI 
context.
+        *      It also include session-level properties that override the 
properties defined on the bean and
+        *      serializer contexts.
+        *      <br>If <jk>null</jk>, defaults to {@link 
SerializerSessionArgs#DEFAULT}.
         */
-       public UrlEncodingSerializerSession(UrlEncodingSerializerContext ctx, 
Boolean encode, ObjectMap op,
-                       Method javaMethod, Locale locale, TimeZone timeZone, 
MediaType mediaType, UriContext uriContext) {
-               super(ctx, encode, op, javaMethod, locale, timeZone, mediaType, 
uriContext);
-               if (op == null || op.isEmpty()) {
+       protected UrlEncodingSerializerSession(UrlEncodingSerializerContext 
ctx, Boolean encode, SerializerSessionArgs args) {
+               super(ctx, encode, args);
+               ObjectMap p = getProperties();
+               if (p.isEmpty()) {
                        expandedParams = ctx.expandedParams;
                } else {
-                       expandedParams = 
op.getBoolean(UrlEncodingContext.URLENC_expandedParams, false);
+                       expandedParams = 
p.getBoolean(UrlEncodingContext.URLENC_expandedParams, false);
                }
        }
 
-       /**
+       /*
         * Returns <jk>true</jk> if the specified bean property should be 
expanded as multiple key-value pairs.
-        *
-        * @param pMeta The metadata on the bean property.
-        * @return <jk>true</jk> if the specified bean property should be 
expanded as multiple key-value pairs.
         */
-       public final boolean shouldUseExpandedParams(BeanPropertyMeta pMeta) {
+       private boolean shouldUseExpandedParams(BeanPropertyMeta pMeta) {
                ClassMeta<?> cm = pMeta.getClassMeta();
                if (cm.isCollectionOrArray()) {
                        if (expandedParams)
@@ -78,13 +72,10 @@ public class UrlEncodingSerializerSession extends 
UonSerializerSession {
                return false;
        }
 
-       /**
+       /*
         * Returns <jk>true</jk> if the specified value should be represented 
as an expanded parameter list.
-        *
-        * @param value The value to check.
-        * @return <jk>true</jk> if the specified value should be represented 
as an expanded parameter list.
         */
-       public final boolean shouldUseExpandedParams(Object value) {
+       private boolean shouldUseExpandedParams(Object value) {
                if (value == null || ! expandedParams)
                        return false;
                ClassMeta<?> cm = 
getClassMetaForObject(value).getSerializedClassMeta();
@@ -94,4 +85,173 @@ public class UrlEncodingSerializerSession extends 
UonSerializerSession {
                }
                return false;
        }
+
+       @Override /* SerializerSession */
+       protected void doSerialize(SerializerPipe out, Object o) throws 
Exception {
+               serializeAnything(getUonWriter(out), o);
+       }
+
+       /*
+        * Workhorse method. Determines the type of object, and then calls the 
appropriate type-specific serialization method.
+        */
+       private SerializerWriter serializeAnything(UonWriter out, Object o) 
throws Exception {
+
+               ClassMeta<?> aType;                     // The actual type
+               ClassMeta<?> sType;                     // The serialized type
+
+               aType = push("root", o, object());
+               indent--;
+               if (aType == null)
+                       aType = object();
+
+               sType = aType.getSerializedClassMeta();
+               String typeName = getBeanTypeName(object(), aType, null);
+
+               // Swap if necessary
+               PojoSwap swap = aType.getPojoSwap();
+               if (swap != null) {
+                       o = swap.swap(this, o);
+
+                       // If the getSwapClass() method returns Object, we need 
to figure out
+                       // the actual type now.
+                       if (sType.isObject())
+                               sType = getClassMetaForObject(o);
+               }
+
+               if (sType.isMap()) {
+                       if (o instanceof BeanMap)
+                               serializeBeanMap(out, (BeanMap)o, typeName);
+                       else
+                               serializeMap(out, (Map)o, sType);
+               } else if (sType.isBean()) {
+                       serializeBeanMap(out, toBeanMap(o), typeName);
+               } else if (sType.isCollection() || sType.isArray()) {
+                       Map m = sType.isCollection() ? 
getCollectionMap((Collection)o) : getCollectionMap(o);
+                       serializeCollectionMap(out, m, getClassMeta(Map.class, 
Integer.class, Object.class));
+               } else {
+                       // All other types can't be serialized as key/value 
pairs, so we create a
+                       // mock key/value pair with a "_value" key.
+                       out.append("_value=");
+                       super.serializeAnything(out, o, null, null, null);
+               }
+
+               pop();
+               return out;
+       }
+
+       /*
+        * Converts a Collection into an integer-indexed map.
+        */
+       private static Map<Integer,Object> getCollectionMap(Collection<?> c) {
+               Map<Integer,Object> m = new TreeMap<Integer,Object>();
+               int i = 0;
+               for (Object o : c)
+                       m.put(i++, o);
+               return m;
+       }
+
+       /*
+        * Converts an array into an integer-indexed map.
+        */
+       private static Map<Integer,Object> getCollectionMap(Object array) {
+               Map<Integer,Object> m = new TreeMap<Integer,Object>();
+               for (int i = 0; i < Array.getLength(array); i++)
+                       m.put(i, Array.get(array, i));
+               return m;
+       }
+
+       private SerializerWriter serializeMap(UonWriter out, Map m, 
ClassMeta<?> type) throws Exception {
+
+               m = sort(m);
+
+               ClassMeta<?> keyType = type.getKeyType(), valueType = 
type.getValueType();
+
+               boolean addAmp = false;
+
+               for (Map.Entry e : (Set<Map.Entry>)m.entrySet()) {
+                       Object key = generalize(e.getKey(), keyType);
+                       Object value = e.getValue();
+
+                       if (shouldUseExpandedParams(value)) {
+                               Iterator i = value instanceof Collection ? 
((Collection)value).iterator() : iterator(value);
+                               while (i.hasNext()) {
+                                       if (addAmp)
+                                               out.cr(indent).append('&');
+                                       out.appendObject(key, true).append('=');
+                                       super.serializeAnything(out, i.next(), 
null, (key == null ? null : key.toString()), null);
+                                       addAmp = true;
+                               }
+                       } else {
+                               if (addAmp)
+                                       out.cr(indent).append('&');
+                               out.appendObject(key, true).append('=');
+                               super.serializeAnything(out, value, valueType, 
(key == null ? null : key.toString()), null);
+                               addAmp = true;
+                       }
+               }
+
+               return out;
+       }
+
+       private SerializerWriter serializeCollectionMap(UonWriter out, Map m, 
ClassMeta<?> type) throws Exception {
+
+               ClassMeta<?> valueType = type.getValueType();
+
+               boolean addAmp = false;
+
+               for (Map.Entry e : (Set<Map.Entry>)m.entrySet()) {
+                       if (addAmp)
+                               out.cr(indent).append('&');
+                       out.append(e.getKey()).append('=');
+                       super.serializeAnything(out, e.getValue(), valueType, 
null, null);
+                       addAmp = true;
+               }
+
+               return out;
+       }
+
+       private SerializerWriter serializeBeanMap(UonWriter out, BeanMap<?> m, 
String typeName) throws Exception {
+               boolean addAmp = false;
+
+               for (BeanPropertyValue p : m.getValues(isTrimNulls(), typeName 
!= null ? createBeanTypeNameProperty(m, typeName) : null)) {
+                       BeanPropertyMeta pMeta = p.getMeta();
+                       ClassMeta<?> cMeta = p.getClassMeta();
+
+                       String key = p.getName();
+                       Object value = p.getValue();
+                       Throwable t = p.getThrown();
+                       if (t != null)
+                               onBeanGetterException(pMeta, t);
+
+                       if (canIgnoreValue(cMeta, key, value))
+                               continue;
+
+                       if (value != null && shouldUseExpandedParams(pMeta)) {
+                               // Transformed object array bean properties may 
be transformed resulting in ArrayLists,
+                               // so we need to check type if we think it's an 
array.
+                               Iterator i = (cMeta.isCollection() || value 
instanceof Collection) ? ((Collection)value).iterator() : iterator(value);
+                               while (i.hasNext()) {
+                                       if (addAmp)
+                                               out.cr(indent).append('&');
+
+                                       out.appendObject(key, true).append('=');
+
+                                       super.serializeAnything(out, i.next(), 
cMeta.getElementType(), key, pMeta);
+
+                                       addAmp = true;
+                               }
+                       } else {
+                               if (addAmp)
+                                       out.cr(indent).append('&');
+
+                               out.appendObject(key, true).append('=');
+
+                               super.serializeAnything(out, value, cMeta, key, 
pMeta);
+
+                               addAmp = true;
+                       }
+
+               }
+               return out;
+       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2a37f310/juneau-core/src/main/java/org/apache/juneau/xml/XmlDocSerializer.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/xml/XmlDocSerializer.java 
b/juneau-core/src/main/java/org/apache/juneau/xml/XmlDocSerializer.java
index e7e4548..6e70c35 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlDocSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlDocSerializer.java
@@ -46,12 +46,7 @@ public class XmlDocSerializer extends XmlSerializer {
                 * @param propertyStore The property store containing all the 
settings for this object.
                 */
                public Ns(PropertyStore propertyStore) {
-                       super(propertyStore);
-               }
-
-               @Override /* CoreObject */
-               protected ObjectMap getOverrideProperties() {
-                       return 
super.getOverrideProperties().append(XML_enableNamespaces, true);
+                       super(propertyStore.copy().append(XML_enableNamespaces, 
true));
                }
        }
 
@@ -64,19 +59,8 @@ public class XmlDocSerializer extends XmlSerializer {
                super(propertyStore);
        }
 
-       
//--------------------------------------------------------------------------------
-       // Entry point methods
-       
//--------------------------------------------------------------------------------
-
        @Override /* Serializer */
-       protected void doSerialize(SerializerSession session, SerializerOutput 
out, Object o) throws Exception {
-               XmlSerializerSession s = (XmlSerializerSession)session;
-               XmlWriter w = s.getXmlWriter(out);
-               w.append("<?xml")
-                       .attr("version", "1.0")
-                       .attr("encoding", "UTF-8")
-                       .appendln("?>");
-               w.flush();
-               super.doSerialize(s, out, o);
+       public WriterSerializerSession createSession(SerializerSessionArgs 
args) {
+               return new XmlDocSerializerSession(ctx, args);
        }
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2a37f310/juneau-core/src/main/java/org/apache/juneau/xml/XmlDocSerializerSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/xml/XmlDocSerializerSession.java 
b/juneau-core/src/main/java/org/apache/juneau/xml/XmlDocSerializerSession.java
new file mode 100644
index 0000000..b889889
--- /dev/null
+++ 
b/juneau-core/src/main/java/org/apache/juneau/xml/XmlDocSerializerSession.java
@@ -0,0 +1,53 @@
+// 
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                
                                              *
+// *                                                                           
                                              *
+// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
+// *                                                                           
                                              *
+// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the 
License.                                              *
+// 
***************************************************************************************************************************
+package org.apache.juneau.xml;
+
+import org.apache.juneau.serializer.*;
+
+/**
+ * Session object that lives for the duration of a single use of {@link 
XmlDocSerializer}.
+ *
+ * <p>
+ * This class is NOT thread safe.
+ * It is typically discarded after one-time use although it can be reused 
within the same thread.
+ */
+public class XmlDocSerializerSession extends XmlSerializerSession {
+
+       /**
+        * Create a new session using properties specified in the context.
+        *
+        * @param ctx
+        *      The context creating this session object.
+        *      The context contains all the configuration settings for this 
object.
+        * @param args
+        *      Runtime arguments.
+        *      These specify session-level information such as locale and URI 
context.
+        *      It also include session-level properties that override the 
properties defined on the bean and
+        *      serializer contexts.
+        *      <br>If <jk>null</jk>, defaults to {@link 
SerializerSessionArgs#DEFAULT}.
+        */
+       protected XmlDocSerializerSession(XmlSerializerContext ctx, 
SerializerSessionArgs args) {
+               super(ctx, args);
+       }
+
+       @Override /* SerializerSession */
+       protected void doSerialize(SerializerPipe out, Object o) throws 
Exception {
+               XmlWriter w = getXmlWriter(out);
+               w.append("<?xml")
+                       .attr("version", "1.0")
+                       .attr("encoding", "UTF-8")
+                       .appendln("?>");
+               w.flush();
+               super.doSerialize(out, o);
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2a37f310/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java 
b/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java
index aed0b63..cd81507 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java
@@ -12,22 +12,9 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.xml;
 
-import static javax.xml.stream.XMLStreamConstants.*;
-import static org.apache.juneau.internal.StringUtils.*;
-import static org.apache.juneau.xml.annotation.XmlFormat.*;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import javax.xml.stream.*;
-import javax.xml.stream.Location;
-
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
-import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
-import org.apache.juneau.transform.*;
-import org.apache.juneau.xml.annotation.*;
 
 /**
  * Parses text generated by the {@link XmlSerializer} class back into a POJO 
model.
@@ -48,15 +35,12 @@ import org.apache.juneau.xml.annotation.*;
  *     <li>{@link BeanContext}
  * </ul>
  */
-@SuppressWarnings({ "rawtypes", "unchecked" })
 @Consumes("text/xml,application/xml")
 public class XmlParser extends ReaderParser {
 
        /** Default parser, all default settings.*/
        public static final XmlParser DEFAULT = new 
XmlParser(PropertyStore.create());
 
-       private static final int UNKNOWN=0, OBJECT=1, ARRAY=2, STRING=3, 
NUMBER=4, BOOLEAN=5, NULL=6;
-
 
        private final XmlParserContext ctx;
 
@@ -75,456 +59,8 @@ public class XmlParser extends ReaderParser {
                return new XmlParserBuilder(propertyStore);
        }
 
-       /**
-        * Workhorse method.
-        *
-        * @param session The current parser session.
-        * @param eType The expected type of object.
-        * @param currAttr The current bean property name.
-        * @param r The reader.
-        * @param outer The outer object.
-        * @param isRoot If <jk>true</jk>, then we're serializing a root 
element in the document.
-        * @param pMeta The bean property metadata.
-        * @return The parsed object.
-        * @throws Exception
-        */
-       protected <T> T parseAnything(XmlParserSession session, ClassMeta<T> 
eType, String currAttr, XMLStreamReader r,
-                       Object outer, boolean isRoot, BeanPropertyMeta pMeta) 
throws Exception {
-
-               if (eType == null)
-                       eType = (ClassMeta<T>)object();
-               PojoSwap<T,Object> transform = 
(PojoSwap<T,Object>)eType.getPojoSwap();
-               ClassMeta<?> sType = eType.getSerializedClassMeta();
-               session.setCurrentClass(sType);
-
-               String wrapperAttr = (isRoot && 
session.isPreserveRootElement()) ? r.getName().getLocalPart() : null;
-               String typeAttr = r.getAttributeValue(null, 
session.getBeanTypePropertyName(eType));
-               int jsonType = getJsonType(typeAttr);
-               String elementName = session.getElementName(r);
-               if (jsonType == 0) {
-                       if (elementName == null || elementName.equals(currAttr))
-                               jsonType = UNKNOWN;
-                       else {
-                               typeAttr = elementName;
-                               jsonType = getJsonType(elementName);
-                       }
-               }
-
-               ClassMeta tcm = session.getClassMeta(typeAttr, pMeta, eType);
-               if (tcm == null && elementName != null && ! 
elementName.equals(currAttr))
-                       tcm = session.getClassMeta(elementName, pMeta, eType);
-               if (tcm != null)
-                       sType = eType = tcm;
-
-               Object o = null;
-
-               if (jsonType == NULL) {
-                       r.nextTag();    // Discard end tag
-                       return null;
-               }
-
-               if (sType.isObject()) {
-                       if (jsonType == OBJECT) {
-                               ObjectMap m = new ObjectMap(session);
-                               parseIntoMap(session, r, m, string(), object(), 
pMeta);
-                               if (wrapperAttr != null)
-                                       m = new 
ObjectMap(session).append(wrapperAttr, m);
-                               o = session.cast(m, pMeta, eType);
-                       } else if (jsonType == ARRAY)
-                               o = parseIntoCollection(session, r, new 
ObjectList(session), null, pMeta);
-                       else if (jsonType == STRING) {
-                               o = session.getElementText(r);
-                               if (sType.isChar())
-                                       o = o.toString().charAt(0);
-                       }
-                       else if (jsonType == NUMBER)
-                               o = parseNumber(session.getElementText(r), 
null);
-                       else if (jsonType == BOOLEAN)
-                               o = 
Boolean.parseBoolean(session.getElementText(r));
-                       else if (jsonType == UNKNOWN)
-                               o = getUnknown(session, r);
-               } else if (sType.isBoolean()) {
-                       o = Boolean.parseBoolean(session.getElementText(r));
-               } else if (sType.isCharSequence()) {
-                       o = session.getElementText(r);
-               } else if (sType.isChar()) {
-                       String s = session.getElementText(r);
-                       o = s.length() == 0 ? 0 : s.charAt(0);
-               } else if (sType.isMap()) {
-                       Map m = (sType.canCreateNewInstance(outer) ? 
(Map)sType.newInstance(outer) : new ObjectMap(session));
-                       o = parseIntoMap(session, r, m, sType.getKeyType(), 
sType.getValueType(), pMeta);
-                       if (wrapperAttr != null)
-                               o = new ObjectMap(session).append(wrapperAttr, 
m);
-               } else if (sType.isCollection()) {
-                       Collection l = (sType.canCreateNewInstance(outer) ? 
(Collection)sType.newInstance(outer) : new ObjectList(session));
-                       o = parseIntoCollection(session, r, l, sType, pMeta);
-               } else if (sType.isNumber()) {
-                       o = parseNumber(session.getElementText(r), (Class<? 
extends Number>)sType.getInnerClass());
-               } else if (sType.canCreateNewBean(outer)) {
-                       if 
(sType.getExtendedMeta(XmlClassMeta.class).getFormat() == COLLAPSED) {
-                               String fieldName = r.getLocalName();
-                               BeanMap<?> m = session.newBeanMap(outer, 
sType.getInnerClass());
-                               BeanPropertyMeta bpm = 
m.getMeta().getExtendedMeta(XmlBeanMeta.class).getPropertyMeta(fieldName);
-                               ClassMeta<?> cm = m.getMeta().getClassMeta();
-                               Object value = parseAnything(session, cm, 
currAttr, r, m.getBean(false), false, null);
-                               setName(cm, value, currAttr);
-                               bpm.set(m, currAttr, value);
-                               o = m.getBean();
-                       } else {
-                               BeanMap m = session.newBeanMap(outer, 
sType.getInnerClass());
-                               o = parseIntoBean(session, r, m).getBean();
-                       }
-               } else if (sType.isArray() || sType.isArgs()) {
-                       ArrayList l = (ArrayList)parseIntoCollection(session, 
r, new ArrayList(), sType, pMeta);
-                       o = session.toArray(sType, l);
-               } else if (sType.canCreateNewInstanceFromString(outer)) {
-                       o = sType.newInstanceFromString(outer, 
session.getElementText(r));
-               } else if (sType.canCreateNewInstanceFromNumber(outer)) {
-                       o = sType.newInstanceFromNumber(session, outer, 
parseNumber(session.getElementText(r), sType.getNewInstanceFromNumberClass()));
-               } else {
-                       throw new ParseException(session,
-                               "Class ''{0}'' could not be instantiated.  
Reason: ''{1}'', property: ''{2}''",
-                               sType.getInnerClass().getName(), 
sType.getNotABeanReason(), pMeta == null ? null : pMeta.getName());
-               }
-
-               if (transform != null && o != null)
-                       o = transform.unswap(session, o, eType);
-
-               if (outer != null)
-                       setParent(eType, o, outer);
-
-               return (T)o;
-       }
-
-       private <K,V> Map<K,V> parseIntoMap(XmlParserSession session, 
XMLStreamReader r, Map<K,V> m, ClassMeta<K> keyType,
-                       ClassMeta<V> valueType, BeanPropertyMeta pMeta) throws 
Exception {
-               int depth = 0;
-               for (int i = 0; i < r.getAttributeCount(); i++) {
-                       String a = r.getAttributeLocalName(i);
-                       // TODO - Need better handling of namespaces here.
-                       if (! 
(a.equals(session.getBeanTypePropertyName(null)))) {
-                               K key = session.trim(convertAttrToType(session, 
m, a, keyType));
-                               V value = 
session.trim(convertAttrToType(session, m, r.getAttributeValue(i), valueType));
-                               setName(valueType, value, key);
-                               m.put(key, value);
-                       }
-               }
-               do {
-                       int event = r.nextTag();
-                       String currAttr;
-                       if (event == START_ELEMENT) {
-                               depth++;
-                               currAttr = session.getElementName(r);
-                               K key = convertAttrToType(session, m, currAttr, 
keyType);
-                               V value = parseAnything(session, valueType, 
currAttr, r, m, false, pMeta);
-                               setName(valueType, value, currAttr);
-                               if (valueType.isObject() && m.containsKey(key)) 
{
-                                       Object o = m.get(key);
-                                       if (o instanceof List)
-                                               ((List)o).add(value);
-                                       else
-                                               m.put(key, (V)new ObjectList(o, 
value).setBeanSession(session));
-                               } else {
-                                       m.put(key, value);
-                               }
-                       } else if (event == END_ELEMENT) {
-                               depth--;
-                               return m;
-                       }
-               } while (depth > 0);
-               return m;
-       }
-
-       private <E> Collection<E> parseIntoCollection(XmlParserSession session, 
XMLStreamReader r, Collection<E> l,
-                       ClassMeta<?> type, BeanPropertyMeta pMeta) throws 
Exception {
-               int depth = 0;
-               int argIndex = 0;
-               do {
-                       int event = r.nextTag();
-                       if (event == START_ELEMENT) {
-                               depth++;
-                               ClassMeta<?> elementType = type == null ? 
object() : type.isArgs() ? type.getArg(argIndex++) : type.getElementType();
-                               E value = (E)parseAnything(session, 
elementType, null, r, l, false, pMeta);
-                               l.add(value);
-                       } else if (event == END_ELEMENT) {
-                               depth--;
-                               return l;
-                       }
-               } while (depth > 0);
-               return l;
-       }
-
-       private static int getJsonType(String s) {
-               if (s == null)
-                       return UNKNOWN;
-               char c = s.charAt(0);
-               switch(c) {
-                       case 'o': return (s.equals("object") ? OBJECT : 
UNKNOWN);
-                       case 'a': return (s.equals("array") ? ARRAY : UNKNOWN);
-                       case 's': return (s.equals("string") ? STRING : 
UNKNOWN);
-                       case 'b': return (s.equals("boolean") ? BOOLEAN : 
UNKNOWN);
-                       case 'n': {
-                               c = s.charAt(2);
-                               switch(c) {
-                                       case 'm': return (s.equals("number") ? 
NUMBER : UNKNOWN);
-                                       case 'l': return (s.equals("null") ? 
NULL : UNKNOWN);
-                               }
-                               //return NUMBER;
-                       }
-               }
-               return UNKNOWN;
-       }
-
-       private <T> BeanMap<T> parseIntoBean(XmlParserSession session, 
XMLStreamReader r, BeanMap<T> m) throws Exception {
-               BeanMeta<?> bMeta = m.getMeta();
-               XmlBeanMeta xmlMeta = bMeta.getExtendedMeta(XmlBeanMeta.class);
-
-               for (int i = 0; i < r.getAttributeCount(); i++) {
-                       String key = session.getAttributeName(r, i);
-                       String val = r.getAttributeValue(i);
-                       BeanPropertyMeta bpm = xmlMeta.getPropertyMeta(key);
-                       if (bpm == null) {
-                               if (xmlMeta.getAttrsProperty() != null) {
-                                       xmlMeta.getAttrsProperty().add(m, key, 
key, val);
-                               } else {
-                                       Location l = r.getLocation();
-                                       session.onUnknownProperty(key, m, 
l.getLineNumber(), l.getColumnNumber());
-                               }
-                       } else {
-                               bpm.set(m, key, val);
-                       }
-               }
-
-               BeanPropertyMeta cp = xmlMeta.getContentProperty();
-               XmlFormat cpf = xmlMeta.getContentFormat();
-               boolean trim = cp == null || ! cpf.isOneOf(MIXED_PWS, TEXT_PWS);
-               ClassMeta<?> cpcm = (cp == null ? session.object() : 
cp.getClassMeta());
-               StringBuilder sb = null;
-               BeanRegistry breg = cp == null ? null : cp.getBeanRegistry();
-               LinkedList<Object> l = null;
-
-               int depth = 0;
-               do {
-                       int event = r.next();
-                       String currAttr;
-                       // We only care about text in MIXED mode.
-                       // Ignore if in ELEMENTS mode.
-                       if (event == CHARACTERS) {
-                               if (cp != null && cpf.isOneOf(MIXED, 
MIXED_PWS)) {
-                                       if (cpcm.isCollectionOrArray()) {
-                                               if (l == null)
-                                                       l = new 
LinkedList<Object>();
-                                               l.add(session.getText(r, 
false));
-                                       } else {
-                                               cp.set(m, null, 
session.getText(r, trim));
-                                       }
-                               } else if (cpf != ELEMENTS) {
-                                       String s = session.getText(r, trim);
-                                       if (s != null) {
-                                               if (sb == null)
-                                                       sb = 
session.getStringBuilder();
-                                               sb.append(s);
-                                       }
-                               } else {
-                                       // Do nothing...we're in ELEMENTS mode.
-                               }
-                       } else if (event == START_ELEMENT) {
-                               if (cp != null && cpf.isOneOf(TEXT, TEXT_PWS)) {
-                                       String s = session.parseText(r);
-                                       if (s != null) {
-                                               if (sb == null)
-                                                       sb = 
session.getStringBuilder();
-                                               sb.append(s);
-                                       }
-                                       depth--;
-                               } else if (cpf == XMLTEXT) {
-                                       if (sb == null)
-                                               sb = session.getStringBuilder();
-                                       
sb.append(session.getElementAsString(r));
-                                       depth++;
-                               } else if (cp != null && cpf.isOneOf(MIXED, 
MIXED_PWS)) {
-                                       if (session.isWhitespaceElement(r) && 
(breg == null || ! breg.hasName(r.getLocalName()))) {
-                                               if (cpcm.isCollectionOrArray()) 
{
-                                                       if (l == null)
-                                                               l = new 
LinkedList<Object>();
-                                                       
l.add(session.parseWhitespaceElement(r));
-                                               } else {
-                                                       cp.set(m, null, 
session.parseWhitespaceElement(r));
-                                               }
-                                       } else {
-                                               if (cpcm.isCollectionOrArray()) 
{
-                                                       if (l == null)
-                                                               l = new 
LinkedList<Object>();
-                                                       
l.add(parseAnything(session, cpcm.getElementType(), cp.getName(), r, 
m.getBean(false), false, cp));
-                                               } else {
-                                                       cp.set(m, null, 
parseAnything(session, cpcm, cp.getName(), r, m.getBean(false), false, cp));
-                                               }
-                                       }
-                               } else if (cp != null && cpf == ELEMENTS) {
-                                       cp.add(m, null, parseAnything(session, 
cpcm.getElementType(), cp.getName(), r, m.getBean(false), false, cp));
-                               } else {
-                                       currAttr = session.getElementName(r);
-                                       BeanPropertyMeta pMeta = 
xmlMeta.getPropertyMeta(currAttr);
-                                       if (pMeta == null) {
-                                               Location loc = r.getLocation();
-                                               
session.onUnknownProperty(currAttr, m, loc.getLineNumber(), 
loc.getColumnNumber());
-                                               skipCurrentTag(r);
-                                       } else {
-                                               
session.setCurrentProperty(pMeta);
-                                               XmlFormat xf = 
pMeta.getExtendedMeta(XmlBeanPropertyMeta.class).getXmlFormat();
-                                               if (xf == COLLAPSED) {
-                                                       ClassMeta<?> et = 
pMeta.getClassMeta().getElementType();
-                                                       Object value = 
parseAnything(session, et, currAttr, r, m.getBean(false), false, pMeta);
-                                                       setName(et, value, 
currAttr);
-                                                       pMeta.add(m, currAttr, 
value);
-                                               } else if (xf == ATTR)  {
-                                                       pMeta.set(m, currAttr, 
session.getAttributeValue(r, 0));
-                                                       r.nextTag();
-                                               } else {
-                                                       ClassMeta<?> cm = 
pMeta.getClassMeta();
-                                                       Object value = 
parseAnything(session, cm, currAttr, r, m.getBean(false), false, pMeta);
-                                                       setName(cm, value, 
currAttr);
-                                                       pMeta.set(m, currAttr, 
value);
-                                               }
-                                               
session.setCurrentProperty(null);
-                                       }
-                               }
-                       } else if (event == END_ELEMENT) {
-                               if (depth > 0) {
-                                       if (cpf == XMLTEXT) {
-                                               if (sb == null)
-                                                       sb = 
session.getStringBuilder();
-                                               
sb.append(session.getElementAsString(r));
-                                       }
-                                       else
-                                               throw new ParseException("End 
element found where one was not expected.  {0}", XmlUtils.toReadableEvent(r));
-                               }
-                               depth--;
-                       } else {
-                               throw new ParseException("Unexpected event 
type: {0}", XmlUtils.toReadableEvent(r));
-                       }
-               } while (depth >= 0);
-
-               if (sb != null && cp != null)
-                       cp.set(m, null, sb.toString());
-               else if (l != null && cp != null)
-                       cp.set(m, null, XmlUtils.collapseTextNodes(l));
-
-               session.returnStringBuilder(sb);
-               return m;
-       }
-
-       private static void skipCurrentTag(XMLStreamReader r) throws 
XMLStreamException {
-               int depth = 1;
-               do {
-                       int event = r.next();
-                       if (event == START_ELEMENT)
-                               depth++;
-                       else if (event == END_ELEMENT)
-                               depth--;
-               } while (depth > 0);
-       }
-
-       private Object getUnknown(XmlParserSession session, XMLStreamReader r) 
throws Exception {
-               if (r.getEventType() != XMLStreamConstants.START_ELEMENT) {
-                       throw new XmlParseException(r.getLocation(), "Parser 
must be on START_ELEMENT to read next text.");
-               }
-               ObjectMap m = null;
-
-               // If this element has attributes, then it's always an 
ObjectMap.
-               if (r.getAttributeCount() > 0) {
-                       m = new ObjectMap(session);
-                       for (int i = 0; i < r.getAttributeCount(); i++) {
-                               String key = session.getAttributeName(r, i);
-                               String val = r.getAttributeValue(i);
-                               if (! 
key.equals(session.getBeanTypePropertyName(null)))
-                                       m.put(key, val);
-                       }
-               }
-               int eventType = r.next();
-               StringBuilder sb = session.getStringBuilder();
-               while (eventType != XMLStreamConstants.END_ELEMENT) {
-                       if (eventType == XMLStreamConstants.CHARACTERS || 
eventType == XMLStreamConstants.CDATA || eventType == XMLStreamConstants.SPACE 
|| eventType == XMLStreamConstants.ENTITY_REFERENCE) {
-                               sb.append(r.getText());
-                       } else if (eventType == 
XMLStreamConstants.PROCESSING_INSTRUCTION || eventType == 
XMLStreamConstants.COMMENT) {
-                               // skipping
-                       } else if (eventType == 
XMLStreamConstants.END_DOCUMENT) {
-                               throw new XmlParseException(r.getLocation(), 
"Unexpected end of document when reading element text content");
-                       } else if (eventType == 
XMLStreamConstants.START_ELEMENT) {
-                               // Oops...this has an element in it.
-                               // Parse it as a map.
-                               if (m == null)
-                                       m = new ObjectMap(session);
-                               int depth = 0;
-                               do {
-                                       int event = (eventType == -1 ? 
r.nextTag() : eventType);
-                                       String currAttr;
-                                       if (event == START_ELEMENT) {
-                                               depth++;
-                                               currAttr = 
session.getElementName(r);
-                                               String key = 
convertAttrToType(session, null, currAttr, string());
-                                               Object value = 
parseAnything(session, object(), currAttr, r, null, false, null);
-                                               if (m.containsKey(key)) {
-                                                       Object o = m.get(key);
-                                                       if (o instanceof 
ObjectList)
-                                                               
((ObjectList)o).add(value);
-                                                       else
-                                                               m.put(key, new 
ObjectList(o, value).setBeanSession(session));
-                                               } else {
-                                                       m.put(key, value);
-                                               }
-
-                                       } else if (event == END_ELEMENT) {
-                                               depth--;
-                                               break;
-                                       }
-                                       eventType = -1;
-                               } while (depth > 0);
-                               break;
-                       } else {
-                               throw new XmlParseException(r.getLocation(), 
"Unexpected event type ''{0}''", eventType);
-                       }
-                       eventType = r.next();
-               }
-               String s = sb.toString();
-               session.returnStringBuilder(sb);
-               s = session.decodeString(s);
-               if (m != null) {
-                       if (! s.isEmpty())
-                               m.put("contents", s);
-                       return m;
-               }
-               return s;
-       }
-
-
-       
//--------------------------------------------------------------------------------
-       // Entry point methods
-       
//--------------------------------------------------------------------------------
-
        @Override /* Parser */
-       public XmlParserSession createSession(Object input, ObjectMap op, 
Method javaMethod, Object outer, Locale locale,
-                       TimeZone timeZone, MediaType mediaType) {
-               return new XmlParserSession(ctx, op, input, javaMethod, outer, 
locale, timeZone, mediaType);
-       }
-
-       @Override /* Parser */
-       protected <T> T doParse(ParserSession session, ClassMeta<T> type) 
throws Exception {
-               XmlParserSession s = (XmlParserSession)session;
-               return parseAnything(s, type, null, s.getXmlStreamReader(), 
s.getOuter(), true, null);
-       }
-
-       @Override /* ReaderParser */
-       protected <K,V> Map<K,V> doParseIntoMap(ParserSession session, Map<K,V> 
m, Type keyType, Type valueType) throws Exception {
-               XmlParserSession s = (XmlParserSession)session;
-               ClassMeta cm = session.getClassMeta(m.getClass(), keyType, 
valueType);
-               return parseIntoMap(s, m, cm.getKeyType(), cm.getValueType());
-       }
-
-       @Override /* ReaderParser */
-       protected <E> Collection<E> doParseIntoCollection(ParserSession 
session, Collection<E> c, Type elementType) throws Exception {
-               XmlParserSession s = (XmlParserSession)session;
-               ClassMeta cm = session.getClassMeta(c.getClass(), elementType);
-               return parseIntoCollection(s,c, cm.getElementType());
+       public ReaderParserSession createSession(ParserSessionArgs args) {
+               return new XmlParserSession(ctx, args);
        }
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2a37f310/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserSession.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserSession.java 
b/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserSession.java
index 3dd0d13..1f41d56 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlParserSession.java
@@ -14,9 +14,9 @@ package org.apache.juneau.xml;
 
 import static javax.xml.stream.XMLStreamConstants.*;
 import static org.apache.juneau.xml.XmlParserContext.*;
-import static org.apache.juneau.internal.IOUtils.*;
+import static org.apache.juneau.xml.annotation.XmlFormat.*;
+import static org.apache.juneau.internal.StringUtils.*;
 
-import java.io.*;
 import java.lang.reflect.*;
 import java.util.*;
 
@@ -24,17 +24,22 @@ import javax.xml.stream.*;
 import javax.xml.stream.util.*;
 
 import org.apache.juneau.*;
-import org.apache.juneau.http.*;
 import org.apache.juneau.parser.*;
+import org.apache.juneau.transform.*;
 import org.apache.juneau.xml.annotation.*;
 
 /**
  * Session object that lives for the duration of a single use of {@link 
XmlParser}.
  *
  * <p>
- * This class is NOT thread safe.  It is meant to be discarded after one-time 
use.
+ * This class is NOT thread safe.
+ * It is typically discarded after one-time use although it can be reused 
against multiple inputs.
  */
-public class XmlParserSession extends ParserSession {
+@SuppressWarnings({ "unchecked", "rawtypes" })
+public class XmlParserSession extends ReaderParserSession {
+
+       private static final int UNKNOWN=0, OBJECT=1, ARRAY=2, STRING=3, 
NUMBER=4, BOOLEAN=5, NULL=6;
+
 
        private final boolean
                validating,
@@ -42,8 +47,7 @@ public class XmlParserSession extends ParserSession {
        private final XMLReporter reporter;
        private final XMLResolver resolver;
        private final XMLEventAllocator eventAllocator;
-       private XMLStreamReader xmlStreamReader;
-       private final StringBuilder sb = new StringBuilder();  // Reusable 
string builder used in this class.
+       private final StringBuilder rsb = new StringBuilder();  // Reusable 
string builder used in this class.
 
        /**
         * Create a new session using properties specified in the context.
@@ -51,89 +55,36 @@ public class XmlParserSession extends ParserSession {
         * @param ctx
         *      The context creating this session object.
         *      The context contains all the configuration settings for this 
object.
-        * @param input
-        *      The input.
-        *      Can be any of the following types:
-        *      <ul>
-        *              <li><jk>null</jk>
-        *              <li>{@link Reader}
-        *              <li>{@link CharSequence}
-        *              <li>{@link InputStream} containing UTF-8 encoded text.
-        *              <li>{@link File} containing system encoded text.
-        *      </ul>
-        * @param op
-        *      The override properties.
-        *      These override any context properties defined in the context.
-        * @param javaMethod The java method that called this parser, usually 
the method in a REST servlet.
-        * @param outer The outer object for instantiating top-level non-static 
inner classes.
-        * @param locale
-        *      The session locale.
-        *      If <jk>null</jk>, then the locale defined on the context is 
used.
-        * @param timeZone
-        *      The session timezone.
-        *      If <jk>null</jk>, then the timezone defined on the context is 
used.
-        * @param mediaType The session media type (e.g. 
<js>"application/json"</js>).
+        * @param args
+        *      Runtime session arguments.
         */
-       public XmlParserSession(XmlParserContext ctx, ObjectMap op, Object 
input, Method javaMethod, Object outer,
-                       Locale locale, TimeZone timeZone, MediaType mediaType) {
-               super(ctx, op, input, javaMethod, outer, locale, timeZone, 
mediaType);
-               if (op == null || op.isEmpty()) {
+       protected XmlParserSession(XmlParserContext ctx, ParserSessionArgs 
args) {
+               super(ctx, args);
+               ObjectMap p = getProperties();
+               if (p.isEmpty()) {
                        validating = ctx.validating;
                        reporter = ctx.reporter;
                        resolver = ctx.resolver;
                        eventAllocator = ctx.eventAllocator;
                        preserveRootElement = ctx.preserveRootElement;
                } else {
-                       validating = op.getBoolean(XML_validating, 
ctx.validating);
-                       reporter = (XMLReporter)op.get(XML_reporter, 
ctx.reporter);
-                       resolver = (XMLResolver)op.get(XML_resolver, 
ctx.resolver);
-                       eventAllocator = 
(XMLEventAllocator)op.get(XML_eventAllocator, ctx.eventAllocator);
-                       preserveRootElement = 
op.getBoolean(XML_preserveRootElement, ctx.preserveRootElement);
+                       validating = p.getBoolean(XML_validating, 
ctx.validating);
+                       reporter = (XMLReporter)p.get(XML_reporter, 
ctx.reporter);
+                       resolver = (XMLResolver)p.get(XML_resolver, 
ctx.resolver);
+                       eventAllocator = 
(XMLEventAllocator)p.get(XML_eventAllocator, ctx.eventAllocator);
+                       preserveRootElement = 
p.getBoolean(XML_preserveRootElement, ctx.preserveRootElement);
                }
        }
 
        /**
-        * Returns the {@link XmlParserContext#XML_preserveRootElement} setting 
value for this session.
-        *
-        * @return The {@link XmlParserContext#XML_preserveRootElement} setting 
value for this session.
-        */
-       public final boolean isPreserveRootElement() {
-               return preserveRootElement;
-       }
-
-       /**
         * Wrap the specified reader in a STAX reader based on settings in this 
context.
         *
+        * @param pipe The parser input.
         * @return The new STAX reader.
         * @throws Exception If problem occurred trying to create reader.
         */
-       public final XMLStreamReader getXmlStreamReader() throws Exception {
-               if (xmlStreamReader != null)
-                       return xmlStreamReader;
-
-               try {
-                       Reader r = getBufferedReader(getReader());
-                       XMLInputFactory factory = XMLInputFactory.newInstance();
-                       factory.setProperty(XMLInputFactory.IS_VALIDATING, 
validating);
-                       factory.setProperty(XMLInputFactory.IS_COALESCING, 
true);
-                       
factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, true);  // 
This usually has no effect anyway.
-                       if 
(factory.isPropertySupported(XMLInputFactory.REPORTER) && reporter != null)
-                               factory.setProperty(XMLInputFactory.REPORTER, 
reporter);
-                       if 
(factory.isPropertySupported(XMLInputFactory.RESOLVER) && resolver != null)
-                               factory.setProperty(XMLInputFactory.RESOLVER, 
resolver);
-                       if 
(factory.isPropertySupported(XMLInputFactory.ALLOCATOR) && eventAllocator != 
null)
-                               factory.setProperty(XMLInputFactory.ALLOCATOR, 
eventAllocator);
-                       xmlStreamReader = factory.createXMLStreamReader(r);
-                       xmlStreamReader.nextTag();
-               } catch (Error e) {
-                       close();
-                       throw new ParseException(e.getLocalizedMessage());
-               } catch (XMLStreamException e) {
-                       close();
-                       throw new ParseException(e);
-               }
-
-               return xmlStreamReader;
+       protected final XmlReader getXmlReader(ParserPipe pipe) throws 
Exception {
+               return new XmlReader(pipe, validating, reporter, resolver, 
eventAllocator);
        }
 
        /**
@@ -145,57 +96,37 @@ public class XmlParserSession extends ParserSession {
         * @param s The string to be decoded.
         * @return The decoded string.
         */
-       public final String decodeString(String s) {
+       protected final String decodeString(String s) {
                if (s == null)
                        return null;
-               sb.setLength(0);
-               s = XmlUtils.decode(s, sb);
+               rsb.setLength(0);
+               s = XmlUtils.decode(s, rsb);
                if (isTrimStrings())
                        s = s.trim();
                return s;
        }
 
-       /**
+       /*
         * Returns the name of the current XML element.
-        *
-        * <p>
         * Any <js>'_x####_'</js> sequences in the string will be decoded.
-        *
-        * @param r The reader to read from.
-        * @return The decoded element name.
-        * @throws XMLStreamException
         */
-       public final String getElementName(XMLStreamReader r) throws 
XMLStreamException {
+       private String getElementName(XmlReader r) {
                return decodeString(r.getLocalName());
        }
 
-       /**
+       /*
         * Returns the name of the specified attribute on the current XML 
element.
-        *
-        * <p>
         * Any <js>'_x####_'</js> sequences in the string will be decoded.
-        *
-        * @param r The reader to read from.
-        * @param i The attribute index.
-        * @return The decoded attribute name.
-        * @throws XMLStreamException
         */
-       public final String getAttributeName(XMLStreamReader r, int i) throws 
XMLStreamException {
+       private String getAttributeName(XmlReader r, int i) {
                return decodeString(r.getAttributeLocalName(i));
        }
 
-       /**
+       /*
         * Returns the value of the specified attribute on the current XML 
element.
-        *
-        * <p>
         * Any <js>'_x####_'</js> sequences in the string will be decoded.
-        *
-        * @param r The reader to read from.
-        * @param i The attribute index.
-        * @return The decoded attribute value.
-        * @throws XMLStreamException
         */
-       public final String getAttributeValue(XMLStreamReader r, int i) throws 
XMLStreamException {
+       private String getAttributeValue(XmlReader r, int i) {
                return decodeString(r.getAttributeValue(i));
        }
 
@@ -212,28 +143,16 @@ public class XmlParserSession extends ParserSession {
         * @return The decoded text.  <jk>null</jk> if the text consists of the 
sequence <js>'_x0000_'</js>.
         * @throws Exception
         */
-       public String getElementText(XMLStreamReader r) throws Exception {
-               String s = r.getElementText().trim();
-               return decodeString(s);
+       protected String getElementText(XmlReader r) throws Exception {
+               return decodeString(r.getElementText().trim());
        }
 
-       /**
+       /*
         * Returns the content of the current CHARACTERS node.
-        *
-        * <p>
         * Any <js>'_x####_'</js> sequences in the string will be decoded.
-        *
-        * <p>
         * Leading and trailing whitespace (unencoded) will be trimmed from the 
result.
-        *
-        * @param r The reader to read the element text from.
-        * @param trim
-        *      If <jk>true</jk>, trim the contents of the text node BEFORE 
decoding escape sequences.
-        *      Typically <jk>true</jk> for {@link XmlFormat#MIXED_PWS} and 
{@link XmlFormat#TEXT_PWS}.
-        * @return The decoded text.  <jk>null</jk> if the text consists of the 
sequence <js>'_x0000_'</js>.
-        * @throws XMLStreamException
         */
-       public String getText(XMLStreamReader r, boolean trim) throws 
XMLStreamException {
+       private String getText(XmlReader r, boolean trim) {
                String s = r.getText();
                if (trim)
                        s = s.trim();
@@ -242,52 +161,41 @@ public class XmlParserSession extends ParserSession {
                return decodeString(s);
        }
 
-       /**
+       /*
         * Shortcut for calling <code>getText(r, <jk>true</jk>);</code>.
-        *
-        * @param r The reader to read the element text from.
-        * @return The decoded text.  <jk>null</jk> if the text consists of the 
sequence <js>'_x0000_'</js>.
-        * @throws XMLStreamException
         */
-       public String getText(XMLStreamReader r) throws XMLStreamException {
+       private String getText(XmlReader r) {
                return getText(r, true);
        }
 
-       /**
+       /*
         * Takes the element being read from the XML stream reader and 
reconstructs it as XML.
-        *
-        * <p>
         * Used when reconstructing bean properties of type {@link 
XmlFormat#XMLTEXT}.
-        *
-        * @param r The XML stream reader to read the current event from.
-        * @return The event as XML.
-        * @throws RuntimeException if the event is not a start or end tag.
         */
-       public final String getElementAsString(XMLStreamReader r) {
+       private String getElementAsString(XmlReader r) {
                int t = r.getEventType();
                if (t > 2)
                        throw new FormattedRuntimeException("Invalid event type 
on stream reader for elementToString() method: ''{0}''", 
XmlUtils.toReadableEvent(r));
-               sb.setLength(0);
-               sb.append("<").append(t == 1 ? "" : 
"/").append(r.getLocalName());
+               rsb.setLength(0);
+               rsb.append("<").append(t == 1 ? "" : 
"/").append(r.getLocalName());
                if (t == 1)
                        for (int i = 0; i < r.getAttributeCount(); i++)
-                               sb.append(' 
').append(r.getAttributeName(i)).append('=').append('\'').append(r.getAttributeValue(i)).append('\'');
-               sb.append('>');
-               return sb.toString();
+                               rsb.append(' 
').append(r.getAttributeName(i)).append('=').append('\'').append(r.getAttributeValue(i)).append('\'');
+               rsb.append('>');
+               return rsb.toString();
        }
 
        /**
         * Parses the current element as text.
         *
-        * <p>
-        * Note that this is different than {@link #getText(XMLStreamReader)} 
since it assumes that we're pointing to a
-        * whitespace element.
-        *
         * @param r
         * @return The parsed text.
         * @throws Exception
         */
-       public String parseText(XMLStreamReader r) throws Exception {
+       protected String parseText(XmlReader r) throws Exception {
+               // Note that this is different than {@link #getText(XmlReader)} 
since it assumes that we're pointing to a
+               // whitespace element.
+
                StringBuilder sb2 = getStringBuilder();
 
                int depth = 0;
@@ -321,7 +229,7 @@ public class XmlParserSession extends ParserSession {
         * @param r The XML stream reader to read the current event from.
         * @return <jk>true</jk> if the current element is a whitespace element.
         */
-       public boolean isWhitespaceElement(XMLStreamReader r) {
+       protected boolean isWhitespaceElement(XmlReader r) {
                return false;
        }
 
@@ -337,24 +245,449 @@ public class XmlParserSession extends ParserSession {
         * @throws XMLStreamException
         * @throws Exception
         */
-       public String parseWhitespaceElement(XMLStreamReader r) throws 
Exception {
+       protected String parseWhitespaceElement(XmlReader r) throws Exception {
                return null;
        }
 
+       @Override /* ParserSession */
+       protected <T> T doParse(ParserPipe pipe, ClassMeta<T> type) throws 
Exception {
+               return parseAnything(type, null, getXmlReader(pipe), 
getOuter(), true, null);
+       }
+
+       @Override /* ReaderParserSession */
+       protected <K,V> Map<K,V> doParseIntoMap(ParserPipe pipe, Map<K,V> m, 
Type keyType, Type valueType) throws Exception {
+               ClassMeta cm = getClassMeta(m.getClass(), keyType, valueType);
+               return parseIntoMap(pipe, m, cm.getKeyType(), 
cm.getValueType());
+       }
+
+       @Override /* ReaderParserSession */
+       protected <E> Collection<E> doParseIntoCollection(ParserPipe pipe, 
Collection<E> c, Type elementType) throws Exception {
+               ClassMeta cm = getClassMeta(c.getClass(), elementType);
+               return parseIntoCollection(pipe, c, cm.getElementType());
+       }
+
        /**
-        * Silently closes the XML stream.
+        * Workhorse method.
+        *
+        * @param eType The expected type of object.
+        * @param currAttr The current bean property name.
+        * @param r The reader.
+        * @param outer The outer object.
+        * @param isRoot If <jk>true</jk>, then we're serializing a root 
element in the document.
+        * @param pMeta The bean property metadata.
+        * @return The parsed object.
+        * @throws Exception
         */
-       @Override /* ParserContext */
-       public boolean close() {
-               if (super.close()) {
-                       try {
-                               if (xmlStreamReader != null)
-                                       xmlStreamReader.close();
-                       } catch (XMLStreamException e) {
-                               // Ignore.
+       protected <T> T parseAnything(ClassMeta<T> eType, String currAttr, 
XmlReader r,
+                       Object outer, boolean isRoot, BeanPropertyMeta pMeta) 
throws Exception {
+
+               if (eType == null)
+                       eType = (ClassMeta<T>)object();
+               PojoSwap<T,Object> transform = 
(PojoSwap<T,Object>)eType.getPojoSwap();
+               ClassMeta<?> sType = eType.getSerializedClassMeta();
+               setCurrentClass(sType);
+
+               String wrapperAttr = (isRoot && preserveRootElement) ? 
r.getName().getLocalPart() : null;
+               String typeAttr = r.getAttributeValue(null, 
getBeanTypePropertyName(eType));
+               int jsonType = getJsonType(typeAttr);
+               String elementName = getElementName(r);
+               if (jsonType == 0) {
+                       if (elementName == null || elementName.equals(currAttr))
+                               jsonType = UNKNOWN;
+                       else {
+                               typeAttr = elementName;
+                               jsonType = getJsonType(elementName);
                        }
-                       return true;
                }
-               return false;
+
+               ClassMeta tcm = getClassMeta(typeAttr, pMeta, eType);
+               if (tcm == null && elementName != null && ! 
elementName.equals(currAttr))
+                       tcm = getClassMeta(elementName, pMeta, eType);
+               if (tcm != null)
+                       sType = eType = tcm;
+
+               Object o = null;
+
+               if (jsonType == NULL) {
+                       r.nextTag();    // Discard end tag
+                       return null;
+               }
+
+               if (sType.isObject()) {
+                       if (jsonType == OBJECT) {
+                               ObjectMap m = new ObjectMap(this);
+                               parseIntoMap(r, m, string(), object(), pMeta);
+                               if (wrapperAttr != null)
+                                       m = new 
ObjectMap(this).append(wrapperAttr, m);
+                               o = cast(m, pMeta, eType);
+                       } else if (jsonType == ARRAY)
+                               o = parseIntoCollection(r, new 
ObjectList(this), null, pMeta);
+                       else if (jsonType == STRING) {
+                               o = getElementText(r);
+                               if (sType.isChar())
+                                       o = o.toString().charAt(0);
+                       }
+                       else if (jsonType == NUMBER)
+                               o = parseNumber(getElementText(r), null);
+                       else if (jsonType == BOOLEAN)
+                               o = Boolean.parseBoolean(getElementText(r));
+                       else if (jsonType == UNKNOWN)
+                               o = getUnknown(r);
+               } else if (sType.isBoolean()) {
+                       o = Boolean.parseBoolean(getElementText(r));
+               } else if (sType.isCharSequence()) {
+                       o = getElementText(r);
+               } else if (sType.isChar()) {
+                       String s = getElementText(r);
+                       o = s.length() == 0 ? 0 : s.charAt(0);
+               } else if (sType.isMap()) {
+                       Map m = (sType.canCreateNewInstance(outer) ? 
(Map)sType.newInstance(outer) : new ObjectMap(this));
+                       o = parseIntoMap(r, m, sType.getKeyType(), 
sType.getValueType(), pMeta);
+                       if (wrapperAttr != null)
+                               o = new ObjectMap(this).append(wrapperAttr, m);
+               } else if (sType.isCollection()) {
+                       Collection l = (sType.canCreateNewInstance(outer) ? 
(Collection)sType.newInstance(outer) : new ObjectList(this));
+                       o = parseIntoCollection(r, l, sType, pMeta);
+               } else if (sType.isNumber()) {
+                       o = parseNumber(getElementText(r), (Class<? extends 
Number>)sType.getInnerClass());
+               } else if (sType.canCreateNewBean(outer)) {
+                       if 
(sType.getExtendedMeta(XmlClassMeta.class).getFormat() == COLLAPSED) {
+                               String fieldName = r.getLocalName();
+                               BeanMap<?> m = newBeanMap(outer, 
sType.getInnerClass());
+                               BeanPropertyMeta bpm = 
m.getMeta().getExtendedMeta(XmlBeanMeta.class).getPropertyMeta(fieldName);
+                               ClassMeta<?> cm = m.getMeta().getClassMeta();
+                               Object value = parseAnything(cm, currAttr, r, 
m.getBean(false), false, null);
+                               setName(cm, value, currAttr);
+                               bpm.set(m, currAttr, value);
+                               o = m.getBean();
+                       } else {
+                               BeanMap m = newBeanMap(outer, 
sType.getInnerClass());
+                               o = parseIntoBean(r, m).getBean();
+                       }
+               } else if (sType.isArray() || sType.isArgs()) {
+                       ArrayList l = (ArrayList)parseIntoCollection(r, new 
ArrayList(), sType, pMeta);
+                       o = toArray(sType, l);
+               } else if (sType.canCreateNewInstanceFromString(outer)) {
+                       o = sType.newInstanceFromString(outer, 
getElementText(r));
+               } else if (sType.canCreateNewInstanceFromNumber(outer)) {
+                       o = sType.newInstanceFromNumber(this, outer, 
parseNumber(getElementText(r), sType.getNewInstanceFromNumberClass()));
+               } else {
+                       throw new ParseException(loc(r),
+                               "Class ''{0}'' could not be instantiated.  
Reason: ''{1}'', property: ''{2}''",
+                               sType.getInnerClass().getName(), 
sType.getNotABeanReason(), pMeta == null ? null : pMeta.getName());
+               }
+
+               if (transform != null && o != null)
+                       o = transform.unswap(this, o, eType);
+
+               if (outer != null)
+                       setParent(eType, o, outer);
+
+               return (T)o;
+       }
+
+       private <K,V> Map<K,V> parseIntoMap(XmlReader r, Map<K,V> m, 
ClassMeta<K> keyType,
+                       ClassMeta<V> valueType, BeanPropertyMeta pMeta) throws 
Exception {
+               int depth = 0;
+               for (int i = 0; i < r.getAttributeCount(); i++) {
+                       String a = r.getAttributeLocalName(i);
+                       // TODO - Need better handling of namespaces here.
+                       if (! (a.equals(getBeanTypePropertyName(null)))) {
+                               K key = trim(convertAttrToType(m, a, keyType));
+                               V value = trim(convertAttrToType(m, 
r.getAttributeValue(i), valueType));
+                               setName(valueType, value, key);
+                               m.put(key, value);
+                       }
+               }
+               do {
+                       int event = r.nextTag();
+                       String currAttr;
+                       if (event == START_ELEMENT) {
+                               depth++;
+                               currAttr = getElementName(r);
+                               K key = convertAttrToType(m, currAttr, keyType);
+                               V value = parseAnything(valueType, currAttr, r, 
m, false, pMeta);
+                               setName(valueType, value, currAttr);
+                               if (valueType.isObject() && m.containsKey(key)) 
{
+                                       Object o = m.get(key);
+                                       if (o instanceof List)
+                                               ((List)o).add(value);
+                                       else
+                                               m.put(key, (V)new ObjectList(o, 
value).setBeanSession(this));
+                               } else {
+                                       m.put(key, value);
+                               }
+                       } else if (event == END_ELEMENT) {
+                               depth--;
+                               return m;
+                       }
+               } while (depth > 0);
+               return m;
+       }
+
+       private <E> Collection<E> parseIntoCollection(XmlReader r, 
Collection<E> l,
+                       ClassMeta<?> type, BeanPropertyMeta pMeta) throws 
Exception {
+               int depth = 0;
+               int argIndex = 0;
+               do {
+                       int event = r.nextTag();
+                       if (event == START_ELEMENT) {
+                               depth++;
+                               ClassMeta<?> elementType = type == null ? 
object() : type.isArgs() ? type.getArg(argIndex++) : type.getElementType();
+                               E value = (E)parseAnything(elementType, null, 
r, l, false, pMeta);
+                               l.add(value);
+                       } else if (event == END_ELEMENT) {
+                               depth--;
+                               return l;
+                       }
+               } while (depth > 0);
+               return l;
+       }
+
+       private static int getJsonType(String s) {
+               if (s == null)
+                       return UNKNOWN;
+               char c = s.charAt(0);
+               switch(c) {
+                       case 'o': return (s.equals("object") ? OBJECT : 
UNKNOWN);
+                       case 'a': return (s.equals("array") ? ARRAY : UNKNOWN);
+                       case 's': return (s.equals("string") ? STRING : 
UNKNOWN);
+                       case 'b': return (s.equals("boolean") ? BOOLEAN : 
UNKNOWN);
+                       case 'n': {
+                               c = s.charAt(2);
+                               switch(c) {
+                                       case 'm': return (s.equals("number") ? 
NUMBER : UNKNOWN);
+                                       case 'l': return (s.equals("null") ? 
NULL : UNKNOWN);
+                               }
+                               //return NUMBER;
+                       }
+               }
+               return UNKNOWN;
+       }
+
+       private <T> BeanMap<T> parseIntoBean(XmlReader r, BeanMap<T> m) throws 
Exception {
+               BeanMeta<?> bMeta = m.getMeta();
+               XmlBeanMeta xmlMeta = bMeta.getExtendedMeta(XmlBeanMeta.class);
+
+               for (int i = 0; i < r.getAttributeCount(); i++) {
+                       String key = getAttributeName(r, i);
+                       String val = r.getAttributeValue(i);
+                       BeanPropertyMeta bpm = xmlMeta.getPropertyMeta(key);
+                       if (bpm == null) {
+                               if (xmlMeta.getAttrsProperty() != null) {
+                                       xmlMeta.getAttrsProperty().add(m, key, 
key, val);
+                               } else {
+                                       Location l = r.getLocation();
+                                       onUnknownProperty(r.getPipe(), key, m, 
l.getLineNumber(), l.getColumnNumber());
+                               }
+                       } else {
+                               bpm.set(m, key, val);
+                       }
+               }
+
+               BeanPropertyMeta cp = xmlMeta.getContentProperty();
+               XmlFormat cpf = xmlMeta.getContentFormat();
+               boolean trim = cp == null || ! cpf.isOneOf(MIXED_PWS, TEXT_PWS);
+               ClassMeta<?> cpcm = (cp == null ? object() : cp.getClassMeta());
+               StringBuilder sb = null;
+               BeanRegistry breg = cp == null ? null : cp.getBeanRegistry();
+               LinkedList<Object> l = null;
+
+               int depth = 0;
+               do {
+                       int event = r.next();
+                       String currAttr;
+                       // We only care about text in MIXED mode.
+                       // Ignore if in ELEMENTS mode.
+                       if (event == CHARACTERS) {
+                               if (cp != null && cpf.isOneOf(MIXED, 
MIXED_PWS)) {
+                                       if (cpcm.isCollectionOrArray()) {
+                                               if (l == null)
+                                                       l = new 
LinkedList<Object>();
+                                               l.add(getText(r, false));
+                                       } else {
+                                               cp.set(m, null, getText(r, 
trim));
+                                       }
+                               } else if (cpf != ELEMENTS) {
+                                       String s = getText(r, trim);
+                                       if (s != null) {
+                                               if (sb == null)
+                                                       sb = getStringBuilder();
+                                               sb.append(s);
+                                       }
+                               } else {
+                                       // Do nothing...we're in ELEMENTS mode.
+                               }
+                       } else if (event == START_ELEMENT) {
+                               if (cp != null && cpf.isOneOf(TEXT, TEXT_PWS)) {
+                                       String s = parseText(r);
+                                       if (s != null) {
+                                               if (sb == null)
+                                                       sb = getStringBuilder();
+                                               sb.append(s);
+                                       }
+                                       depth--;
+                               } else if (cpf == XMLTEXT) {
+                                       if (sb == null)
+                                               sb = getStringBuilder();
+                                       sb.append(getElementAsString(r));
+                                       depth++;
+                               } else if (cp != null && cpf.isOneOf(MIXED, 
MIXED_PWS)) {
+                                       if (isWhitespaceElement(r) && (breg == 
null || ! breg.hasName(r.getLocalName()))) {
+                                               if (cpcm.isCollectionOrArray()) 
{
+                                                       if (l == null)
+                                                               l = new 
LinkedList<Object>();
+                                                       
l.add(parseWhitespaceElement(r));
+                                               } else {
+                                                       cp.set(m, null, 
parseWhitespaceElement(r));
+                                               }
+                                       } else {
+                                               if (cpcm.isCollectionOrArray()) 
{
+                                                       if (l == null)
+                                                               l = new 
LinkedList<Object>();
+                                                       
l.add(parseAnything(cpcm.getElementType(), cp.getName(), r, m.getBean(false), 
false, cp));
+                                               } else {
+                                                       cp.set(m, null, 
parseAnything(cpcm, cp.getName(), r, m.getBean(false), false, cp));
+                                               }
+                                       }
+                               } else if (cp != null && cpf == ELEMENTS) {
+                                       cp.add(m, null, 
parseAnything(cpcm.getElementType(), cp.getName(), r, m.getBean(false), false, 
cp));
+                               } else {
+                                       currAttr = getElementName(r);
+                                       BeanPropertyMeta pMeta = 
xmlMeta.getPropertyMeta(currAttr);
+                                       if (pMeta == null) {
+                                               Location loc = r.getLocation();
+                                               onUnknownProperty(r.getPipe(), 
currAttr, m, loc.getLineNumber(), loc.getColumnNumber());
+                                               skipCurrentTag(r);
+                                       } else {
+                                               setCurrentProperty(pMeta);
+                                               XmlFormat xf = 
pMeta.getExtendedMeta(XmlBeanPropertyMeta.class).getXmlFormat();
+                                               if (xf == COLLAPSED) {
+                                                       ClassMeta<?> et = 
pMeta.getClassMeta().getElementType();
+                                                       Object value = 
parseAnything(et, currAttr, r, m.getBean(false), false, pMeta);
+                                                       setName(et, value, 
currAttr);
+                                                       pMeta.add(m, currAttr, 
value);
+                                               } else if (xf == ATTR)  {
+                                                       pMeta.set(m, currAttr, 
getAttributeValue(r, 0));
+                                                       r.nextTag();
+                                               } else {
+                                                       ClassMeta<?> cm = 
pMeta.getClassMeta();
+                                                       Object value = 
parseAnything(cm, currAttr, r, m.getBean(false), false, pMeta);
+                                                       setName(cm, value, 
currAttr);
+                                                       pMeta.set(m, currAttr, 
value);
+                                               }
+                                               setCurrentProperty(null);
+                                       }
+                               }
+                       } else if (event == END_ELEMENT) {
+                               if (depth > 0) {
+                                       if (cpf == XMLTEXT) {
+                                               if (sb == null)
+                                                       sb = getStringBuilder();
+                                               
sb.append(getElementAsString(r));
+                                       }
+                                       else
+                                               throw new ParseException("End 
element found where one was not expected.  {0}", XmlUtils.toReadableEvent(r));
+                               }
+                               depth--;
+                       } else {
+                               throw new ParseException("Unexpected event 
type: {0}", XmlUtils.toReadableEvent(r));
+                       }
+               } while (depth >= 0);
+
+               if (sb != null && cp != null)
+                       cp.set(m, null, sb.toString());
+               else if (l != null && cp != null)
+                       cp.set(m, null, XmlUtils.collapseTextNodes(l));
+
+               returnStringBuilder(sb);
+               return m;
+       }
+
+       private static void skipCurrentTag(XmlReader r) throws 
XMLStreamException {
+               int depth = 1;
+               do {
+                       int event = r.next();
+                       if (event == START_ELEMENT)
+                               depth++;
+                       else if (event == END_ELEMENT)
+                               depth--;
+               } while (depth > 0);
+       }
+
+       private Object getUnknown(XmlReader r) throws Exception {
+               if (r.getEventType() != START_ELEMENT) {
+                       throw new XmlParseException(r.getLocation(), "Parser 
must be on START_ELEMENT to read next text.");
+               }
+               ObjectMap m = null;
+
+               // If this element has attributes, then it's always an 
ObjectMap.
+               if (r.getAttributeCount() > 0) {
+                       m = new ObjectMap(this);
+                       for (int i = 0; i < r.getAttributeCount(); i++) {
+                               String key = getAttributeName(r, i);
+                               String val = r.getAttributeValue(i);
+                               if (! key.equals(getBeanTypePropertyName(null)))
+                                       m.put(key, val);
+                       }
+               }
+               int eventType = r.next();
+               StringBuilder sb = getStringBuilder();
+               while (eventType != END_ELEMENT) {
+                       if (eventType == CHARACTERS || eventType == CDATA || 
eventType == SPACE || eventType == ENTITY_REFERENCE) {
+                               sb.append(r.getText());
+                       } else if (eventType == PROCESSING_INSTRUCTION || 
eventType == COMMENT) {
+                               // skipping
+                       } else if (eventType == END_DOCUMENT) {
+                               throw new XmlParseException(r.getLocation(), 
"Unexpected end of document when reading element text content");
+                       } else if (eventType == START_ELEMENT) {
+                               // Oops...this has an element in it.
+                               // Parse it as a map.
+                               if (m == null)
+                                       m = new ObjectMap(this);
+                               int depth = 0;
+                               do {
+                                       int event = (eventType == -1 ? 
r.nextTag() : eventType);
+                                       String currAttr;
+                                       if (event == START_ELEMENT) {
+                                               depth++;
+                                               currAttr = getElementName(r);
+                                               String key = 
convertAttrToType(null, currAttr, string());
+                                               Object value = 
parseAnything(object(), currAttr, r, null, false, null);
+                                               if (m.containsKey(key)) {
+                                                       Object o = m.get(key);
+                                                       if (o instanceof 
ObjectList)
+                                                               
((ObjectList)o).add(value);
+                                                       else
+                                                               m.put(key, new 
ObjectList(o, value).setBeanSession(this));
+                                               } else {
+                                                       m.put(key, value);
+                                               }
+
+                                       } else if (event == END_ELEMENT) {
+                                               depth--;
+                                               break;
+                                       }
+                                       eventType = -1;
+                               } while (depth > 0);
+                               break;
+                       } else {
+                               throw new XmlParseException(r.getLocation(), 
"Unexpected event type ''{0}''", eventType);
+                       }
+                       eventType = r.next();
+               }
+               String s = sb.toString();
+               returnStringBuilder(sb);
+               s = decodeString(s);
+               if (m != null) {
+                       if (! s.isEmpty())
+                               m.put("contents", s);
+                       return m;
+               }
+               return s;
+       }
+
+       private ObjectMap loc(XmlReader r) {
+               return getLastLocation().append("line", 
r.getLocation().getLineNumber()).append("column", 
r.getLocation().getColumnNumber());
        }
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2a37f310/juneau-core/src/main/java/org/apache/juneau/xml/XmlReader.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlReader.java 
b/juneau-core/src/main/java/org/apache/juneau/xml/XmlReader.java
new file mode 100644
index 0000000..50c0e5e
--- /dev/null
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlReader.java
@@ -0,0 +1,301 @@
+// 
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                
                                              *
+// *                                                                           
                                              *
+// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
+// *                                                                           
                                              *
+// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the 
License.                                              *
+// 
***************************************************************************************************************************
+package org.apache.juneau.xml;
+
+import java.io.*;
+
+import javax.xml.namespace.*;
+import javax.xml.stream.*;
+import javax.xml.stream.util.*;
+
+import org.apache.juneau.parser.*;
+
+/**
+ * Wrapper class around a {@link XMLStreamReader}.
+ *
+ * <p>
+ * The purpose is to encapsulate the reader with the {@link ParserPipe} object 
so that it can be retrieved for
+ * debugging purposes.
+ */
+public final class XmlReader implements XMLStreamReader {
+
+       private final ParserPipe pipe;
+       private final XMLStreamReader sr;
+
+       /**
+        * Constructor.
+        *
+        * @param pipe The parser input.
+        * @param validating The value for the {@link 
XMLInputFactory#IS_VALIDATING} setting.
+        * @param reporter The value for the {@link XMLInputFactory#REPORTER} 
setting.
+        * @param resolver The value for the {@link XMLInputFactory#RESOLVER} 
setting.
+        * @param eventAllocator The value for the {@link 
XMLInputFactory#ALLOCATOR} setting.
+        * @throws Exception
+        */
+       protected XmlReader(ParserPipe pipe, boolean validating, XMLReporter 
reporter, XMLResolver resolver, XMLEventAllocator eventAllocator) throws 
Exception {
+               this.pipe = pipe;
+               try {
+                       Reader r = pipe.getBufferedReader();
+                       XMLInputFactory factory = XMLInputFactory.newInstance();
+                       factory.setProperty(XMLInputFactory.IS_VALIDATING, 
validating);
+                       factory.setProperty(XMLInputFactory.IS_COALESCING, 
true);
+                       
factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, true);  // 
This usually has no effect anyway.
+                       if 
(factory.isPropertySupported(XMLInputFactory.REPORTER) && reporter != null)
+                               factory.setProperty(XMLInputFactory.REPORTER, 
reporter);
+                       if 
(factory.isPropertySupported(XMLInputFactory.RESOLVER) && resolver != null)
+                               factory.setProperty(XMLInputFactory.RESOLVER, 
resolver);
+                       if 
(factory.isPropertySupported(XMLInputFactory.ALLOCATOR) && eventAllocator != 
null)
+                               factory.setProperty(XMLInputFactory.ALLOCATOR, 
eventAllocator);
+                       sr = factory.createXMLStreamReader(r);
+                       sr.nextTag();
+               } catch (Error e) {
+                       throw new ParseException(e.getLocalizedMessage());
+               } catch (XMLStreamException e) {
+                       throw new ParseException(e);
+               }
+       }
+
+       /**
+        * Returns the pipe passed into the constructor.
+        *
+        * @return The pipe passed into the constructor.
+        */
+       public ParserPipe getPipe() {
+               return pipe;
+       }
+
+       @Override /* XMLStreamReader */
+       public void close() throws XMLStreamException {
+               sr.close();
+       }
+
+       @Override /* XMLStreamReader */
+       public int getAttributeCount() {
+               return sr.getAttributeCount();
+       }
+
+       @Override /* XMLStreamReader */
+       public String getAttributeLocalName(int index) {
+               return sr.getAttributeLocalName(index);
+       }
+
+       @Override /* XMLStreamReader */
+       public QName getAttributeName(int index) {
+               return sr.getAttributeName(index);
+       }
+
+       @Override /* XMLStreamReader */
+       public String getAttributeNamespace(int index) {
+               return sr.getAttributeNamespace(index);
+       }
+
+       @Override /* XMLStreamReader */
+       public String getAttributePrefix(int index) {
+               return sr.getAttributePrefix(index);
+       }
+
+       @Override /* XMLStreamReader */
+       public String getAttributeType(int index) {
+               return sr.getAttributeType(index);
+       }
+
+       @Override /* XMLStreamReader */
+       public String getAttributeValue(int index) {
+               return sr.getAttributeValue(index);
+       }
+
+       @Override /* XMLStreamReader */
+       public String getAttributeValue(String namespaceURI, String localName) {
+               return sr.getAttributeValue(namespaceURI, localName);
+       }
+
+       @Override /* XMLStreamReader */
+       public String getCharacterEncodingScheme() {
+               return sr.getCharacterEncodingScheme();
+       }
+
+       @Override /* XMLStreamReader */
+       public String getElementText() throws XMLStreamException {
+               return sr.getElementText();
+       }
+
+       @Override /* XMLStreamReader */
+       public String getEncoding() {
+               return sr.getEncoding();
+       }
+
+       @Override /* XMLStreamReader */
+       public int getEventType() {
+               return sr.getEventType();
+       }
+
+       @Override /* XMLStreamReader */
+       public String getLocalName() {
+               return sr.getLocalName();
+       }
+
+       @Override /* XMLStreamReader */
+       public Location getLocation() {
+               return sr.getLocation();
+       }
+
+       @Override /* XMLStreamReader */
+       public QName getName() {
+               return sr.getName();
+       }
+
+       @Override /* XMLStreamReader */
+       public NamespaceContext getNamespaceContext() {
+               return sr.getNamespaceContext();
+       }
+
+       @Override /* XMLStreamReader */
+       public int getNamespaceCount() {
+               return sr.getNamespaceCount();
+       }
+
+       @Override /* XMLStreamReader */
+       public String getNamespacePrefix(int index) {
+               return sr.getNamespacePrefix(index);
+       }
+
+       @Override /* XMLStreamReader */
+       public String getNamespaceURI() {
+               return sr.getNamespaceURI();
+       }
+
+       @Override /* XMLStreamReader */
+       public String getNamespaceURI(String prefix) {
+               return sr.getNamespaceURI(prefix);
+       }
+
+       @Override /* XMLStreamReader */
+       public String getNamespaceURI(int index) {
+               return sr.getNamespaceURI(index);
+       }
+
+       @Override /* XMLStreamReader */
+       public String getPIData() {
+               return sr.getPIData();
+       }
+
+       @Override /* XMLStreamReader */
+       public String getPITarget() {
+               return sr.getPITarget();
+       }
+
+       @Override /* XMLStreamReader */
+       public String getPrefix() {
+               return sr.getPrefix();
+       }
+
+       @Override /* XMLStreamReader */
+       public Object getProperty(String name) throws IllegalArgumentException {
+               return sr.getProperty(name);
+       }
+
+       @Override /* XMLStreamReader */
+       public String getText() {
+               return sr.getText();
+       }
+
+       @Override /* XMLStreamReader */
+       public char[] getTextCharacters() {
+               return sr.getTextCharacters();
+       }
+
+       @Override /* XMLStreamReader */
+       public int getTextCharacters(int sourceStart, char[] target, int 
targetStart, int length) throws XMLStreamException {
+               return sr.getTextCharacters(sourceStart, target, targetStart, 
length);
+       }
+
+       @Override /* XMLStreamReader */
+       public int getTextLength() {
+               return sr.getTextLength();
+       }
+
+       @Override /* XMLStreamReader */
+       public int getTextStart() {
+               return sr.getTextStart();
+       }
+
+       @Override /* XMLStreamReader */
+       public String getVersion() {
+               return sr.getVersion();
+       }
+
+       @Override /* XMLStreamReader */
+       public boolean hasName() {
+               return sr.hasName();
+       }
+
+       @Override /* XMLStreamReader */
+       public boolean hasNext() throws XMLStreamException {
+               return sr.hasNext();
+       }
+
+       @Override /* XMLStreamReader */
+       public boolean hasText() {
+               return sr.hasText();
+       }
+
+       @Override /* XMLStreamReader */
+       public boolean isAttributeSpecified(int index) {
+               return sr.isAttributeSpecified(index);
+       }
+
+       @Override /* XMLStreamReader */
+       public boolean isCharacters() {
+               return sr.isCharacters();
+       }
+
+       @Override /* XMLStreamReader */
+       public boolean isEndElement() {
+               return sr.isEndElement();
+       }
+
+       @Override /* XMLStreamReader */
+       public boolean isStandalone() {
+               return sr.isStandalone();
+       }
+
+       @Override /* XMLStreamReader */
+       public boolean isStartElement() {
+               return sr.isStartElement();
+       }
+
+       @Override /* XMLStreamReader */
+       public boolean isWhiteSpace() {
+               return sr.isWhiteSpace();
+       }
+
+       @Override /* XMLStreamReader */
+       public int next() throws XMLStreamException {
+               return sr.next();
+       }
+
+       @Override /* XMLStreamReader */
+       public int nextTag() throws XMLStreamException {
+               return sr.nextTag();
+       }
+
+       @Override /* XMLStreamReader */
+       public void require(int type, String namespaceURI, String localName) 
throws XMLStreamException {
+               sr.require(type, namespaceURI, localName);
+       }
+
+       @Override /* XMLStreamReader */
+       public boolean standaloneSet() {
+               return sr.standaloneSet();
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/2a37f310/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaDocSerializer.java
----------------------------------------------------------------------
diff --git 
a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaDocSerializer.java 
b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaDocSerializer.java
index 34cbab0..4c1e89e 100644
--- 
a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaDocSerializer.java
+++ 
b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaDocSerializer.java
@@ -42,18 +42,11 @@ public class XmlSchemaDocSerializer extends 
XmlSchemaSerializer {
         * @param propertyStore The property store containing all the settings 
for this object.
         */
        public XmlSchemaDocSerializer(PropertyStore propertyStore) {
-               super(propertyStore, null);
+               super(propertyStore);
        }
 
        @Override /* Serializer */
-       protected void doSerialize(SerializerSession session, SerializerOutput 
out, Object o) throws Exception {
-               XmlSerializerSession s = (XmlSerializerSession)session;
-               XmlWriter w = s.getXmlWriter(out);
-               w.append("<?xml")
-                       .attr("version", "1.0")
-                       .attr("encoding", "UTF-8")
-                       .appendln("?>");
-               w.flush();
-               super.doSerialize(s, out, o);
+       public WriterSerializerSession createSession(SerializerSessionArgs 
args) {
+               return new XmlSchemaSerializerSession(ctx, args);
        }
 }

Reply via email to