[SCM] Hessian: simple binary protocol for connecting web services branch, master, updated. debian/4.0.6-1-1-g407db2e

Emmanuel Bourg ebourg at apache.org
Sat Apr 13 23:38:27 UTC 2013


The following commit has been merged in the master branch:
commit 407db2ed00d9da34a35c317c8d36a05bb82fe352
Author: Emmanuel Bourg <ebourg at apache.org>
Date:   Sun Apr 14 01:36:53 2013 +0200

    New upstream release (4.0.35)
    Removed the test classes from the generated jar
    debian/watch: Updated to find the latest versions of Hessian
    debian/control: Updated the dependency on the Servlet API (2.5 -> 3.0)
    debian/control: Bumped Standards-Version to 3.9.4 (no changes)
    debian/copyright: Updated to comply with the Machine-readable format 1.0
    debian/copyright: Replaced the generic Apache License 1.1 with the variant actually used upstream

diff --git a/com/caucho/burlap/client/BurlapProxy.java b/com/caucho/burlap/client/BurlapProxy.java
index 93f7861..da8ab60 100644
--- a/com/caucho/burlap/client/BurlapProxy.java
+++ b/com/caucho/burlap/client/BurlapProxy.java
@@ -136,9 +136,9 @@ public class BurlapProxy implements InvocationHandler {
       OutputStream os;
 
       try {
-	os = conn.getOutputStream();
+        os = conn.getOutputStream();
       } catch (Exception e) {
-	throw new BurlapRuntimeException(e);
+        throw new BurlapRuntimeException(e);
       }
 
       BurlapOutput out = _factory.getBurlapOutput(os);
@@ -151,18 +151,18 @@ public class BurlapProxy implements InvocationHandler {
         methodName = methodName + "__0";
 
       if (log.isLoggable(Level.FINE))
-	log.fine(this + " calling " + methodName + " (" + method + ")");
+        log.fine(this + " calling " + methodName + " (" + method + ")");
 
       out.call(methodName, args);
 
       try {
-	os.flush();
+        os.flush();
       } catch (Exception e) {
-	throw new BurlapRuntimeException(e);
+        throw new BurlapRuntimeException(e);
       }
 
       if (conn instanceof HttpURLConnection) {
-	httpConn = (HttpURLConnection) conn;
+        httpConn = (HttpURLConnection) conn;
         int code = 500;
 
         try {
@@ -210,13 +210,13 @@ public class BurlapProxy implements InvocationHandler {
       throw new BurlapRuntimeException(e);
     } finally {
       try {
-	if (is != null)
-	  is.close();
+        if (is != null)
+          is.close();
       } catch (IOException e) {
       }
       
       if (httpConn != null)
-	httpConn.disconnect();
+        httpConn.disconnect();
     }
   }
 
diff --git a/com/caucho/burlap/client/BurlapProxyFactory.java b/com/caucho/burlap/client/BurlapProxyFactory.java
index 08999ab..c514364 100644
--- a/com/caucho/burlap/client/BurlapProxyFactory.java
+++ b/com/caucho/burlap/client/BurlapProxyFactory.java
@@ -286,7 +286,7 @@ public class BurlapProxyFactory implements ServiceProxyFactory, ObjectFactory {
    */
   public Object getObjectInstance(Object obj, Name name,
                                   Context nameCtx,
-				  Hashtable<?,?> environment)
+                                  Hashtable<?,?> environment)
     throws Exception
   {
     Reference ref = (Reference) obj;
diff --git a/com/caucho/burlap/io/BurlapInput.java b/com/caucho/burlap/io/BurlapInput.java
index e421dd2..5f971b5 100644
--- a/com/caucho/burlap/io/BurlapInput.java
+++ b/com/caucho/burlap/io/BurlapInput.java
@@ -355,12 +355,12 @@ public class BurlapInput extends AbstractBurlapInput {
       _replyFault = (Throwable) detail;
       
       if (message != null && _detailMessageField != null) {
-	try {
-	  _detailMessageField.set(_replyFault, message);
-	} catch (Throwable e) {
-	}
+        try {
+          _detailMessageField.set(_replyFault, message);
+        } catch (Throwable e) {
+        }
       }
-	
+
       return _replyFault;
     }
 
@@ -1330,7 +1330,7 @@ public class BurlapInput extends AbstractBurlapInput {
       while (ch >= '0' && ch <= '9') {
         ms = 10 * ms + ch - '0';
 
-	ch = read();
+        ch = read();
       }
     }
 
diff --git a/com/caucho/burlap/server/BurlapServlet.java b/com/caucho/burlap/server/BurlapServlet.java
index c5c692d..b333ac8 100644
--- a/com/caucho/burlap/server/BurlapServlet.java
+++ b/com/caucho/burlap/server/BurlapServlet.java
@@ -106,47 +106,47 @@ public class BurlapServlet extends GenericServlet {
     
     try {
       if (_service == null) {
-	String className = getInitParameter("service-class");
-	Class<?> serviceClass = null;
-
-	if (className != null) {
-	  ClassLoader loader = Thread.currentThread().getContextClassLoader();
-
-	  if (loader != null)
-	    serviceClass = Class.forName(className, false, loader);
-	  else
-	    serviceClass = Class.forName(className);
-	}
-	else {
-	  if (getClass().equals(BurlapServlet.class))
-	    throw new ServletException("server must extend BurlapServlet");
-
-	  serviceClass = getClass();
-	}
-
-	_service = serviceClass.newInstance();
-
-	if (_service instanceof BurlapServlet)
-	  ((BurlapServlet) _service).setService(this);
-	if (_service instanceof Service)
-	  ((Service) _service).init(getServletConfig());
-	else if (_service instanceof Servlet)
-	  ((Servlet) _service).init(getServletConfig());
+        String className = getInitParameter("service-class");
+        Class<?> serviceClass = null;
+
+        if (className != null) {
+          ClassLoader loader = Thread.currentThread().getContextClassLoader();
+
+          if (loader != null)
+            serviceClass = Class.forName(className, false, loader);
+          else
+            serviceClass = Class.forName(className);
+        }
+        else {
+          if (getClass().equals(BurlapServlet.class))
+            throw new ServletException("server must extend BurlapServlet");
+
+          serviceClass = getClass();
+        }
+
+        _service = serviceClass.newInstance();
+
+        if (_service instanceof BurlapServlet)
+          ((BurlapServlet) _service).setService(this);
+        if (_service instanceof Service)
+          ((Service) _service).init(getServletConfig());
+        else if (_service instanceof Servlet)
+          ((Servlet) _service).init(getServletConfig());
       }
       
       if (_apiClass == null) {
-	String className = getInitParameter("api-class");
-
-	if (className != null) {
-	  ClassLoader loader = Thread.currentThread().getContextClassLoader();
-
-	  if (loader != null)
-	    _apiClass = Class.forName(className, false, loader);
-	  else
-	    _apiClass = Class.forName(className);
-	}
-	else
-	  _apiClass = _service.getClass();
+        String className = getInitParameter("api-class");
+
+        if (className != null) {
+          ClassLoader loader = Thread.currentThread().getContextClassLoader();
+
+          if (loader != null)
+            _apiClass = Class.forName(className, false, loader);
+          else
+            _apiClass = Class.forName(className);
+        }
+        else
+          _apiClass = _service.getClass();
       }
 
       _skeleton = new BurlapSkeleton(_service, _apiClass);
@@ -182,7 +182,7 @@ public class BurlapServlet extends GenericServlet {
     if (objectId == null)
       objectId = req.getParameter("ejbid");
 
-    ServiceContext.begin(req, serviceId, objectId);
+    ServiceContext.begin(req, res, serviceId, objectId);
 
     try {
       InputStream is = request.getInputStream();
diff --git a/com/caucho/burlap/server/BurlapSkeleton.java b/com/caucho/burlap/server/BurlapSkeleton.java
index ed4045c..765550a 100644
--- a/com/caucho/burlap/server/BurlapSkeleton.java
+++ b/com/caucho/burlap/server/BurlapSkeleton.java
@@ -137,11 +137,11 @@ public class BurlapSkeleton extends AbstractSkeleton {
       String value = null;
 
       if ("java.api.class".equals(attrName))
-	value = getAPIClassName();
+        value = getAPIClassName();
       else if ("java.home.class".equals(attrName))
-	value = getHomeClassName();
+        value = getHomeClassName();
       else if ("java.object.class".equals(attrName))
-	value = getObjectClassName();
+        value = getObjectClassName();
 
       out.startReply();
 
@@ -153,8 +153,8 @@ public class BurlapSkeleton extends AbstractSkeleton {
     else if (method == null) {
       out.startReply();
       out.writeFault("NoSuchMethodException",
-		     "The service has no method named: " + in.getMethod(),
-		     null);
+                     "The service has no method named: " + in.getMethod(),
+                     null);
       out.completeReply();
       return;
     }
@@ -173,12 +173,12 @@ public class BurlapSkeleton extends AbstractSkeleton {
       result = method.invoke(service, values);
     } catch (Throwable e) {
       log.log(Level.FINE,
-	      service + "." + method.getName() + "() failed with exception:\n"
-	      + e.toString(),
-	      e);
+              service + "." + method.getName() + "() failed with exception:\n"
+              + e.toString(),
+              e);
       
       if (e instanceof InvocationTargetException
-	  && e.getCause() instanceof Exception)
+          && e.getCause() instanceof Exception)
         e = ((InvocationTargetException) e).getTargetException();
       out.startReply();
       out.writeFault("ServiceException", e.getMessage(), e);
diff --git a/com/caucho/hessian/HessianUnshared.java b/com/caucho/hessian/HessianUnshared.java
new file mode 100644
index 0000000..e1c366d
--- /dev/null
+++ b/com/caucho/hessian/HessianUnshared.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1998-2012 Caucho Technology -- all rights reserved
+ *
+ * This file is part of Resin(R) Open Source
+ *
+ * Each copy or derived work must preserve the copyright notice and this
+ * notice unmodified.
+ *
+ * Resin Open Source is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Resin Open Source is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
+ * of NON-INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Resin Open Source; if not, write to the
+ *
+ *   Free Software Foundation, Inc.
+ *   59 Temple Place, Suite 330
+ *   Boston, MA 02111-1307  USA
+ *
+ * @author Scott Ferguson
+ */
+
+package com.caucho.hessian;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Marks the class and all children as unshared.
+ * A reference item will be created, but will not be stored in a 
+ * mapped or checked for duplicated.
+ * 
+ * Used for efficiency to avoid the cost of the map lookup.
+ */
+ at Target({ElementType.TYPE })
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface HessianUnshared
+{
+}
diff --git a/com/caucho/hessian/client/AbstractHessianConnection.java b/com/caucho/hessian/client/AbstractHessianConnection.java
index fd6a9db..b27f938 100644
--- a/com/caucho/hessian/client/AbstractHessianConnection.java
+++ b/com/caucho/hessian/client/AbstractHessianConnection.java
@@ -93,6 +93,12 @@ abstract public class AbstractHessianConnection implements HessianConnection {
   abstract public InputStream getInputStream()
     throws IOException;
 
+  @Override
+  public String getContentEncoding()
+  {
+    return null;
+  }
+  
   /**
    * Close/free the connection, using keepalive if appropriate.
    */
diff --git a/com/caucho/hessian/client/HessianConnection.java b/com/caucho/hessian/client/HessianConnection.java
index 9057b7e..ef272f1 100644
--- a/com/caucho/hessian/client/HessianConnection.java
+++ b/com/caucho/hessian/client/HessianConnection.java
@@ -84,6 +84,12 @@ public interface HessianConnection {
    * Returns the status string.
    */
   public String getStatusMessage();
+  
+  /**
+   * Returns the content encoding
+   */
+  public String getContentEncoding();
+  
 
   /**
    * Returns the InputStream to the result
diff --git a/com/caucho/hessian/client/HessianProxy.java b/com/caucho/hessian/client/HessianProxy.java
index e0f0a02..cc4d51d 100644
--- a/com/caucho/hessian/client/HessianProxy.java
+++ b/com/caucho/hessian/client/HessianProxy.java
@@ -60,6 +60,7 @@ import java.util.WeakHashMap;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.net.URLConnection;
+import java.util.zip.*;
 
 /**
  * Proxy implementation for Hessian clients.  Applications will generally
@@ -127,36 +128,36 @@ public class HessianProxy implements InvocationHandler, Serializable {
 
       // equals and hashCode are special cased
       if (methodName.equals("equals")
-	  && params.length == 1 && params[0].equals(Object.class)) {
-	Object value = args[0];
-	if (value == null || ! Proxy.isProxyClass(value.getClass()))
-	  return Boolean.FALSE;
+          && params.length == 1 && params[0].equals(Object.class)) {
+        Object value = args[0];
+        if (value == null || ! Proxy.isProxyClass(value.getClass()))
+          return Boolean.FALSE;
 
-	Object proxyHandler = Proxy.getInvocationHandler(value);
+        Object proxyHandler = Proxy.getInvocationHandler(value);
 
-	if (! (proxyHandler instanceof HessianProxy))
-	  return Boolean.FALSE;
-	
-	HessianProxy handler = (HessianProxy) proxyHandler;
+        if (! (proxyHandler instanceof HessianProxy))
+          return Boolean.FALSE;
 
-	return new Boolean(_url.equals(handler.getURL()));
+        HessianProxy handler = (HessianProxy) proxyHandler;
+
+        return new Boolean(_url.equals(handler.getURL()));
       }
       else if (methodName.equals("hashCode") && params.length == 0)
-	return new Integer(_url.hashCode());
+        return new Integer(_url.hashCode());
       else if (methodName.equals("getHessianType"))
-	return proxy.getClass().getInterfaces()[0].getName();
+        return proxy.getClass().getInterfaces()[0].getName();
       else if (methodName.equals("getHessianURL"))
-	return _url.toString();
+        return _url.toString();
       else if (methodName.equals("toString") && params.length == 0)
-	return "HessianProxy[" + _url + "]";
+        return "HessianProxy[" + _url + "]";
       
       if (! _factory.isOverloadEnabled())
-	mangleName = method.getName();
+        mangleName = method.getName();
       else
         mangleName = mangleName(method);
 
       synchronized (_mangleMap) {
-	_mangleMap.put(method, mangleName);
+        _mangleMap.put(method, mangleName);
       }
     }
 
@@ -165,20 +166,20 @@ public class HessianProxy implements InvocationHandler, Serializable {
     
     try {
       if (log.isLoggable(Level.FINER))
-	log.finer("Hessian[" + _url + "] calling " + mangleName);
+        log.finer("Hessian[" + _url + "] calling " + mangleName);
       
       conn = sendRequest(mangleName, args);
 
-      is = conn.getInputStream();
+      is = getInputStream(conn);
 
       if (log.isLoggable(Level.FINEST)) {
-	PrintWriter dbg = new PrintWriter(new LogWriter(log));
-	HessianDebugInputStream dIs
-	  = new HessianDebugInputStream(is, dbg);
+        PrintWriter dbg = new PrintWriter(new LogWriter(log));
+        HessianDebugInputStream dIs
+          = new HessianDebugInputStream(is, dbg);
+
+        dIs.startTop2();
 
-	dIs.startTop2();
-	
-	is = dIs;
+        is = dIs;
       }
 
       AbstractHessianInput in;
@@ -186,55 +187,67 @@ public class HessianProxy implements InvocationHandler, Serializable {
       int code = is.read();
 
       if (code == 'H') {
-	int major = is.read();
-	int minor = is.read();
+        int major = is.read();
+        int minor = is.read();
 
-	in = _factory.getHessian2Input(is);
+        in = _factory.getHessian2Input(is);
 
-	Object value = in.readReply(method.getReturnType());
+        Object value = in.readReply(method.getReturnType());
 
-	return value;
+        return value;
       }
       else if (code == 'r') {
-	int major = is.read();
-	int minor = is.read();
-	
-	in = _factory.getHessianInput(is);
+        int major = is.read();
+        int minor = is.read();
+
+        in = _factory.getHessianInput(is);
 
-	in.startReplyBody();
+        in.startReplyBody();
 
-	Object value = in.readObject(method.getReturnType());
+        Object value = in.readObject(method.getReturnType());
 
-	if (value instanceof InputStream) {
-	  value = new ResultInputStream(conn, is, in, (InputStream) value);
-	  is = null;
-	  conn = null;
-	}
-	else
-	  in.completeReply();
+        if (value instanceof InputStream) {
+          value = new ResultInputStream(conn, is, in, (InputStream) value);
+          is = null;
+          conn = null;
+        }
+        else
+          in.completeReply();
 
-	return value;
+        return value;
       }
       else
-	throw new HessianProtocolException("'" + (char) code + "' is an unknown code");
+        throw new HessianProtocolException("'" + (char) code + "' is an unknown code");
     } catch (HessianProtocolException e) {
       throw new HessianRuntimeException(e);
     } finally {
       try {
-	if (is != null)
-	  is.close();
+        if (is != null)
+          is.close();
       } catch (Exception e) {
-	log.log(Level.FINE, e.toString(), e);
+        log.log(Level.FINE, e.toString(), e);
       }
       
       try {
-	if (conn != null)
-	  conn.destroy();
+        if (conn != null)
+          conn.destroy();
       } catch (Exception e) {
-	log.log(Level.FINE, e.toString(), e);
+        log.log(Level.FINE, e.toString(), e);
       }
     }
   }
+  
+  protected InputStream getInputStream(HessianConnection conn)
+    throws IOException
+  {
+    InputStream is = conn.getInputStream();
+
+    if ("deflate".equals(conn.getContentEncoding())) {
+      is = new InflaterInputStream(is, new Inflater(true));
+    }
+    
+    return is;
+  }
 
   protected String mangleName(Method method)
   {
@@ -263,16 +276,16 @@ public class HessianProxy implements InvocationHandler, Serializable {
       OutputStream os = null;
 
       try {
-	os = conn.getOutputStream();
+        os = conn.getOutputStream();
       } catch (Exception e) {
-	throw new HessianRuntimeException(e);
+        throw new HessianRuntimeException(e);
       }
 
       if (log.isLoggable(Level.FINEST)) {
-	PrintWriter dbg = new PrintWriter(new LogWriter(log));
-	HessianDebugOutputStream dOs = new HessianDebugOutputStream(os, dbg);
-	dOs.startTop2();
-	os = dOs;
+        PrintWriter dbg = new PrintWriter(new LogWriter(log));
+        HessianDebugOutputStream dOs = new HessianDebugOutputStream(os, dbg);
+        dOs.startTop2();
+        os = dOs;
       }
       
       AbstractHessianOutput out = _factory.getHessianOutput(os);
@@ -287,7 +300,7 @@ public class HessianProxy implements InvocationHandler, Serializable {
       return conn;
     } finally {
       if (! isValid && conn != null)
-	conn.destroy();
+        conn.destroy();
     }
   }
 
@@ -298,6 +311,7 @@ public class HessianProxy implements InvocationHandler, Serializable {
   protected void addRequestHeaders(HessianConnection conn)
   {
     conn.addHeader("Content-Type", "x-application/hessian");
+    conn.addHeader("Accept-Encoding", "deflate");
 
     String basicAuth = _factory.getBasicAuth();
 
@@ -326,9 +340,9 @@ public class HessianProxy implements InvocationHandler, Serializable {
     private InputStream _hessianIs;
 
     ResultInputStream(HessianConnection conn,
-		      InputStream is,
-		      AbstractHessianInput in,
-		      InputStream hessianIs)
+                      InputStream is,
+                      AbstractHessianInput in,
+                      InputStream hessianIs)
     {
       _conn = conn;
       _connIs = is;
@@ -340,30 +354,30 @@ public class HessianProxy implements InvocationHandler, Serializable {
       throws IOException
     {
       if (_hessianIs != null) {
-	int value = _hessianIs.read();
+        int value = _hessianIs.read();
 
-	if (value < 0)
-	  close();
+        if (value < 0)
+          close();
 
-	return value;
+        return value;
       }
       else
-	return -1;
+        return -1;
     }
 
     public int read(byte []buffer, int offset, int length)
       throws IOException
     {
       if (_hessianIs != null) {
-	int value = _hessianIs.read(buffer, offset, length);
+        int value = _hessianIs.read(buffer, offset, length);
 
-	if (value < 0)
-	  close();
+        if (value < 0)
+          close();
 
-	return value;
+        return value;
       }
       else
-	return -1;
+        return -1;
     }
 
     public void close()
@@ -382,35 +396,35 @@ public class HessianProxy implements InvocationHandler, Serializable {
       _hessianIs = null;
 
       try {
-	if (hessianIs != null)
-	  hessianIs.close();
+        if (hessianIs != null)
+          hessianIs.close();
       } catch (Exception e) {
-	log.log(Level.FINE, e.toString(), e);
+        log.log(Level.FINE, e.toString(), e);
       }
 
       try {
-	if (in != null) {
-	  in.completeReply();
-	  in.close();
-	}
+        if (in != null) {
+          in.completeReply();
+          in.close();
+        }
       } catch (Exception e) {
-	log.log(Level.FINE, e.toString(), e);
+        log.log(Level.FINE, e.toString(), e);
       }
 
       try {
-	if (connIs != null) {
-	  connIs.close();
-	}
+        if (connIs != null) {
+          connIs.close();
+        }
       } catch (Exception e) {
-	log.log(Level.FINE, e.toString(), e);
+        log.log(Level.FINE, e.toString(), e);
       }
 
       try {
-	if (conn != null) {
-	  conn.close();
-	}
+        if (conn != null) {
+          conn.close();
+        }
       } catch (Exception e) {
-	log.log(Level.FINE, e.toString(), e);
+        log.log(Level.FINE, e.toString(), e);
       }
     }
   }
@@ -428,24 +442,24 @@ public class HessianProxy implements InvocationHandler, Serializable {
     public void write(char ch)
     {
       if (ch == '\n' && _sb.length() > 0) {
-	_log.fine(_sb.toString());
-	_sb.setLength(0);
+        _log.fine(_sb.toString());
+        _sb.setLength(0);
       }
       else
-	_sb.append((char) ch);
+        _sb.append((char) ch);
     }
 
     public void write(char []buffer, int offset, int length)
     {
       for (int i = 0; i < length; i++) {
-	char ch = buffer[offset + i];
-	
-	if (ch == '\n' && _sb.length() > 0) {
-	  _log.log(_level, _sb.toString());
-	  _sb.setLength(0);
-	}
-	else
-	  _sb.append((char) ch);
+        char ch = buffer[offset + i];
+
+        if (ch == '\n' && _sb.length() > 0) {
+          _log.log(_level, _sb.toString());
+          _sb.setLength(0);
+        }
+        else
+          _sb.append((char) ch);
       }
     }
 
@@ -456,7 +470,7 @@ public class HessianProxy implements InvocationHandler, Serializable {
     public void close()
     {
       if (_sb.length() > 0)
-	_log.log(_level, _sb.toString());
+        _log.log(_level, _sb.toString());
     }
   }
 }
diff --git a/com/caucho/hessian/client/HessianProxyFactory.java b/com/caucho/hessian/client/HessianProxyFactory.java
index b43468c..e35204a 100644
--- a/com/caucho/hessian/client/HessianProxyFactory.java
+++ b/com/caucho/hessian/client/HessianProxyFactory.java
@@ -48,16 +48,6 @@
 
 package com.caucho.hessian.client;
 
-import com.caucho.hessian.io.*;
-import com.caucho.services.client.ServiceProxyFactory;
-
-import javax.naming.Context;
-import javax.naming.Name;
-import javax.naming.NamingException;
-import javax.naming.RefAddr;
-import javax.naming.Reference;
-import javax.naming.spi.ObjectFactory;
-import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PrintWriter;
@@ -65,12 +55,28 @@ import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Proxy;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.net.HttpURLConnection;
-import java.net.URLConnection;
 import java.util.Hashtable;
-import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.RefAddr;
+import javax.naming.Reference;
+import javax.naming.spi.ObjectFactory;
+
+import com.caucho.hessian.io.AbstractHessianInput;
+import com.caucho.hessian.io.AbstractHessianOutput;
+import com.caucho.hessian.io.Hessian2Input;
+import com.caucho.hessian.io.Hessian2Output;
+import com.caucho.hessian.io.HessianDebugInputStream;
+import com.caucho.hessian.io.HessianInput;
+import com.caucho.hessian.io.HessianOutput;
+import com.caucho.hessian.io.HessianRemoteObject;
+import com.caucho.hessian.io.HessianRemoteResolver;
+import com.caucho.hessian.io.SerializerFactory;
+import com.caucho.services.client.ServiceProxyFactory;
+
 /**
  * Factory for creating Hessian client stubs.  The returned stub will
  * call the remote object for all methods.
@@ -342,13 +348,13 @@ public class HessianProxyFactory implements ServiceProxyFactory, ObjectFactory {
       
     try {
       if (className != null) {
-	ClassLoader loader = Thread.currentThread().getContextClassLoader();
-	
-	Class<?> cl = Class.forName(className, false, loader);
+        ClassLoader loader = Thread.currentThread().getContextClassLoader();
+
+        Class<?> cl = Class.forName(className, false, loader);
 
-	factory = (HessianConnectionFactory) cl.newInstance();
+        factory = (HessianConnectionFactory) cl.newInstance();
 
-	return factory;
+        return factory;
       }
     } catch (Exception e) {
       throw new RuntimeException(e);
@@ -416,7 +422,7 @@ public class HessianProxyFactory implements ServiceProxyFactory, ObjectFactory {
    *
    * @return a proxy to the object with the specified interface.
    */
-  public Object create(Class api, String urlName, ClassLoader loader)
+  public Object create(Class<?> api, String urlName, ClassLoader loader)
     throws MalformedURLException
   {
     URL url = new URL(urlName);
@@ -519,9 +525,7 @@ public class HessianProxyFactory implements ServiceProxyFactory, ObjectFactory {
 
     String api = null;
     String url = null;
-    String user = null;
-    String password = null;
-
+    
     for (int i = 0; i < ref.size(); i++) {
       RefAddr addr = ref.get(i);
 
diff --git a/com/caucho/hessian/client/HessianURLConnection.java b/com/caucho/hessian/client/HessianURLConnection.java
index cb8c0c9..6f39b54 100644
--- a/com/caucho/hessian/client/HessianURLConnection.java
+++ b/com/caucho/hessian/client/HessianURLConnection.java
@@ -51,6 +51,8 @@ package com.caucho.hessian.client;
 import java.net.URL;
 import java.net.URLConnection;
 import java.net.HttpURLConnection;
+import java.util.zip.Inflater;
+import java.util.zip.InflaterInputStream;
 
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -80,6 +82,7 @@ public class HessianURLConnection extends AbstractHessianConnection {
   /**
    * Adds a HTTP header.
    */
+  @Override
   public void addHeader(String key, String value)
   {
     _conn.setRequestProperty(key, value);
@@ -106,7 +109,7 @@ public class HessianURLConnection extends AbstractHessianConnection {
       _statusCode = 500;
 
       try {
-	_statusCode = httpConn.getResponseCode();
+        _statusCode = httpConn.getResponseCode();
       } catch (Exception e) {
       }
 
@@ -115,39 +118,39 @@ public class HessianURLConnection extends AbstractHessianConnection {
       InputStream is = null;
 
       if (_statusCode != 200) {
-	StringBuffer sb = new StringBuffer();
-	int ch;
-
-	try {
-	  is = httpConn.getInputStream();
-
-	  if (is != null) {
-	    while ((ch = is.read()) >= 0)
-	      sb.append((char) ch);
-
-	    is.close();
-	  }
-
-	  is = httpConn.getErrorStream();
-	  if (is != null) {
-	    while ((ch = is.read()) >= 0)
-	      sb.append((char) ch);
-	  }
-
-	  _statusMessage = sb.toString();
-	} catch (FileNotFoundException e) {
-	  throw new HessianConnectionException("HessianProxy cannot connect to '" + _url, e);
-	} catch (IOException e) {
-	  if (is == null)
-	    throw new HessianConnectionException(_statusCode + ": " + e, e);
-	  else
-	    throw new HessianConnectionException(_statusCode + ": " + sb, e);
-	}
-
-	if (is != null)
-	  is.close();
-
-	throw new HessianConnectionException(_statusCode + ": " + sb.toString());
+        StringBuffer sb = new StringBuffer();
+        int ch;
+
+        try {
+          is = httpConn.getInputStream();
+
+          if (is != null) {
+            while ((ch = is.read()) >= 0)
+              sb.append((char) ch);
+
+            is.close();
+          }
+
+          is = httpConn.getErrorStream();
+          if (is != null) {
+            while ((ch = is.read()) >= 0)
+              sb.append((char) ch);
+          }
+
+          _statusMessage = sb.toString();
+        } catch (FileNotFoundException e) {
+          throw new HessianConnectionException("HessianProxy cannot connect to '" + _url, e);
+        } catch (IOException e) {
+          if (is == null)
+            throw new HessianConnectionException(_statusCode + ": " + e, e);
+          else
+            throw new HessianConnectionException(_statusCode + ": " + sb, e);
+        }
+
+        if (is != null)
+          is.close();
+
+        throw new HessianConnectionException(_statusCode + ": " + sb.toString());
       }
     }
   }
@@ -176,24 +179,36 @@ public class HessianURLConnection extends AbstractHessianConnection {
   /**
    * Returns the InputStream to the result
    */
+  @Override
   public InputStream getInputStream()
     throws IOException
   {
-    return _conn.getInputStream();
+    return _conn.getInputStream(); 
+  }
+  
+  @Override
+  public String getContentEncoding()
+  {
+    return _conn.getContentEncoding();
   }
 
   /**
    * Close/free the connection
    */
+  @Override
   public void close()
   {
+    _inputStream = null;
   }
 
   /**
    * Disconnect the connection
    */
+  @Override
   public void destroy()
   {
+    close();
+    
     URLConnection conn = _conn;
     _conn = null;
     
diff --git a/com/caucho/hessian/client/HessianURLConnectionFactory.java b/com/caucho/hessian/client/HessianURLConnectionFactory.java
index f41b7c0..7030a4a 100644
--- a/com/caucho/hessian/client/HessianURLConnectionFactory.java
+++ b/com/caucho/hessian/client/HessianURLConnectionFactory.java
@@ -107,9 +107,9 @@ public class HessianURLConnectionFactory implements HessianConnectionFactory {
     // Used chunked mode when available, i.e. JDK 1.5.
     if (_proxyFactory.isChunkedPost() && conn instanceof HttpURLConnection) {
       try {
-	HttpURLConnection httpConn = (HttpURLConnection) conn;
+        HttpURLConnection httpConn = (HttpURLConnection) conn;
 
-	httpConn.setChunkedStreamingMode(8 * 1024);
+        httpConn.setChunkedStreamingMode(8 * 1024);
       } catch (Throwable e) {
       }
     }
diff --git a/com/caucho/hessian/io/AbstractDeserializer.java b/com/caucho/hessian/io/AbstractDeserializer.java
index 83312fa..ba8b777 100644
--- a/com/caucho/hessian/io/AbstractDeserializer.java
+++ b/com/caucho/hessian/io/AbstractDeserializer.java
@@ -128,6 +128,7 @@ public class AbstractDeserializer implements Deserializer {
     return name;
   }
   
+  @Override
   public Object readObject(AbstractHessianInput in,
                            String []fieldNames)
     throws IOException
diff --git a/com/caucho/hessian/io/AbstractHessianInput.java b/com/caucho/hessian/io/AbstractHessianInput.java
index 13610d0..3d9c15b 100644
--- a/com/caucho/hessian/io/AbstractHessianInput.java
+++ b/com/caucho/hessian/io/AbstractHessianInput.java
@@ -356,7 +356,7 @@ abstract public class AbstractHessianInput {
       int len;
 
       while ((len = is.read(_buffer, 0, _buffer.length)) > 0) {
-	os.write(_buffer, 0, len);
+        os.write(_buffer, 0, len);
       }
 
       return true;
@@ -365,7 +365,7 @@ abstract public class AbstractHessianInput {
     }
   }
     
-	   
+
 
   /**
    * Reads a byte array.
diff --git a/com/caucho/hessian/io/AbstractHessianOutput.java b/com/caucho/hessian/io/AbstractHessianOutput.java
index d7ca76b..29098c2 100644
--- a/com/caucho/hessian/io/AbstractHessianOutput.java
+++ b/com/caucho/hessian/io/AbstractHessianOutput.java
@@ -118,6 +118,11 @@ abstract public class AbstractHessianOutput {
   public void init(OutputStream os)
   {
   }
+  
+  public boolean setUnshared(boolean isUnshared)
+  {
+    throw new UnsupportedOperationException(getClass().getSimpleName());
+  }
 
   /**
    * Writes a complete method call.
@@ -360,8 +365,8 @@ abstract public class AbstractHessianOutput {
    * @param value the string value to write.
    */
   abstract public void writeByteBufferPart(byte []buffer,
-					   int offset,
-					   int length)
+                                           int offset,
+                                           int length)
     throws IOException;
   
   /**
@@ -374,8 +379,8 @@ abstract public class AbstractHessianOutput {
    * @param value the string value to write.
    */
   abstract public void writeByteBufferEnd(byte []buffer,
-					  int offset,
-					  int length)
+                                          int offset,
+                                          int length)
     throws IOException;
 
   /**
@@ -394,14 +399,14 @@ abstract public class AbstractHessianOutput {
     int len;
     while ((len = is.read(buffer, 0, buffer.length)) > 0) {
       if (len < buffer.length) {
-	int len2 = is.read(buffer, len, buffer.length - len);
+        int len2 = is.read(buffer, len, buffer.length - len);
 
-	if (len2 < 0) {
-	  writeByteBufferEnd(buffer, 0, len);
-	  return;
-	}
+        if (len2 < 0) {
+          writeByteBufferEnd(buffer, 0, len);
+          return;
+        }
 
-	len += len2;
+        len += len2;
       }
 
       writeByteBufferPart(buffer, 0, len);
diff --git a/com/caucho/hessian/io/AbstractSerializer.java b/com/caucho/hessian/io/AbstractSerializer.java
index 306f005..8321463 100644
--- a/com/caucho/hessian/io/AbstractSerializer.java
+++ b/com/caucho/hessian/io/AbstractSerializer.java
@@ -74,13 +74,13 @@ abstract public class AbstractSerializer implements Serializer {
       Object replace = writeReplace(obj);
       
       if (replace != null) {
-	// out.removeRef(obj);
+        // out.removeRef(obj);
 
-	out.writeObject(replace);
+        out.writeObject(replace);
 
-	out.replaceRef(replace, obj);
+        out.replaceRef(replace, obj);
 
-	return;
+        return;
       }
     } catch (RuntimeException e) {
       throw e;
@@ -98,9 +98,9 @@ abstract public class AbstractSerializer implements Serializer {
     }
     else {
       if (ref == -1) {
-	writeDefinition20(cl, out);
-	
-	out.writeObjectBegin(cl.getName());
+        writeDefinition20(cl, out);
+
+        out.writeObjectBegin(cl.getName());
       }
 
       writeInstance(obj, out);
@@ -118,7 +118,7 @@ abstract public class AbstractSerializer implements Serializer {
   }
 
   protected void writeObject10(Object obj,
-			    AbstractHessianOutput out)
+                            AbstractHessianOutput out)
     throws IOException
   {
     throw new UnsupportedOperationException(getClass().getName());
@@ -132,7 +132,7 @@ abstract public class AbstractSerializer implements Serializer {
   }
 
   protected void writeInstance(Object obj,
-			    AbstractHessianOutput out)
+                            AbstractHessianOutput out)
     throws IOException
   {
     throw new UnsupportedOperationException(getClass().getName());
diff --git a/com/caucho/hessian/io/AbstractStreamDeserializer.java b/com/caucho/hessian/io/AbstractStreamDeserializer.java
index 7beeb9b..489afde 100644
--- a/com/caucho/hessian/io/AbstractStreamDeserializer.java
+++ b/com/caucho/hessian/io/AbstractStreamDeserializer.java
@@ -54,11 +54,12 @@ import java.io.IOException;
  * Deserializing a byte stream
  */
 abstract public class AbstractStreamDeserializer extends AbstractDeserializer {
-  abstract public Class getType();
+  abstract public Class<?> getType();
   
   /**
    * Reads the Hessian 1.0 style map.
    */
+  @Override
   public Object readMap(AbstractHessianInput in)
     throws IOException
   {
@@ -70,7 +71,7 @@ abstract public class AbstractStreamDeserializer extends AbstractDeserializer {
       if (key.equals("value"))
         value = readStreamValue(in);
       else
-	in.readObject();
+        in.readObject();
     }
 
     in.readMapEnd();
@@ -78,6 +79,7 @@ abstract public class AbstractStreamDeserializer extends AbstractDeserializer {
     return value;
   }
   
+  @Override
   public Object readObject(AbstractHessianInput in, Object []fields)
     throws IOException
   {
@@ -86,10 +88,13 @@ abstract public class AbstractStreamDeserializer extends AbstractDeserializer {
     Object value = null;
 
     for (int i = 0; i < fieldNames.length; i++) {
-      if ("value".equals(fieldNames[i]))
+      if ("value".equals(fieldNames[i])) {
         value = readStreamValue(in);
-      else
-	in.readObject();
+        in.addRef(value);
+      }
+      else {
+        in.readObject();
+      }
     }
 
     return value;
diff --git a/com/caucho/hessian/io/AbstractStreamSerializer.java b/com/caucho/hessian/io/AbstractStreamSerializer.java
index 8bd9293..b8dc89f 100644
--- a/com/caucho/hessian/io/AbstractStreamSerializer.java
+++ b/com/caucho/hessian/io/AbstractStreamSerializer.java
@@ -48,15 +48,9 @@
 
 package com.caucho.hessian.io;
 
-import java.io.InputStream;
 import java.io.IOException;
-import java.io.Serializable;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
+import java.io.InputStream;
 import java.util.logging.Level;
-import java.util.logging.Logger;
 
 /**
  * Serializing an object containing a byte stream.
@@ -66,6 +60,7 @@ abstract public class AbstractStreamSerializer extends AbstractSerializer
   /**
    * Writes the object to the output stream.
    */
+  @Override
   public void writeObject(Object obj, AbstractHessianOutput out)
     throws IOException
   {
@@ -78,33 +73,50 @@ abstract public class AbstractStreamSerializer extends AbstractSerializer
     if (ref < -1) {
       out.writeString("value");
 
-      InputStream is = getInputStream(obj);
+      InputStream is = null;
+
       try {
-	out.writeByteStream(is);
-      } finally {
-	is.close();
+        is = getInputStream(obj);
+      } catch (Exception e) {
+        log.log(Level.WARNING, e.toString(), e);
+      }
+      
+      if (is != null) {
+        try {
+          out.writeByteStream(is);
+        } finally {
+          is.close();
+        }
+      } else {
+        out.writeNull();
       }
       
       out.writeMapEnd();
     }
     else {
       if (ref == -1) {
-	out.writeClassFieldLength(1);
-	out.writeString("value");
+        out.writeClassFieldLength(1);
+        out.writeString("value");
 
-	out.writeObjectBegin(getClassName(obj));
+        out.writeObjectBegin(getClassName(obj));
       }
 
-      InputStream is = getInputStream(obj);
+      InputStream is = null;
+
+      try {
+        is = getInputStream(obj);
+      } catch (Exception e) {
+        log.log(Level.WARNING, e.toString(), e);
+      }
 
       try {
-	if (is != null)
-	  out.writeByteStream(is);
-	else
-	  out.writeNull();
+        if (is != null)
+          out.writeByteStream(is);
+        else
+          out.writeNull();
       } finally {
-	if (is != null)
-	  is.close();
+        if (is != null)
+          is.close();
       }
     }
   }
diff --git a/com/caucho/hessian/io/AbstractStringValueDeserializer.java b/com/caucho/hessian/io/AbstractStringValueDeserializer.java
index 9603971..56e34e3 100644
--- a/com/caucho/hessian/io/AbstractStringValueDeserializer.java
+++ b/com/caucho/hessian/io/AbstractStringValueDeserializer.java
@@ -72,7 +72,7 @@ abstract public class AbstractStringValueDeserializer
       if (key.equals("value"))
         value = in.readString();
       else
-	in.readObject();
+        in.readObject();
     }
 
     in.readMapEnd();
@@ -96,7 +96,7 @@ abstract public class AbstractStringValueDeserializer
       if ("value".equals(fieldNames[i]))
         value = in.readString();
       else
-	in.readObject();
+        in.readObject();
     }
 
     Object object = create(value);
diff --git a/com/caucho/hessian/io/AnnotationDeserializer.java b/com/caucho/hessian/io/AnnotationDeserializer.java
index c618ffa..e0e7204 100644
--- a/com/caucho/hessian/io/AnnotationDeserializer.java
+++ b/com/caucho/hessian/io/AnnotationDeserializer.java
@@ -90,17 +90,17 @@ public class AnnotationDeserializer extends AbstractMapDeserializer {
 
       while (! in.isEnd()) {
         String key = in.readString();
-	Object value = in.readObject();
+        Object value = in.readObject();
 
-	valueMap.put(key, value);
+        valueMap.put(key, value);
       }
       
       in.readMapEnd();
 
       return Proxy.newProxyInstance(_annType.getClassLoader(),
-			       new Class[] { _annType },
-			       new AnnotationInvocationHandler(_annType, valueMap));
-			       
+                                    new Class[] { _annType },
+                                    new AnnotationInvocationHandler(_annType, valueMap));
+      
     } catch (IOException e) {
       throw e;
     } catch (Exception e) {
@@ -109,26 +109,26 @@ public class AnnotationDeserializer extends AbstractMapDeserializer {
   }
     
   public Object readObject(AbstractHessianInput in,
-			   Object []fields)
+                           Object []fields)
     throws IOException
   {
     String []fieldNames = (String []) fields;
     
     try {
-      int ref = in.addRef(null);
+      in.addRef(null);
 
       HashMap<String,Object> valueMap = new HashMap<String,Object>(8);
       
       for (int i = 0; i < fieldNames.length; i++) {
         String name = fieldNames[i];
 
-	valueMap.put(name, in.readObject());
+        valueMap.put(name, in.readObject());
       }
 
       return Proxy.newProxyInstance(_annType.getClassLoader(),
-			       new Class[] { _annType },
-			       new AnnotationInvocationHandler(_annType, valueMap));
-			       
+                                    new Class[] { _annType },
+                                    new AnnotationInvocationHandler(_annType, valueMap));
+      
     } catch (IOException e) {
       throw e;
     } catch (Exception e) {
diff --git a/com/caucho/hessian/io/AnnotationInvocationHandler.java b/com/caucho/hessian/io/AnnotationInvocationHandler.java
index 3a6ed86..e1b227e 100644
--- a/com/caucho/hessian/io/AnnotationInvocationHandler.java
+++ b/com/caucho/hessian/io/AnnotationInvocationHandler.java
@@ -49,6 +49,7 @@
 package com.caucho.hessian.io;
 
 import java.io.IOException;
+import java.lang.annotation.Annotation;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.util.HashMap;
@@ -66,27 +67,52 @@ public class AnnotationInvocationHandler implements InvocationHandler {
   private HashMap<String,Object> _valueMap;
 
   public AnnotationInvocationHandler(Class annType,
-				     HashMap<String,Object> valueMap)
+                                     HashMap<String,Object> valueMap)
   {
     _annType = annType;
     _valueMap = valueMap;
   }
 
+  @Override
   public Object invoke(Object proxy, Method method, Object []args)
     throws Throwable
   {
     String name = method.getName();
 
-    if (args != null && args.length != 0)
-      return null;
-
-    if (name.equals("annotationType"))
+    boolean zeroArgs = args == null || args.length == 0;
+    
+    if (name.equals("annotationType") && zeroArgs)
       return _annType;
-    else if (name.equals("toString"))
+    else if (name.equals("toString") && zeroArgs)
       return toString();
+    else if (name.equals("hashCode") && zeroArgs)
+      return doHashCode();
+    else if (name.equals("equals") && ! zeroArgs && args.length == 1)
+      return doEquals(args[0]);
+    else if (! zeroArgs)
+      return null;
+
 
     return _valueMap.get(method.getName());
   }
+  
+  public int doHashCode()
+  {
+    return 13;
+  }
+  
+  public boolean doEquals(Object value)
+  {
+    if (! (value instanceof Annotation))
+      return false;
+    
+    Annotation ann = (Annotation) value;
+    
+    if (! _annType.equals(ann.annotationType()))
+      return false;
+    
+    return true;
+  }
 
   public String toString()
   {
@@ -99,16 +125,16 @@ public class AnnotationInvocationHandler implements InvocationHandler {
     boolean isFirst = true;
     for (Map.Entry entry : _valueMap.entrySet()) {
       if (! isFirst)
-	sb.append(", ");
+        sb.append(", ");
       isFirst = false;
 
       sb.append(entry.getKey());
       sb.append("=");
 
       if (entry.getValue() instanceof String)
-	sb.append('"').append(entry.getValue()).append('"');
+        sb.append('"').append(entry.getValue()).append('"');
       else
-	sb.append(entry.getValue());
+        sb.append(entry.getValue());
     }
     sb.append("]");
 
diff --git a/com/caucho/hessian/io/AnnotationSerializer.java b/com/caucho/hessian/io/AnnotationSerializer.java
index 4278c5e..0078502 100644
--- a/com/caucho/hessian/io/AnnotationSerializer.java
+++ b/com/caucho/hessian/io/AnnotationSerializer.java
@@ -98,8 +98,8 @@ public class AnnotationSerializer extends AbstractSerializer
     }
     else {
       if (ref == -1) {
-	writeDefinition20(out);
-	out.writeObjectBegin(_annType.getName());
+        writeDefinition20(out);
+        out.writeObjectBegin(_annType.getName());
       }
 
       writeInstance(obj, out);
@@ -113,7 +113,7 @@ public class AnnotationSerializer extends AbstractSerializer
       Method method = _methods[i];
 
       out.writeString(method.getName());
-	
+
       _methodSerializers[i].serialize(out, obj, method);
     }
       
@@ -124,7 +124,7 @@ public class AnnotationSerializer extends AbstractSerializer
     throws IOException
   {
     out.writeClassFieldLength(_methods.length);
-	
+
     for (int i = 0; i < _methods.length; i++) {
       Method method = _methods[i];
       
@@ -147,29 +147,29 @@ public class AnnotationSerializer extends AbstractSerializer
   {
     synchronized (this) {
       if (_annType != null)
-	return;
+        return;
 
       _annType = cl;
       
       ArrayList methods = new ArrayList();
     
       for (Method method : _annType.getDeclaredMethods()) {
-	if (method.getName().equals("hashCode")
-	    || method.getName().equals("toString")
-	    || method.getName().equals("annotationType")) {
-	  continue;
-	}
+        if (method.getName().equals("hashCode")
+            || method.getName().equals("toString")
+            || method.getName().equals("annotationType")) {
+          continue;
+        }
 
-	if (method.getParameterTypes().length != 0)
-	  continue;
+        if (method.getParameterTypes().length != 0)
+          continue;
 
-	methods.add(method);
+        methods.add(method);
 
-	method.setAccessible(true);
+        method.setAccessible(true);
       }
 
       if (_annType == null)
-	throw new IllegalStateException(cl.getName() + " is invalid because it does not have a valid annotationType()");
+        throw new IllegalStateException(cl.getName() + " is invalid because it does not have a valid annotationType()");
 
       _methods = new Method[methods.size()];
       methods.toArray(_methods);
@@ -177,7 +177,7 @@ public class AnnotationSerializer extends AbstractSerializer
       _methodSerializers = new MethodSerializer[_methods.length];
 
       for (int i = 0; i < _methods.length; i++) {
-	_methodSerializers[i] = getMethodSerializer(_methods[i].getReturnType());
+        _methodSerializers[i] = getMethodSerializer(_methods[i].getReturnType());
       }
     }
   }
@@ -194,13 +194,13 @@ public class AnnotationSerializer extends AbstractSerializer
 
     if (ifaces != null) {
       for (Class iface : ifaces) {
-	if (iface.equals(Annotation.class))
-	  return cl;
-	
-	Class annType = getAnnotationType(iface);
+        if (iface.equals(Annotation.class))
+          return cl;
 
-	if (annType != null)
-	  return annType;
+        Class annType = getAnnotationType(iface);
+
+        if (annType != null)
+          return annType;
       }
     }
 
@@ -241,7 +241,7 @@ public class AnnotationSerializer extends AbstractSerializer
   static HessianException error(Method method, Throwable cause)
   {
     String msg = (method.getDeclaringClass().getSimpleName()
-		  + "." + method.getName() + "(): " + cause);
+                  + "." + method.getName() + "(): " + cause);
 
     throw new HessianMethodSerializationException(msg, cause);
   }
@@ -253,19 +253,19 @@ public class AnnotationSerializer extends AbstractSerializer
       throws IOException
     {
       Object value = null;
-	
+
       try {
-	value = method.invoke(obj);
+        value = method.invoke(obj);
       } catch (InvocationTargetException e) {
-	throw error(method, e.getCause());
+        throw error(method, e.getCause());
       } catch (IllegalAccessException e) {
-	log.log(Level.FINE, e.toString(), e);
+        log.log(Level.FINE, e.toString(), e);
       }
 
       try {
-	out.writeObject(value);
+        out.writeObject(value);
       } catch (Exception e) {
-	throw error(method, e);
+        throw error(method, e);
       }
     }
   }
@@ -277,13 +277,13 @@ public class AnnotationSerializer extends AbstractSerializer
       throws IOException
     {
       boolean value = false;
-	
+
       try {
-	value = (Boolean) method.invoke(obj);
+        value = (Boolean) method.invoke(obj);
       } catch (InvocationTargetException e) {
-	throw error(method, e.getCause());
+        throw error(method, e.getCause());
       } catch (IllegalAccessException e) {
-	log.log(Level.FINE, e.toString(), e);
+        log.log(Level.FINE, e.toString(), e);
       }
 
       out.writeBoolean(value);
@@ -297,13 +297,13 @@ public class AnnotationSerializer extends AbstractSerializer
       throws IOException
     {
       int value = 0;
-	
+
       try {
-	value = (Integer) method.invoke(obj);
+        value = (Integer) method.invoke(obj);
       } catch (InvocationTargetException e) {
-	throw error(method, e.getCause());
+        throw error(method, e.getCause());
       } catch (IllegalAccessException e) {
-	log.log(Level.FINE, e.toString(), e);
+        log.log(Level.FINE, e.toString(), e);
       }
 
       out.writeInt(value);
@@ -317,13 +317,13 @@ public class AnnotationSerializer extends AbstractSerializer
       throws IOException
     {
       long value = 0;
-	
+
       try {
-	value = (Long) method.invoke(obj);
+        value = (Long) method.invoke(obj);
       } catch (InvocationTargetException e) {
-	throw error(method, e.getCause());
+        throw error(method, e.getCause());
       } catch (IllegalAccessException e) {
-	log.log(Level.FINE, e.toString(), e);
+        log.log(Level.FINE, e.toString(), e);
       }
 
       out.writeLong(value);
@@ -337,13 +337,13 @@ public class AnnotationSerializer extends AbstractSerializer
       throws IOException
     {
       double value = 0;
-	
+
       try {
-	value = (Double) method.invoke(obj);
+        value = (Double) method.invoke(obj);
       } catch (InvocationTargetException e) {
-	throw error(method, e.getCause());
+        throw error(method, e.getCause());
       } catch (IllegalAccessException e) {
-	log.log(Level.FINE, e.toString(), e);
+        log.log(Level.FINE, e.toString(), e);
       }
 
       out.writeDouble(value);
@@ -357,13 +357,13 @@ public class AnnotationSerializer extends AbstractSerializer
       throws IOException
     {
       String value = null;
-	
+
       try {
-	value = (String) method.invoke(obj);
+        value = (String) method.invoke(obj);
       } catch (InvocationTargetException e) {
-	throw error(method, e.getCause());
+        throw error(method, e.getCause());
       } catch (IllegalAccessException e) {
-	log.log(Level.FINE, e.toString(), e);
+        log.log(Level.FINE, e.toString(), e);
       }
 
       out.writeString(value);
@@ -381,7 +381,7 @@ public class AnnotationSerializer extends AbstractSerializer
       try {
         value = (java.util.Date) method.invoke(obj);
       } catch (InvocationTargetException e) {
-	throw error(method, e.getCause());
+        throw error(method, e.getCause());
       } catch (IllegalAccessException e) {
         log.log(Level.FINE, e.toString(), e);
       }
diff --git a/com/caucho/hessian/io/ArrayDeserializer.java b/com/caucho/hessian/io/ArrayDeserializer.java
index ed9b53f..9e1c60b 100644
--- a/com/caucho/hessian/io/ArrayDeserializer.java
+++ b/com/caucho/hessian/io/ArrayDeserializer.java
@@ -139,11 +139,11 @@ public class ArrayDeserializer extends AbstractListDeserializer {
       
     if (_componentType != null) {
       for (int i = 0; i < data.length; i++)
-	data[i] = in.readObject(_componentType);
+        data[i] = in.readObject(_componentType);
     }
     else {
       for (int i = 0; i < data.length; i++)
-	data[i] = in.readObject();
+        data[i] = in.readObject();
     }
 
     return data;
diff --git a/com/caucho/hessian/io/ArraySerializer.java b/com/caucho/hessian/io/ArraySerializer.java
index 85d033e..e7221a3 100644
--- a/com/caucho/hessian/io/ArraySerializer.java
+++ b/com/caucho/hessian/io/ArraySerializer.java
@@ -63,7 +63,7 @@ public class ArraySerializer extends AbstractSerializer {
     Object []array = (Object []) obj;
 
     boolean hasEnd = out.writeListBegin(array.length,
-					getArrayType(obj.getClass()));
+                                        getArrayType(obj.getClass()));
 
     for (int i = 0; i < array.length; i++)
       out.writeObject(array[i]);
diff --git a/com/caucho/hessian/io/BasicDeserializer.java b/com/caucho/hessian/io/BasicDeserializer.java
index 75eb93c..f701d9a 100644
--- a/com/caucho/hessian/io/BasicDeserializer.java
+++ b/com/caucho/hessian/io/BasicDeserializer.java
@@ -185,20 +185,20 @@ public class BasicDeserializer extends AbstractDeserializer {
       
     case CHARACTER:
       {
-	String s = in.readString();
-	if (s == null || s.equals(""))
-	  return Character.valueOf((char) 0);
-	else
-	  return Character.valueOf(s.charAt(0));
+        String s = in.readString();
+        if (s == null || s.equals(""))
+          return Character.valueOf((char) 0);
+        else
+          return Character.valueOf(s.charAt(0));
       }
       
     case CHARACTER_OBJECT:
       {
-	String s = in.readString();
-	if (s == null || s.equals(""))
-	  return null;
-	else
-	  return Character.valueOf(s.charAt(0));
+        String s = in.readString();
+        if (s == null || s.equals(""))
+          return null;
+        else
+          return Character.valueOf(s.charAt(0));
       }
       
     case DATE:
@@ -236,22 +236,22 @@ public class BasicDeserializer extends AbstractDeserializer {
 
       switch (code) {
       case 'N':
-	return null;
+        return null;
 
       case 0x10: case 0x11: case 0x12: case 0x13:
       case 0x14: case 0x15: case 0x16: case 0x17:
       case 0x18: case 0x19: case 0x1a: case 0x1b:
       case 0x1c: case 0x1d: case 0x1e: case 0x1f:
-	int length = code - 0x10;
-	in.readInt();
+        int length = code - 0x10;
+        in.readInt();
 
-	return readLengthList(in, length);
+        return readLengthList(in, length);
 
       default:
-	String type = in.readType();
-	length = in.readLength();
+        String type = in.readType();
+        length = in.readLength();
 
-	return readList(in, length);
+        return readList(in, length);
       }
     }
 
@@ -272,7 +272,7 @@ public class BasicDeserializer extends AbstractDeserializer {
 
         for (int i = 0; i < data.length; i++)
           data[i] = in.readBoolean();
-	
+
         in.readEnd();
 
         return data;
@@ -282,7 +282,7 @@ public class BasicDeserializer extends AbstractDeserializer {
 
         while (! in.isEnd())
           list.add(Boolean.valueOf(in.readBoolean()));
-	
+
         in.readEnd();
 
         boolean []data = new boolean[list.size()];
@@ -304,7 +304,7 @@ public class BasicDeserializer extends AbstractDeserializer {
         
         for (int i = 0; i < data.length; i++)
           data[i] = (short) in.readInt();
-	
+
         in.readEnd();
 
         return data;
@@ -337,7 +337,7 @@ public class BasicDeserializer extends AbstractDeserializer {
           data[i] = in.readInt();
 
         in.readEnd();
-	
+
         return data;
       }
       else {
@@ -348,7 +348,7 @@ public class BasicDeserializer extends AbstractDeserializer {
 
 
         in.readEnd();
-	
+
         int []data = new int[list.size()];
         for (int i = 0; i < data.length; i++)
           data[i] = ((Integer) list.get(i)).intValue();
@@ -523,7 +523,7 @@ public class BasicDeserializer extends AbstractDeserializer {
       in.addRef(data);
 
       for (int i = 0; i < data.length; i++)
-	data[i] = in.readBoolean();
+        data[i] = in.readBoolean();
 
       return data;
     }
@@ -534,7 +534,7 @@ public class BasicDeserializer extends AbstractDeserializer {
       in.addRef(data);
         
       for (int i = 0; i < data.length; i++)
-	data[i] = (short) in.readInt();
+        data[i] = (short) in.readInt();
 
       return data;
     }
@@ -545,7 +545,7 @@ public class BasicDeserializer extends AbstractDeserializer {
       in.addRef(data);
         
       for (int i = 0; i < data.length; i++)
-	data[i] = in.readInt();
+        data[i] = in.readInt();
 
       return data;
     }
@@ -556,7 +556,7 @@ public class BasicDeserializer extends AbstractDeserializer {
       in.addRef(data);
         
       for (int i = 0; i < data.length; i++)
-	data[i] = in.readLong();
+        data[i] = in.readLong();
 
       return data;
     }
@@ -566,7 +566,7 @@ public class BasicDeserializer extends AbstractDeserializer {
       in.addRef(data);
 
       for (int i = 0; i < data.length; i++)
-	data[i] = (float) in.readDouble();
+        data[i] = (float) in.readDouble();
 
       return data;
     }
@@ -576,7 +576,7 @@ public class BasicDeserializer extends AbstractDeserializer {
       in.addRef(data);
 
       for (int i = 0; i < data.length; i++)
-	data[i] = in.readDouble();
+        data[i] = in.readDouble();
 
       return data;
     }
@@ -586,7 +586,7 @@ public class BasicDeserializer extends AbstractDeserializer {
       in.addRef(data);
 
       for (int i = 0; i < data.length; i++)
-	data[i] = in.readString();
+        data[i] = in.readString();
 
       return data;
     }
@@ -596,7 +596,7 @@ public class BasicDeserializer extends AbstractDeserializer {
       in.addRef(data);
 
       for (int i = 0; i < data.length; i++)
-	data[i] = in.readObject();
+        data[i] = in.readObject();
 
       return data;
     }
diff --git a/com/caucho/hessian/io/BasicSerializer.java b/com/caucho/hessian/io/BasicSerializer.java
index 1298e37..fbaf4b9 100644
--- a/com/caucho/hessian/io/BasicSerializer.java
+++ b/com/caucho/hessian/io/BasicSerializer.java
@@ -68,7 +68,8 @@ public class BasicSerializer extends AbstractSerializer
   public static final int CHARACTER = DOUBLE + 1;
   public static final int CHARACTER_OBJECT = CHARACTER + 1;
   public static final int STRING = CHARACTER_OBJECT + 1;
-  public static final int DATE = STRING + 1;
+  public static final int STRING_BUILDER = STRING + 1;
+  public static final int DATE = STRING_BUILDER + 1;
   public static final int NUMBER = DATE + 1;
   public static final int OBJECT = NUMBER + 1;
   
@@ -149,6 +150,10 @@ public class BasicSerializer extends AbstractSerializer
       out.writeString((String) obj);
       break;
       
+    case STRING_BUILDER:
+      out.writeString(((StringBuilder) obj).toString());
+      break;
+      
     case DATE:
       out.writeUTCDate(((Date) obj).getTime());
       break;
@@ -164,7 +169,7 @@ public class BasicSerializer extends AbstractSerializer
         out.writeBoolean(data[i]);
 
       if (hasEnd)
-	out.writeListEnd();
+        out.writeListEnd();
       
       break;
     }
@@ -188,7 +193,7 @@ public class BasicSerializer extends AbstractSerializer
         out.writeInt(data[i]);
 
       if (hasEnd)
-	out.writeListEnd();
+        out.writeListEnd();
       break;
     }
 
@@ -205,7 +210,7 @@ public class BasicSerializer extends AbstractSerializer
         out.writeInt(data[i]);
 
       if (hasEnd)
-	out.writeListEnd();
+        out.writeListEnd();
       
       break;
     }
@@ -223,7 +228,7 @@ public class BasicSerializer extends AbstractSerializer
         out.writeLong(data[i]);
 
       if (hasEnd)
-	out.writeListEnd();
+        out.writeListEnd();
       break;
     }
 
@@ -240,7 +245,7 @@ public class BasicSerializer extends AbstractSerializer
         out.writeDouble(data[i]);
 
       if (hasEnd)
-	out.writeListEnd();
+        out.writeListEnd();
       break;
     }
 
@@ -256,7 +261,7 @@ public class BasicSerializer extends AbstractSerializer
         out.writeDouble(data[i]);
 
       if (hasEnd)
-	out.writeListEnd();
+        out.writeListEnd();
       break;
     }
 
@@ -274,7 +279,7 @@ public class BasicSerializer extends AbstractSerializer
       }
 
       if (hasEnd)
-	out.writeListEnd();
+        out.writeListEnd();
       break;
     }
 
@@ -299,7 +304,7 @@ public class BasicSerializer extends AbstractSerializer
       }
 
       if (hasEnd)
-	out.writeListEnd();
+        out.writeListEnd();
       break;
     }
     
diff --git a/com/caucho/hessian/io/BeanDeserializer.java b/com/caucho/hessian/io/BeanDeserializer.java
index a2fb242..f4fb548 100644
--- a/com/caucho/hessian/io/BeanDeserializer.java
+++ b/com/caucho/hessian/io/BeanDeserializer.java
@@ -53,6 +53,7 @@ import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.HashMap;
+import java.util.Locale;
 
 /**
  * Serializing an object for known object types.
@@ -123,7 +124,7 @@ public class BeanDeserializer extends AbstractMapDeserializer {
 
         if (method != null) {
           Object value = in.readObject(method.getParameterTypes()[0]);
-	  
+
           method.invoke(obj, new Object[] {value });
         }
         else {
@@ -136,7 +137,7 @@ public class BeanDeserializer extends AbstractMapDeserializer {
       Object resolve = resolve(obj);
 
       if (obj != resolve)
-	in.setRef(ref, resolve);
+        in.setRef(ref, resolve);
 
       return resolve;
     } catch (IOException e) {
@@ -173,11 +174,11 @@ public class BeanDeserializer extends AbstractMapDeserializer {
       Method []methods = cl.getDeclaredMethods();
       
       for (int i = 0; i < methods.length; i++) {
-	Method method = methods[i];
+        Method method = methods[i];
 
-	if (method.getName().equals("readResolve") &&
-	    method.getParameterTypes().length == 0)
-	  return method;
+        if (method.getName().equals("readResolve") &&
+            method.getParameterTypes().length == 0)
+          return method;
       }
     }
 
@@ -195,46 +196,46 @@ public class BeanDeserializer extends AbstractMapDeserializer {
       Method []methods = cl.getDeclaredMethods();
       
       for (int i = 0; i < methods.length; i++) {
-	Method method = methods[i];
+        Method method = methods[i];
 
-	if (Modifier.isStatic(method.getModifiers()))
-	  continue;
+        if (Modifier.isStatic(method.getModifiers()))
+          continue;
 
-	String name = method.getName();
+        String name = method.getName();
 
-	if (! name.startsWith("set"))
-	  continue;
+        if (! name.startsWith("set"))
+          continue;
 
-	Class []paramTypes = method.getParameterTypes();
-	if (paramTypes.length != 1)
-	  continue;
+        Class []paramTypes = method.getParameterTypes();
+        if (paramTypes.length != 1)
+          continue;
 
-	if (! method.getReturnType().equals(void.class))
-	  continue;
+        if (! method.getReturnType().equals(void.class))
+          continue;
 
-	if (findGetter(methods, name, paramTypes[0]) == null)
-	  continue;
+        if (findGetter(methods, name, paramTypes[0]) == null)
+          continue;
 
-	// XXX: could parameterize the handler to only deal with public
-	try {
-	  method.setAccessible(true);
-	} catch (Throwable e) {
-	  e.printStackTrace();
-	}
+        // XXX: could parameterize the handler to only deal with public
+        try {
+          method.setAccessible(true);
+        } catch (Throwable e) {
+          e.printStackTrace();
+        }
     
-	name = name.substring(3);
+        name = name.substring(3);
 
-	int j = 0;
-	for (; j < name.length() && Character.isUpperCase(name.charAt(j)); j++) {
-	}
+        int j = 0;
+        for (; j < name.length() && Character.isUpperCase(name.charAt(j)); j++) {
+        }
 
-	if (j == 1)
-	  name = name.substring(0, j).toLowerCase() + name.substring(j);
-	else if (j > 1)
-	  name = name.substring(0, j - 1).toLowerCase() + name.substring(j - 1);
+        if (j == 1)
+          name = name.substring(0, j).toLowerCase(Locale.ENGLISH) + name.substring(j);
+        else if (j > 1)
+          name = name.substring(0, j - 1).toLowerCase(Locale.ENGLISH) + name.substring(j - 1);
 
 
-	methodMap.put(name, method);
+        methodMap.put(name, method);
       }
     }
 
@@ -252,15 +253,15 @@ public class BeanDeserializer extends AbstractMapDeserializer {
       Method method = methods[i];
 
       if (! method.getName().equals(getterName))
-	continue;
+        continue;
       
       if (! method.getReturnType().equals(arg))
-	continue;
+        continue;
 
       Class []params = method.getParameterTypes();
 
       if (params.length == 0)
-	return method;
+        return method;
     }
 
     return null;
diff --git a/com/caucho/hessian/io/BeanSerializer.java b/com/caucho/hessian/io/BeanSerializer.java
index a8db0e5..759f183 100644
--- a/com/caucho/hessian/io/BeanSerializer.java
+++ b/com/caucho/hessian/io/BeanSerializer.java
@@ -54,6 +54,7 @@ import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.Locale;
 import java.util.logging.*;
 
 /**
@@ -81,36 +82,36 @@ public class BeanSerializer extends AbstractSerializer {
       Method []methods = cl.getDeclaredMethods();
       
       for (int i = 0; i < methods.length; i++) {
-	Method method = methods[i];
+        Method method = methods[i];
 
-	if (Modifier.isStatic(method.getModifiers()))
-	  continue;
+        if (Modifier.isStatic(method.getModifiers()))
+          continue;
 
-	if (method.getParameterTypes().length != 0)
-	  continue;
+        if (method.getParameterTypes().length != 0)
+          continue;
 
-	String name = method.getName();
+        String name = method.getName();
 
-	if (! name.startsWith("get"))
-	  continue;
+        if (! name.startsWith("get"))
+          continue;
 
-	Class type = method.getReturnType();
+        Class type = method.getReturnType();
 
-	if (type.equals(void.class))
-	  continue;
+        if (type.equals(void.class))
+          continue;
 
-	if (findSetter(methods, name, type) == null)
-	  continue;
+        if (findSetter(methods, name, type) == null)
+          continue;
 
-	// XXX: could parameterize the handler to only deal with public
-	method.setAccessible(true);
+        // XXX: could parameterize the handler to only deal with public
+        method.setAccessible(true);
 
-	if (type.isPrimitive()
-	    || type.getName().startsWith("java.lang.")
-	    && ! type.equals(Object.class))
-	  primitiveMethods.add(method);
-	else
-	  compoundMethods.add(method);
+        if (type.isPrimitive()
+            || type.getName().startsWith("java.lang.")
+            && ! type.equals(Object.class))
+          primitiveMethods.add(method);
+        else
+          compoundMethods.add(method);
       }
     }
 
@@ -135,9 +136,9 @@ public class BeanSerializer extends AbstractSerializer {
       }
 
       if (j == 1)
-	name = name.substring(0, j).toLowerCase() + name.substring(j);
+        name = name.substring(0, j).toLowerCase(Locale.ENGLISH) + name.substring(j);
       else if (j > 1)
-	name = name.substring(0, j - 1).toLowerCase() + name.substring(j - 1);
+        name = name.substring(0, j - 1).toLowerCase(Locale.ENGLISH) + name.substring(j - 1);
 
       _names[i] = name;
     }
@@ -155,10 +156,10 @@ public class BeanSerializer extends AbstractSerializer {
       Method writeReplace = getWriteReplace(serializerClass, cl);
 
       if (writeReplace != null) {
-	_writeReplaceFactory = serializerObject;
-	_writeReplace = writeReplace;
+        _writeReplaceFactory = serializerObject;
+        _writeReplace = writeReplace;
 
-	return;
+        return;
       }
     } catch (ClassNotFoundException e) {
     } catch (Exception e) {
@@ -177,11 +178,11 @@ public class BeanSerializer extends AbstractSerializer {
       Method []methods = cl.getDeclaredMethods();
       
       for (int i = 0; i < methods.length; i++) {
-	Method method = methods[i];
+        Method method = methods[i];
 
-	if (method.getName().equals("writeReplace") &&
-	    method.getParameterTypes().length == 0)
-	  return method;
+        if (method.getName().equals("writeReplace") &&
+            method.getParameterTypes().length == 0)
+          return method;
       }
     }
 
@@ -195,10 +196,10 @@ public class BeanSerializer extends AbstractSerializer {
   {
     for (; cl != null; cl = cl.getSuperclass()) {
       for (Method method : cl.getDeclaredMethods()) {
-	if (method.getName().equals("writeReplace")
-	    && method.getParameterTypes().length == 1
-	    && param.equals(method.getParameterTypes()[0]))
-	  return method;
+        if (method.getName().equals("writeReplace")
+            && method.getParameterTypes().length == 1
+            && param.equals(method.getParameterTypes()[0]))
+          return method;
       }
     }
 
@@ -215,20 +216,20 @@ public class BeanSerializer extends AbstractSerializer {
     
     try {
       if (_writeReplace != null) {
-	Object repl;
+        Object repl;
 
-	if (_writeReplaceFactory != null)
-	  repl = _writeReplace.invoke(_writeReplaceFactory, obj);
-	else
-	  repl = _writeReplace.invoke(obj);
+        if (_writeReplaceFactory != null)
+          repl = _writeReplace.invoke(_writeReplaceFactory, obj);
+        else
+          repl = _writeReplace.invoke(obj);
 
-	// out.removeRef(obj);
+        // out.removeRef(obj);
 
-	out.writeObject(repl);
+        out.writeObject(repl);
 
-	out.replaceRef(repl, obj);
+        out.replaceRef(repl, obj);
 
-	return;
+        return;
       }
     } catch (Exception e) {
       log.log(Level.FINER, e.toString(), e);
@@ -240,43 +241,43 @@ public class BeanSerializer extends AbstractSerializer {
       // Hessian 1.1 uses a map
       
       for (int i = 0; i < _methods.length; i++) {
-	Method method = _methods[i];
-	Object value = null;
-
-	try {
-	  value = _methods[i].invoke(obj, (Object []) null);
-	} catch (Exception e) {
-	  log.log(Level.FINE, e.toString(), e);
-	}
-
-	out.writeString(_names[i]);
-	
-	out.writeObject(value);
+        Method method = _methods[i];
+        Object value = null;
+
+        try {
+          value = _methods[i].invoke(obj, (Object []) null);
+        } catch (Exception e) {
+          log.log(Level.FINE, e.toString(), e);
+        }
+
+        out.writeString(_names[i]);
+
+        out.writeObject(value);
       }
       
       out.writeMapEnd();
     }
     else {
       if (ref == -1) {
-	out.writeInt(_names.length);
-	
-	for (int i = 0; i < _names.length; i++)
-	  out.writeString(_names[i]);
-	
-	out.writeObjectBegin(cl.getName());
+        out.writeInt(_names.length);
+
+        for (int i = 0; i < _names.length; i++)
+          out.writeString(_names[i]);
+
+        out.writeObjectBegin(cl.getName());
       }
 
       for (int i = 0; i < _methods.length; i++) {
-	Method method = _methods[i];
-	Object value = null;
-
-	try {
-	  value = _methods[i].invoke(obj, (Object []) null);
-	} catch (Exception e) {
-	  log.log(Level.FINER, e.toString(), e);
-	}
-	
-	out.writeObject(value);
+        Method method = _methods[i];
+        Object value = null;
+
+        try {
+          value = _methods[i].invoke(obj, (Object []) null);
+        } catch (Exception e) {
+          log.log(Level.FINER, e.toString(), e);
+        }
+
+        out.writeObject(value);
       }
     }
   }
@@ -292,15 +293,15 @@ public class BeanSerializer extends AbstractSerializer {
       Method method = methods[i];
 
       if (! method.getName().equals(setterName))
-	continue;
+        continue;
       
       if (! method.getReturnType().equals(void.class))
-	continue;
+        continue;
 
       Class []params = method.getParameterTypes();
 
       if (params.length == 1 && params[0].equals(arg))
-	return method;
+        return method;
     }
 
     return null;
diff --git a/com/caucho/hessian/io/BigDecimalDeserializer.java b/com/caucho/hessian/io/BigDecimalDeserializer.java
index 1291771..81960e1 100644
--- a/com/caucho/hessian/io/BigDecimalDeserializer.java
+++ b/com/caucho/hessian/io/BigDecimalDeserializer.java
@@ -48,17 +48,14 @@
 
 package com.caucho.hessian.io;
 
-import java.io.IOException;
 import java.math.BigDecimal;
 
-import com.caucho.hessian.HessianException;
-
 /**
  * Deserializing a BigDecimal
  */
 public class BigDecimalDeserializer extends AbstractStringValueDeserializer {
   @Override
-  public Class getType()
+  public Class<?> getType()
   {
     return BigDecimal.class;
   }
diff --git a/com/caucho/hessian/io/ThrowableSerializer.java b/com/caucho/hessian/io/ByteArraySerializer.java
similarity index 85%
copy from com/caucho/hessian/io/ThrowableSerializer.java
copy to com/caucho/hessian/io/ByteArraySerializer.java
index c7303bb..4f9f041 100644
--- a/com/caucho/hessian/io/ThrowableSerializer.java
+++ b/com/caucho/hessian/io/ByteArraySerializer.java
@@ -53,19 +53,30 @@ import java.io.IOException;
 /**
  * Serializing an object for known object types.
  */
-public class ThrowableSerializer extends JavaSerializer {
-  public ThrowableSerializer(Class cl, ClassLoader loader)
+public class ByteArraySerializer extends AbstractSerializer
+  implements ObjectSerializer
+{
+  public static final ByteArraySerializer SER = new ByteArraySerializer();
+  
+  private ByteArraySerializer()
+  {
+  }
+
+  @Override
+  public Serializer getObjectSerializer()
   {
-    super(cl);
+    return this;
   }
   
+  @Override
   public void writeObject(Object obj, AbstractHessianOutput out)
     throws IOException
   {
-    Throwable e = (Throwable) obj;
-
-    e.getStackTrace();
-
-    super.writeObject(obj, out);
+    byte []data = (byte []) obj;
+    
+    if (data != null)
+      out.writeBytes(data, 0, data.length);
+    else
+      out.writeNull();
   }
 }
diff --git a/com/caucho/hessian/io/CalendarHandle.java b/com/caucho/hessian/io/CalendarHandle.java
index 9056110..f75c9a7 100644
--- a/com/caucho/hessian/io/CalendarHandle.java
+++ b/com/caucho/hessian/io/CalendarHandle.java
@@ -77,9 +77,9 @@ public class CalendarHandle implements java.io.Serializable, HessianHandle {
       Calendar cal;
       
       if (this.type != null)
-	cal = (Calendar) this.type.newInstance();
+        cal = (Calendar) this.type.newInstance();
       else
-	cal = new GregorianCalendar();
+        cal = new GregorianCalendar();
       
       cal.setTimeInMillis(this.date.getTime());
 
diff --git a/com/caucho/hessian/io/ClassDeserializer.java b/com/caucho/hessian/io/ClassDeserializer.java
index 3a0152a..b997759 100644
--- a/com/caucho/hessian/io/ClassDeserializer.java
+++ b/com/caucho/hessian/io/ClassDeserializer.java
@@ -81,9 +81,9 @@ public class ClassDeserializer extends AbstractMapDeserializer {
       String key = in.readString();
 
       if (key.equals("name"))
-	name = in.readString();
+        name = in.readString();
       else
-	in.readObject();
+        in.readObject();
     }
       
     in.readMapEnd();
@@ -108,7 +108,7 @@ public class ClassDeserializer extends AbstractMapDeserializer {
       if ("name".equals(fieldNames[i]))
         name = in.readString();
       else
-	in.readObject();
+        in.readObject();
     }
 
     Object value = create(name);
diff --git a/com/caucho/hessian/io/ClassSerializer.java b/com/caucho/hessian/io/ClassSerializer.java
index 0a25797..80a63f9 100644
--- a/com/caucho/hessian/io/ClassSerializer.java
+++ b/com/caucho/hessian/io/ClassSerializer.java
@@ -69,18 +69,18 @@ public class ClassSerializer extends AbstractSerializer {
       int ref = out.writeObjectBegin("java.lang.Class");
 
       if (ref < -1) {
-	out.writeString("name");
-	out.writeString(cl.getName());
-	out.writeMapEnd();
+        out.writeString("name");
+        out.writeString(cl.getName());
+        out.writeMapEnd();
       }
       else {
-	if (ref == -1) {
-	  out.writeInt(1);
-	  out.writeString("name");
-	  out.writeObjectBegin("java.lang.Class");
-	}
+        if (ref == -1) {
+          out.writeInt(1);
+          out.writeString("name");
+          out.writeObjectBegin("java.lang.Class");
+        }
 
-	out.writeString(cl.getName());
+        out.writeString(cl.getName());
       }
     }
   }
diff --git a/com/caucho/hessian/io/CollectionSerializer.java b/com/caucho/hessian/io/CollectionSerializer.java
index 5af824c..95114ed 100644
--- a/com/caucho/hessian/io/CollectionSerializer.java
+++ b/com/caucho/hessian/io/CollectionSerializer.java
@@ -89,11 +89,26 @@ public class CollectionSerializer extends AbstractSerializer
     boolean hasEnd;
     
     if (cl.equals(ArrayList.class)
-	|| ! _sendJavaType
-	|| ! Serializable.class.isAssignableFrom(cl))
+        || ! Serializable.class.isAssignableFrom(cl)) {
       hasEnd = out.writeListBegin(list.size(), null);
-    else
+    }
+    else if (! _sendJavaType) {
+      hasEnd = false;
+      
+      // hessian/3a19
+      for (; cl != null; cl = cl.getSuperclass()) {
+        if (cl.getName().startsWith("java.")) {
+          hasEnd = out.writeListBegin(list.size(), cl.getName());
+          break;
+        }
+      }
+      
+      if (cl == null)
+        hasEnd = out.writeListBegin(list.size(), null);
+    }
+    else {
       hasEnd = out.writeListBegin(list.size(), obj.getClass().getName());
+    }
 
     Iterator iter = list.iterator();
     while (iter.hasNext()) {
diff --git a/com/caucho/hessian/io/ContextSerializerFactory.java b/com/caucho/hessian/io/ContextSerializerFactory.java
index 5bc7651..bbc3363 100644
--- a/com/caucho/hessian/io/ContextSerializerFactory.java
+++ b/com/caucho/hessian/io/ContextSerializerFactory.java
@@ -83,7 +83,7 @@ public class ContextSerializerFactory
   private static HashMap _staticClassNameMap;
 
   private ContextSerializerFactory _parent;
-  private ClassLoader _loader;
+  private WeakReference<ClassLoader> _loaderRef;
 
   private final HashSet<String> _serializerFiles = new HashSet<String>();
   private final HashSet<String> _deserializerFiles = new HashSet<String>();
@@ -94,8 +94,8 @@ public class ContextSerializerFactory
   private final ConcurrentHashMap<String,Serializer> _customSerializerMap
     = new ConcurrentHashMap<String,Serializer>();
 
-  private final HashMap<Class,Serializer> _serializerInterfaceMap
-    = new HashMap<Class,Serializer>();
+  private final HashMap<Class<?>,Serializer> _serializerInterfaceMap
+    = new HashMap<Class<?>,Serializer>();
 
   private final HashMap<String,Deserializer> _deserializerClassMap
     = new HashMap<String,Deserializer>();
@@ -106,8 +106,8 @@ public class ContextSerializerFactory
   private final ConcurrentHashMap<String,Deserializer> _customDeserializerMap
     = new ConcurrentHashMap<String,Deserializer>();
 
-  private final HashMap<Class,Deserializer> _deserializerInterfaceMap
-    = new HashMap<Class,Deserializer>();
+  private final HashMap<Class<?>,Deserializer> _deserializerInterfaceMap
+    = new HashMap<Class<?>,Deserializer>();
 
   public ContextSerializerFactory(ContextSerializerFactory parent,
                                   ClassLoader loader)
@@ -115,7 +115,7 @@ public class ContextSerializerFactory
     if (loader == null)
       loader = _systemClassLoader;
 
-    _loader = loader;
+    _loaderRef = new WeakReference<ClassLoader>(loader);
 
     init();
   }
@@ -154,7 +154,12 @@ public class ContextSerializerFactory
 
   public ClassLoader getClassLoader()
   {
-    return _loader;
+    WeakReference<ClassLoader> loaderRef = _loaderRef;
+    
+    if (loaderRef != null)
+      return loaderRef.get();
+    else
+      return null;
   }
 
   /**
@@ -424,6 +429,7 @@ public class ContextSerializerFactory
 
     addBasic(boolean[].class, "[boolean", BasicSerializer.BOOLEAN_ARRAY);
     addBasic(byte[].class, "[byte", BasicSerializer.BYTE_ARRAY);
+    _staticSerializerMap.put(byte[].class.getName(), ByteArraySerializer.SER);
     addBasic(short[].class, "[short", BasicSerializer.SHORT_ARRAY);
     addBasic(int[].class, "[int", BasicSerializer.INTEGER_ARRAY);
     addBasic(long[].class, "[long", BasicSerializer.LONG_ARRAY);
diff --git a/com/caucho/hessian/io/Deflation.java b/com/caucho/hessian/io/Deflation.java
index 0e3ae50..486e37a 100644
--- a/com/caucho/hessian/io/Deflation.java
+++ b/com/caucho/hessian/io/Deflation.java
@@ -81,7 +81,7 @@ public class Deflation extends HessianEnvelope {
 
     if (! method.equals(getClass().getName()))
       throw new IOException("expected hessian Envelope method '" +
-			    getClass().getName() + "' at '" + method + "'");
+                            getClass().getName() + "' at '" + method + "'");
 
     return unwrapHeaders(in);
   }
@@ -136,14 +136,14 @@ public class Deflation extends HessianEnvelope {
       _out = null;
 
       if (out != null) {
-	_deflateOut.close();
-	_bodyOut.close();
+        _deflateOut.close();
+        _bodyOut.close();
 
-	out.writeInt(0);
+        out.writeInt(0);
 
         out.completeEnvelope();
           
-	out.close();
+        out.close();
       }
     }
   }
@@ -188,17 +188,17 @@ public class Deflation extends HessianEnvelope {
       _in = null;
 
       if (in != null) {
-	_inflateIn.close();
-	_bodyIn.close();
+        _inflateIn.close();
+        _bodyIn.close();
 
-	int len = in.readInt();
+        int len = in.readInt();
 
-	if (len != 0)
-	  throw new IOException("Unexpected footer");
+        if (len != 0)
+          throw new IOException("Unexpected footer");
 
         in.completeEnvelope();
 
-	in.close();
+        in.close();
       }
     }
   }
diff --git a/com/caucho/hessian/io/EnumDeserializer.java b/com/caucho/hessian/io/EnumDeserializer.java
index cd3f155..c7e6e63 100644
--- a/com/caucho/hessian/io/EnumDeserializer.java
+++ b/com/caucho/hessian/io/EnumDeserializer.java
@@ -70,7 +70,7 @@ public class EnumDeserializer extends AbstractDeserializer {
 
     try {
       _valueOf = _enumType.getMethod("valueOf",
-			     new Class[] { Class.class, String.class });
+                             new Class[] { Class.class, String.class });
     } catch (Exception e) {
       throw new RuntimeException(e);
     }
@@ -92,7 +92,7 @@ public class EnumDeserializer extends AbstractDeserializer {
       if (key.equals("name"))
         name = in.readString();
       else
-	in.readObject();
+        in.readObject();
     }
 
     in.readMapEnd();
@@ -115,7 +115,7 @@ public class EnumDeserializer extends AbstractDeserializer {
       if ("name".equals(fieldNames[i]))
         name = in.readString();
       else
-	in.readObject();
+        in.readObject();
     }
 
     Object obj = create(name);
diff --git a/com/caucho/hessian/io/EnumSerializer.java b/com/caucho/hessian/io/EnumSerializer.java
index 7bed60f..ab965f6 100644
--- a/com/caucho/hessian/io/EnumSerializer.java
+++ b/com/caucho/hessian/io/EnumSerializer.java
@@ -97,9 +97,9 @@ public class EnumSerializer extends AbstractSerializer {
     }
     else {
       if (ref == -1) {
-	out.writeClassFieldLength(1);
-	out.writeString("name");
-	out.writeObjectBegin(cl.getName());
+        out.writeClassFieldLength(1);
+        out.writeString("name");
+        out.writeObjectBegin(cl.getName());
       }
 
       out.writeString(name);
diff --git a/com/caucho/hessian/io/Hessian2Input.java b/com/caucho/hessian/io/Hessian2Input.java
index 0ad8860..00cfe10 100644
--- a/com/caucho/hessian/io/Hessian2Input.java
+++ b/com/caucho/hessian/io/Hessian2Input.java
@@ -82,7 +82,7 @@ public class Hessian2Input
 
   private static Field _detailMessageField;
 
-  private static final int SIZE = 256;
+  private static final int SIZE = 1024;
   private static final int GAP = 16;
   
   // standard, unmodified factory for deserializing objects
@@ -111,13 +111,22 @@ public class Hessian2Input
   private String _method;
   private Throwable _replyFault;
 
-  private StringBuffer _sbuf = new StringBuffer();
+  private StringBuilder _sbuf = new StringBuilder();
   
   // true if this is the last chunk
   private boolean _isLastChunk;
   // the chunk length
   private int _chunkLength;
   
+  private HessianDebugInputStream _dIs;
+  
+  public Hessian2Input()
+  {
+    if (log.isLoggable(Level.FINEST)) {
+      _dIs = new HessianDebugInputStream(log, Level.FINEST);
+    }
+  }
+  
   /**
    * Creates a new Hessian input stream, initialized with an
    * underlying input stream.
@@ -126,7 +135,9 @@ public class Hessian2Input
    */
   public Hessian2Input(InputStream is)
   {
-    _is = is;
+    this();
+    
+    init(is);
   }
 
   /**
@@ -193,6 +204,31 @@ public class Hessian2Input
     return _replyFault;
   }
 
+  @Override
+  public void init(InputStream is)
+  {
+    if (_dIs != null) {
+      _dIs.initPacket(is);
+      is = _dIs;
+    }
+    
+    _is = is;
+    
+    reset();
+  }
+
+  public void initPacket(InputStream is)
+  {
+    if (_dIs != null) {
+      _dIs.initPacket(is);
+      is = _dIs;
+    }
+    
+    _is = is;
+    
+    resetReferences();
+  }
+
   /**
    * Starts reading the call
    *
@@ -354,17 +390,17 @@ public class Hessian2Input
       sb.append((char) tag);
       
       try {
-	int ch;
+        int ch;
 
-	while ((ch = read()) >= 0) {
-	  sb.append((char) ch);
-	}
+        while ((ch = read()) >= 0) {
+          sb.append((char) ch);
+        }
       } catch (IOException e) {
-	log.log(Level.FINE, e.toString(), e);
+        log.log(Level.FINE, e.toString(), e);
       }
       
       throw error("expected hessian reply at " + codeName(tag) + "\n"
-		  + sb);
+                  + sb);
     }
   }
 
@@ -398,12 +434,12 @@ public class Hessian2Input
       _replyFault = (Throwable) detail;
       
       if (message != null && _detailMessageField != null) {
-	try {
-	  _detailMessageField.set(_replyFault, message);
-	} catch (Throwable e) {
-	}
+        try {
+          _detailMessageField.set(_replyFault, message);
+        } catch (Throwable e) {
+        }
       }
-	
+
       return _replyFault;
     }
 
@@ -585,7 +621,7 @@ public class Hessian2Input
       return true;
       
     case 'I': return
-	parseInt() != 0;
+        parseInt() != 0;
       
     case 0xd8: case 0xd9: case 0xda: case 0xdb:
     case 0xdc: case 0xdd: case 0xde: case 0xdf:
@@ -621,9 +657,9 @@ public class Hessian2Input
 
     case BC_LONG_INT:
       return (0x1000000L * read()
-	      + 0x10000L * read()
-	      + 0x100 * read()
-	      + read()) != 0;
+              + 0x10000L * read()
+              + 0x100 * read()
+              + read()) != 0;
       
     case 'L':
       return parseLong() != 0;
@@ -642,9 +678,9 @@ public class Hessian2Input
       
     case BC_DOUBLE_MILL:
       {
-	int mills = parseInt();
+        int mills = parseInt();
 
-	return mills != 0;
+        return mills != 0;
       }
       
     case 'D':
@@ -731,9 +767,9 @@ public class Hessian2Input
     case 'I':
     case BC_LONG_INT:
       return ((read() << 24)
-	      + (read() << 16)
-	      + (read() << 8)
-	      + read());
+              + (read() << 16)
+              + (read() << 8)
+              + read());
 
       // direct long
     case 0xd8: case 0xd9: case 0xda: case 0xdb:
@@ -777,9 +813,9 @@ public class Hessian2Input
 
     case BC_DOUBLE_MILL:
       {
-	int mills = parseInt();
+        int mills = parseInt();
 
-	return (int) (0.001 * mills);
+        return (int) (0.001 * mills);
       }
 
     case 'D':
@@ -892,9 +928,9 @@ public class Hessian2Input
 
     case BC_DOUBLE_MILL:
       {
-	int mills = parseInt();
+        int mills = parseInt();
 
-	return (long) (0.001 * mills);
+        return (long) (0.001 * mills);
       }
 
     case 'D':
@@ -1017,9 +1053,9 @@ public class Hessian2Input
 
     case BC_DOUBLE_MILL:
       {
-	int mills = parseInt();
+        int mills = parseInt();
 
-	return 0.001 * mills;
+        return 0.001 * mills;
       }
       
     case 'D':
@@ -1131,14 +1167,14 @@ public class Hessian2Input
       case 0x14: case 0x15: case 0x16: case 0x17:
       case 0x18: case 0x19: case 0x1a: case 0x1b:
       case 0x1c: case 0x1d: case 0x1e: case 0x1f:
-	_isLastChunk = true;
-	_chunkLength = tag - 0x00;
-	break;
-	
+        _isLastChunk = true;
+        _chunkLength = tag - 0x00;
+        break;
+
       case 0x30: case 0x31: case 0x32: case 0x33:
-	_isLastChunk = true;
-	_chunkLength = (tag - 0x30) * 256 + read();
-	break;
+        _isLastChunk = true;
+        _chunkLength = (tag - 0x30) * 256 + read();
+        break;
 
       default:
         throw expect("string", tag);
@@ -1170,25 +1206,25 @@ public class Hessian2Input
           _chunkLength = (read() << 8) + read();
           break;
 
-	case 0x00: case 0x01: case 0x02: case 0x03:
-	case 0x04: case 0x05: case 0x06: case 0x07:
-	case 0x08: case 0x09: case 0x0a: case 0x0b:
-	case 0x0c: case 0x0d: case 0x0e: case 0x0f:
-
-	case 0x10: case 0x11: case 0x12: case 0x13:
-	case 0x14: case 0x15: case 0x16: case 0x17:
-	case 0x18: case 0x19: case 0x1a: case 0x1b:
-	case 0x1c: case 0x1d: case 0x1e: case 0x1f:
-	  _isLastChunk = true;
-	  _chunkLength = tag - 0x00;
-	  break;
-
-	case 0x30: case 0x31: case 0x32: case 0x33:
-	  _isLastChunk = true;
-	  _chunkLength = (tag - 0x30) * 256 + read();
-	  break;
-      
-	default:
+        case 0x00: case 0x01: case 0x02: case 0x03:
+        case 0x04: case 0x05: case 0x06: case 0x07:
+        case 0x08: case 0x09: case 0x0a: case 0x0b:
+        case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+
+        case 0x10: case 0x11: case 0x12: case 0x13:
+        case 0x14: case 0x15: case 0x16: case 0x17:
+        case 0x18: case 0x19: case 0x1a: case 0x1b:
+        case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+          _isLastChunk = true;
+          _chunkLength = tag - 0x00;
+          break;
+
+        case 0x30: case 0x31: case 0x32: case 0x33:
+          _isLastChunk = true;
+          _chunkLength = (tag - 0x30) * 256 + read();
+          break;
+      
+        default:
           throw expect("string", tag);
         }
       }
@@ -1257,7 +1293,7 @@ public class Hessian2Input
     case 0xd0: case 0xd1: case 0xd2: case 0xd3:
     case 0xd4: case 0xd5: case 0xd6: case 0xd7:
       return String.valueOf(((tag - BC_INT_SHORT_ZERO) << 16)
-			    + 256 * read() + read());
+                            + 256 * read() + read());
 
     case 'I':
     case BC_LONG_INT:
@@ -1284,7 +1320,7 @@ public class Hessian2Input
     case 0x38: case 0x39: case 0x3a: case 0x3b:
     case 0x3c: case 0x3d: case 0x3e: case 0x3f:
       return String.valueOf(((tag - BC_LONG_SHORT_ZERO) << 16)
-			    + 256 * read() + read());
+                            + 256 * read() + read());
 
     case 'L':
       return String.valueOf(parseLong());
@@ -1297,17 +1333,17 @@ public class Hessian2Input
 
     case BC_DOUBLE_BYTE:
       return String.valueOf((byte) (_offset < _length
-				    ? _buffer[_offset++]
-				    : read()));
+                                    ? _buffer[_offset++]
+                                    : read()));
 
     case BC_DOUBLE_SHORT:
       return String.valueOf(((short) (256 * read() + read())));
 
     case BC_DOUBLE_MILL:
       {
-	int mills = parseInt();
+        int mills = parseInt();
 
-	return String.valueOf(0.001 * mills);
+        return String.valueOf(0.001 * mills);
       }
       
     case 'D':
@@ -1397,42 +1433,42 @@ public class Hessian2Input
     case 0x28: case 0x29: case 0x2a: case 0x2b:
     case 0x2c: case 0x2d: case 0x2e: case 0x2f:
       {
-	_isLastChunk = true;
-	_chunkLength = tag - 0x20;
+        _isLastChunk = true;
+        _chunkLength = tag - 0x20;
 
-	byte []buffer = new byte[_chunkLength];
+        byte []buffer = new byte[_chunkLength];
 
-	int offset = 0;
-	while (offset < _chunkLength) {
-	  int sublen = read(buffer, 0, _chunkLength - offset);
+        int offset = 0;
+        while (offset < _chunkLength) {
+          int sublen = read(buffer, 0, _chunkLength - offset);
 
-	  if (sublen <= 0)
-	    break;
-	  
-	  offset += sublen;
-	}
+          if (sublen <= 0)
+            break;
+
+          offset += sublen;
+        }
 
-	return buffer;
+        return buffer;
       }
       
     case 0x34: case 0x35: case 0x36: case 0x37:
       {
-	_isLastChunk = true;
-	_chunkLength = (tag - 0x34) * 256 + read();
+        _isLastChunk = true;
+        _chunkLength = (tag - 0x34) * 256 + read();
+
+        byte []buffer = new byte[_chunkLength];
 
-	byte []buffer = new byte[_chunkLength];
+        int offset = 0;
+        while (offset < _chunkLength) {
+          int sublen = read(buffer, 0, _chunkLength - offset);
 
-	int offset = 0;
-	while (offset < _chunkLength) {
-	  int sublen = read(buffer, 0, _chunkLength - offset);
+          if (sublen <= 0)
+            break;
 
-	  if (sublen <= 0)
-	    break;
-	  
-	  offset += sublen;
-	}
+          offset += sublen;
+        }
 
-	return buffer;
+        return buffer;
       }
       
     default:
@@ -1467,17 +1503,17 @@ public class Hessian2Input
     case 'B':
     case BC_BINARY_CHUNK:
       {
-	_isLastChunk = tag == 'B';
-	_chunkLength = (read() << 8) + read();
+        _isLastChunk = tag == 'B';
+        _chunkLength = (read() << 8) + read();
 
-	int value = parseByte();
+        int value = parseByte();
 
-	// special code so successive read byte won't
-	// be read as a single object.
-	if (_chunkLength == 0 && _isLastChunk)
-	  _chunkLength = END_OF_DATA;
+        // special code so successive read byte won't
+        // be read as a single object.
+        if (_chunkLength == 0 && _isLastChunk)
+          _chunkLength = END_OF_DATA;
 
-	return value;
+        return value;
       }
 
     case 0x20: case 0x21: case 0x22: case 0x23:
@@ -1485,32 +1521,32 @@ public class Hessian2Input
     case 0x28: case 0x29: case 0x2a: case 0x2b:
     case 0x2c: case 0x2d: case 0x2e: case 0x2f:
       {
-	_isLastChunk = true;
-	_chunkLength = tag - 0x20;
+        _isLastChunk = true;
+        _chunkLength = tag - 0x20;
 
-	int value = parseByte();
+        int value = parseByte();
 
-	// special code so successive read byte won't
-	// be read as a single object.
-	if (_chunkLength == 0)
-	  _chunkLength = END_OF_DATA;
+        // special code so successive read byte won't
+        // be read as a single object.
+        if (_chunkLength == 0)
+          _chunkLength = END_OF_DATA;
 
-	return value;
+        return value;
       }
       
     case 0x34: case 0x35: case 0x36: case 0x37:
       {
-	_isLastChunk = true;
-	_chunkLength = (tag - 0x34) * 256 + read();
+        _isLastChunk = true;
+        _chunkLength = (tag - 0x34) * 256 + read();
 
-	int value = parseByte();
+        int value = parseByte();
 
-	// special code so successive read byte won't
-	// be read as a single object.
-	if (_chunkLength == 0)
-	  _chunkLength = END_OF_DATA;
+        // special code so successive read byte won't
+        // be read as a single object.
+        if (_chunkLength == 0)
+          _chunkLength = END_OF_DATA;
 
-	return value;
+        return value;
       }
       
     default:
@@ -1548,16 +1584,16 @@ public class Hessian2Input
     case 0x28: case 0x29: case 0x2a: case 0x2b:
     case 0x2c: case 0x2d: case 0x2e: case 0x2f:
       {
-	_isLastChunk = true;
-	_chunkLength = tag - 0x20;
-	break;
+        _isLastChunk = true;
+        _chunkLength = tag - 0x20;
+        break;
       }
       
     case 0x34: case 0x35: case 0x36: case 0x37:
       {
-	_isLastChunk = true;
-	_chunkLength = (tag - 0x34) * 256 + read();
-	break;
+        _isLastChunk = true;
+        _chunkLength = (tag - 0x34) * 256 + read();
+        break;
       }
       
       default:
@@ -1648,35 +1684,35 @@ public class Hessian2Input
 
     case 'H':
       {
-	Deserializer reader = findSerializerFactory().getDeserializer(cl);
+        Deserializer reader = findSerializerFactory().getDeserializer(cl);
 
-	return reader.readMap(this);
+        return reader.readMap(this);
       }
 
     case 'M':
       {
-	String type = readType();
+        String type = readType();
 
-	// hessian/3bb3
-	if ("".equals(type)) {
-	  Deserializer reader;
-	  reader = findSerializerFactory().getDeserializer(cl);
+        // hessian/3bb3
+        if ("".equals(type)) {
+          Deserializer reader;
+          reader = findSerializerFactory().getDeserializer(cl);
 
-	  return reader.readMap(this);
-	}
-	else {
-	  Deserializer reader;
-	  reader = findSerializerFactory().getObjectDeserializer(type, cl);
+          return reader.readMap(this);
+        }
+        else {
+          Deserializer reader;
+          reader = findSerializerFactory().getObjectDeserializer(type, cl);
 
-	  return reader.readMap(this);
-	}
+          return reader.readMap(this);
+        }
       }
 
     case 'C':
       {
-	readObjectDefinition(cl);
+        readObjectDefinition(cl);
 
-	return readObject(cl);
+        return readObject(cl);
       }
 
     case 0x60: case 0x61: case 0x62: case 0x63:
@@ -1684,110 +1720,110 @@ public class Hessian2Input
     case 0x68: case 0x69: case 0x6a: case 0x6b:
     case 0x6c: case 0x6d: case 0x6e: case 0x6f:
       {
-	int ref = tag - 0x60;
-	int size = _classDefs.size();
+        int ref = tag - 0x60;
+        int size = _classDefs.size();
 
-	if (ref < 0 || size <= ref)
-	  throw new HessianProtocolException("'" + ref + "' is an unknown class definition");
+        if (ref < 0 || size <= ref)
+          throw new HessianProtocolException("'" + ref + "' is an unknown class definition");
 
-	ObjectDefinition def = _classDefs.get(ref);
+        ObjectDefinition def = _classDefs.get(ref);
 
-	return readObjectInstance(cl, def);
+        return readObjectInstance(cl, def);
       }
 
     case 'O':
       {
-	int ref = readInt();
-	int size = _classDefs.size();
+        int ref = readInt();
+        int size = _classDefs.size();
 
-	if (ref < 0 || size <= ref)
-	  throw new HessianProtocolException("'" + ref + "' is an unknown class definition");
+        if (ref < 0 || size <= ref)
+          throw new HessianProtocolException("'" + ref + "' is an unknown class definition");
 
-	ObjectDefinition def = _classDefs.get(ref);
+        ObjectDefinition def = _classDefs.get(ref);
 
-	return readObjectInstance(cl, def);
+        return readObjectInstance(cl, def);
       }
 
     case BC_LIST_VARIABLE:
       {
-	String type = readType();
+        String type = readType();
       
-	Deserializer reader;
-	reader = findSerializerFactory().getListDeserializer(type, cl);
+        Deserializer reader;
+        reader = findSerializerFactory().getListDeserializer(type, cl);
 
-	Object v = reader.readList(this, -1);
+        Object v = reader.readList(this, -1);
 
-	return v;
+        return v;
       }
 
     case BC_LIST_FIXED:
       {
-	String type = readType();
-	int length = readInt();
+        String type = readType();
+        int length = readInt();
       
-	Deserializer reader;
-	reader = findSerializerFactory().getListDeserializer(type, cl);
+        Deserializer reader;
+        reader = findSerializerFactory().getListDeserializer(type, cl);
 
-	Object v = reader.readLengthList(this, length);
+        Object v = reader.readLengthList(this, length);
 
-	return v;
+        return v;
       }
 
     case 0x70: case 0x71: case 0x72: case 0x73:
     case 0x74: case 0x75: case 0x76: case 0x77:
       {
-	int length = tag - 0x70;
+        int length = tag - 0x70;
 
-	String type = readType();
+        String type = readType();
       
-	Deserializer reader;
-	reader = findSerializerFactory().getListDeserializer(type, cl);
+        Deserializer reader;
+        reader = findSerializerFactory().getListDeserializer(type, cl);
 
-	Object v = reader.readLengthList(this, length);
+        Object v = reader.readLengthList(this, length);
 
-	return v;
+        return v;
       }
 
     case BC_LIST_VARIABLE_UNTYPED:
       {
-	Deserializer reader;
-	reader = findSerializerFactory().getListDeserializer(null, cl);
+        Deserializer reader;
+        reader = findSerializerFactory().getListDeserializer(null, cl);
 
-	Object v = reader.readList(this, -1);
+        Object v = reader.readList(this, -1);
 
-	return v;
+        return v;
       }
 
     case BC_LIST_FIXED_UNTYPED:
       {
-	int length = readInt();
+        int length = readInt();
       
-	Deserializer reader;
-	reader = findSerializerFactory().getListDeserializer(null, cl);
+        Deserializer reader;
+        reader = findSerializerFactory().getListDeserializer(null, cl);
 
-	Object v = reader.readLengthList(this, length);
+        Object v = reader.readLengthList(this, length);
 
-	return v;
+        return v;
       }
 
     case 0x78: case 0x79: case 0x7a: case 0x7b:
     case 0x7c: case 0x7d: case 0x7e: case 0x7f:
       {
-	int length = tag - 0x78;
+        int length = tag - 0x78;
       
-	Deserializer reader;
-	reader = findSerializerFactory().getListDeserializer(null, cl);
+        Deserializer reader;
+        reader = findSerializerFactory().getListDeserializer(null, cl);
 
-	Object v = reader.readLengthList(this, length);
+        Object v = reader.readLengthList(this, length);
 
-	return v;
+        return v;
       }
 
     case BC_REF:
       {
-	int ref = readInt();
+        int ref = readInt();
 
-	return _refs.get(ref);
+        return _refs.get(ref);
       }
     }
 
@@ -1852,7 +1888,7 @@ public class Hessian2Input
     case 0xd0: case 0xd1: case 0xd2: case 0xd3:
     case 0xd4: case 0xd5: case 0xd6: case 0xd7:
       return Integer.valueOf(((tag - BC_INT_SHORT_ZERO) << 16)
-			     + 256 * read() + read());
+                             + 256 * read() + read());
       
     case 'I':
       return Integer.valueOf(parseInt());
@@ -1899,9 +1935,9 @@ public class Hessian2Input
       
     case BC_DOUBLE_MILL:
       {
-	int mills = parseInt();
+        int mills = parseInt();
 
-	return Double.valueOf(0.001 * mills);
+        return Double.valueOf(0.001 * mills);
       }
 
     case 'D':
@@ -1916,16 +1952,14 @@ public class Hessian2Input
     case BC_STRING_CHUNK:
     case 'S':
       {
-	_isLastChunk = tag == 'S';
-	_chunkLength = (read() << 8) + read();
+        _isLastChunk = tag == 'S';
+        _chunkLength = (read() << 8) + read();
 
-	int data;
-	_sbuf.setLength(0);
-      
-	while ((data = parseChar()) >= 0)
-	  _sbuf.append((char) data);
+        _sbuf.setLength(0);
+        
+        parseString(_sbuf);
 
-	return _sbuf.toString();
+        return _sbuf.toString();
       }
 
     case 0x00: case 0x01: case 0x02: case 0x03:
@@ -1938,45 +1972,42 @@ public class Hessian2Input
     case 0x18: case 0x19: case 0x1a: case 0x1b:
     case 0x1c: case 0x1d: case 0x1e: case 0x1f:
       {
-	_isLastChunk = true;
-	_chunkLength = tag - 0x00;
+        _isLastChunk = true;
+        _chunkLength = tag - 0x00;
 
-	int data;
-	_sbuf.setLength(0);
+        int data;
+        _sbuf.setLength(0);
       
-	while ((data = parseChar()) >= 0)
-	  _sbuf.append((char) data);
+        parseString(_sbuf);
 
-	return _sbuf.toString();
+        return _sbuf.toString();
       }
 
     case 0x30: case 0x31: case 0x32: case 0x33:
       {
-	_isLastChunk = true;
-	_chunkLength = (tag - 0x30) * 256 + read();
+        _isLastChunk = true;
+        _chunkLength = (tag - 0x30) * 256 + read();
 
-	_sbuf.setLength(0);
+        _sbuf.setLength(0);
 
-	int ch;
-	while ((ch = parseChar()) >= 0)
-	  _sbuf.append((char) ch);
+        parseString(_sbuf);
 
-	return _sbuf.toString();
+        return _sbuf.toString();
       }
 
     case BC_BINARY_CHUNK:
     case 'B':
       {
-	_isLastChunk = tag == 'B';
-	_chunkLength = (read() << 8) + read();
+        _isLastChunk = tag == 'B';
+        _chunkLength = (read() << 8) + read();
 
-	int data;
-	ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        int data;
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
       
-	while ((data = parseByte()) >= 0)
-	  bos.write(data);
+        while ((data = parseByte()) >= 0)
+          bos.write(data);
 
-	return bos.toByteArray();
+        return bos.toByteArray();
       }
 
     case 0x20: case 0x21: case 0x22: case 0x23:
@@ -1984,113 +2015,113 @@ public class Hessian2Input
     case 0x28: case 0x29: case 0x2a: case 0x2b:
     case 0x2c: case 0x2d: case 0x2e: case 0x2f:
       {
-	_isLastChunk = true;
-	int len = tag - 0x20;
-	_chunkLength = 0;
+        _isLastChunk = true;
+        int len = tag - 0x20;
+        _chunkLength = 0;
 
-	byte []data = new byte[len];
+        byte []data = new byte[len];
 
-	for (int i = 0; i < len; i++)
-	  data[i] = (byte) read();
+        for (int i = 0; i < len; i++)
+          data[i] = (byte) read();
 
-	return data;
+        return data;
       }
       
     case 0x34: case 0x35: case 0x36: case 0x37:
       {
-	_isLastChunk = true;
-	int len = (tag - 0x34) * 256 + read();
-	_chunkLength = 0;
+        _isLastChunk = true;
+        int len = (tag - 0x34) * 256 + read();
+        _chunkLength = 0;
 
-	byte []buffer = new byte[len];
+        byte []buffer = new byte[len];
 
-	for (int i = 0; i < len; i++) {
-	  buffer[i] = (byte) read();
-	}
+        for (int i = 0; i < len; i++) {
+          buffer[i] = (byte) read();
+        }
 
-	return buffer;
+        return buffer;
       }
 
     case BC_LIST_VARIABLE:
       {
-	// variable length list
-	String type = readType();
+        // variable length list
+        String type = readType();
 
-	return findSerializerFactory().readList(this, -1, type);
+        return findSerializerFactory().readList(this, -1, type);
       }
 
     case BC_LIST_VARIABLE_UNTYPED:
       {
-	return findSerializerFactory().readList(this, -1, null);
+        return findSerializerFactory().readList(this, -1, null);
       }
 
     case BC_LIST_FIXED:
       {
-	// fixed length lists
-	String type = readType();
-	int length = readInt();
+        // fixed length lists
+        String type = readType();
+        int length = readInt();
 
-	Deserializer reader;
-	reader = findSerializerFactory().getListDeserializer(type, null);
+        Deserializer reader;
+        reader = findSerializerFactory().getListDeserializer(type, null);
       
-	return reader.readLengthList(this, length);
+        return reader.readLengthList(this, length);
       }
 
     case BC_LIST_FIXED_UNTYPED:
       {
-	// fixed length lists
-	int length = readInt();
+        // fixed length lists
+        int length = readInt();
 
-	Deserializer reader;
-	reader = findSerializerFactory().getListDeserializer(null, null);
+        Deserializer reader;
+        reader = findSerializerFactory().getListDeserializer(null, null);
       
-	return reader.readLengthList(this, length);
+        return reader.readLengthList(this, length);
       }
 
       // compact fixed list
     case 0x70: case 0x71: case 0x72: case 0x73:
     case 0x74: case 0x75: case 0x76: case 0x77:
       {
-	// fixed length lists
-	String type = readType();
-	int length = tag - 0x70;
+        // fixed length lists
+        String type = readType();
+        int length = tag - 0x70;
 
-	Deserializer reader;
-	reader = findSerializerFactory().getListDeserializer(type, null);
+        Deserializer reader;
+        reader = findSerializerFactory().getListDeserializer(type, null);
       
-	return reader.readLengthList(this, length);
+        return reader.readLengthList(this, length);
       }
 
       // compact fixed untyped list
     case 0x78: case 0x79: case 0x7a: case 0x7b:
     case 0x7c: case 0x7d: case 0x7e: case 0x7f:
       {
-	// fixed length lists
-	int length = tag - 0x78;
+        // fixed length lists
+        int length = tag - 0x78;
 
-	Deserializer reader;
-	reader = findSerializerFactory().getListDeserializer(null, null);
+        Deserializer reader;
+        reader = findSerializerFactory().getListDeserializer(null, null);
       
-	return reader.readLengthList(this, length);
+        return reader.readLengthList(this, length);
       }
 
     case 'H':
       {
-	return findSerializerFactory().readMap(this, null);
+        return findSerializerFactory().readMap(this, null);
       }
 
     case 'M':
       {
-	String type = readType();
+        String type = readType();
 
-	return findSerializerFactory().readMap(this, type);
+        return findSerializerFactory().readMap(this, type);
       }
 
     case 'C':
       {
-	readObjectDefinition(null);
+        readObjectDefinition(null);
 
-	return readObject();
+        return readObject();
       }
 
     case 0x60: case 0x61: case 0x62: case 0x63:
@@ -2098,41 +2129,41 @@ public class Hessian2Input
     case 0x68: case 0x69: case 0x6a: case 0x6b:
     case 0x6c: case 0x6d: case 0x6e: case 0x6f:
       {
-	int ref = tag - 0x60;
+        int ref = tag - 0x60;
+
+        if (_classDefs.size() <= ref)
+          throw error("No classes defined at reference '"
+                      + Integer.toHexString(tag) + "'");
 
-	if (_classDefs.size() <= ref)
-	  throw error("No classes defined at reference '"
-		      + Integer.toHexString(tag) + "'");
-	
-	ObjectDefinition def = _classDefs.get(ref);
+        ObjectDefinition def = _classDefs.get(ref);
 
-	return readObjectInstance(null, def);
+        return readObjectInstance(null, def);
       }
 
     case 'O':
       {
-	int ref = readInt();
+        int ref = readInt();
 
-	if (_classDefs.size() <= ref)
-	  throw error("Illegal object reference #" + ref);
+        if (_classDefs.size() <= ref)
+          throw error("Illegal object reference #" + ref);
 
-	ObjectDefinition def = _classDefs.get(ref);
+        ObjectDefinition def = _classDefs.get(ref);
 
-	return readObjectInstance(null, def);
+        return readObjectInstance(null, def);
       }
 
     case BC_REF:
       {
-	int ref = readInt();
+        int ref = readInt();
 
-	return _refs.get(ref);
+        return _refs.get(ref);
       }
 
     default:
       if (tag < 0)
-	throw new EOFException("readObject: unexpected end of file");
+        throw new EOFException("readObject: unexpected end of file");
       else
-	throw error("readObject: unknown code " + codeName(tag));
+        throw error("readObject: unknown code " + codeName(tag));
     }
   }
 
@@ -2207,7 +2238,9 @@ public class Hessian2Input
   public Object readRef()
     throws IOException
   {
-    return _refs.get(parseInt());
+    int value = parseInt();
+    
+    return _refs.get(value);
   }
 
   /**
@@ -2242,7 +2275,7 @@ public class Hessian2Input
       code = read();
 
       if (code >= 0)
-	_offset--;
+        _offset--;
     }
 
     return (code < 0 || code == 'Z');
@@ -2291,6 +2324,7 @@ public class Hessian2Input
   /**
    * Adds a list/map reference.
    */
+  @Override
   public int addRef(Object ref)
   {
     if (_refs == null)
@@ -2312,6 +2346,7 @@ public class Hessian2Input
   /**
    * Resets the references for streaming.
    */
+  @Override
   public void resetReferences()
   {
     _refs.clear();
@@ -2388,24 +2423,24 @@ public class Hessian2Input
     case 0x30: case 0x31: case 0x32: case 0x33:
     case BC_STRING_CHUNK: case 'S':
       {
-	String type = readString();
+        String type = readString();
 
-	if (_types == null)
-	  _types = new ArrayList();
+        if (_types == null)
+          _types = new ArrayList();
 
-	_types.add(type);
+        _types.add(type);
 
-	return type;
+        return type;
       }
 
     default:
       {
-	int ref = readInt();
+        int ref = readInt();
+
+        if (_types.size() <= ref)
+          throw new IndexOutOfBoundsException("type ref #" + ref + " is greater than the number of valid types (" + _types.size() + ")");
 
-	if (_types.size() <= ref)
-	  throw new IndexOutOfBoundsException("type ref #" + ref + " is greater than the number of valid types (" + _types.size() + ")");
-	
-	return (String) _types.get(ref);
+        return (String) _types.get(ref);
       }
     }
   }
@@ -2477,13 +2512,13 @@ public class Hessian2Input
     long b8 = read();
 
     return ((b64 << 56)
-	    + (b56 << 48)
-	    + (b48 << 40)
-	    + (b40 << 32)
-	    + (b32 << 24)
-	    + (b24 << 16)
-	    + (b16 << 8)
-	    + b8);
+            + (b56 << 48)
+            + (b48 << 40)
+            + (b40 << 32)
+            + (b32 << 24)
+            + (b24 << 16)
+            + (b16 << 8)
+            + b8);
   }
   
   /**
@@ -2506,7 +2541,25 @@ public class Hessian2Input
   {
     throw new UnsupportedOperationException();
   }
-  
+
+  private void parseString(StringBuilder sbuf)
+    throws IOException
+  {
+    while (true) {
+      if (_chunkLength <= 0) {
+        if (! parseChunkLength())
+          return;
+      }
+      
+      int length = _chunkLength;
+      _chunkLength = 0;
+      
+      while (length-- > 0) {
+        sbuf.append((char) parseUTF8Char());
+      }
+    }
+  }
+
   /**
    * Reads a character from the underlying stream.
    */
@@ -2514,51 +2567,59 @@ public class Hessian2Input
     throws IOException
   {
     while (_chunkLength <= 0) {
-      if (_isLastChunk)
+      if (! parseChunkLength())
         return -1;
+    }
 
-      int code = _offset < _length ? (_buffer[_offset++] & 0xff) : read();
+    _chunkLength--;
 
-      switch (code) {
-      case BC_STRING_CHUNK:
-        _isLastChunk = false;
+    return parseUTF8Char();
+  }
+  
+  private boolean parseChunkLength()
+    throws IOException
+  {
+    if (_isLastChunk)
+      return false;
 
-        _chunkLength = (read() << 8) + read();
-        break;
-        
-      case 'S':
-        _isLastChunk = true;
+    int code = _offset < _length ? (_buffer[_offset++] & 0xff) : read();
 
-        _chunkLength = (read() << 8) + read();
-        break;
-	
-      case 0x00: case 0x01: case 0x02: case 0x03:
-      case 0x04: case 0x05: case 0x06: case 0x07:
-      case 0x08: case 0x09: case 0x0a: case 0x0b:
-      case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+    switch (code) {
+    case BC_STRING_CHUNK:
+      _isLastChunk = false;
 
-      case 0x10: case 0x11: case 0x12: case 0x13:
-      case 0x14: case 0x15: case 0x16: case 0x17:
-      case 0x18: case 0x19: case 0x1a: case 0x1b:
-      case 0x1c: case 0x1d: case 0x1e: case 0x1f:
-	_isLastChunk = true;
-	_chunkLength = code - 0x00;
-	break;
-	
-      case 0x30: case 0x31: case 0x32: case 0x33:
-	_isLastChunk = true;
-	_chunkLength = (code - 0x30) * 256 + read();
-	break;
+      _chunkLength = (read() << 8) + read();
+      break;
+      
+    case 'S':
+      _isLastChunk = true;
 
-      default:
-        throw expect("string", code);
-      }
+      _chunkLength = (read() << 8) + read();
+      break;
 
-    }
+    case 0x00: case 0x01: case 0x02: case 0x03:
+    case 0x04: case 0x05: case 0x06: case 0x07:
+    case 0x08: case 0x09: case 0x0a: case 0x0b:
+    case 0x0c: case 0x0d: case 0x0e: case 0x0f:
 
-    _chunkLength--;
+    case 0x10: case 0x11: case 0x12: case 0x13:
+    case 0x14: case 0x15: case 0x16: case 0x17:
+    case 0x18: case 0x19: case 0x1a: case 0x1b:
+    case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+      _isLastChunk = true;
+      _chunkLength = code - 0x00;
+      break;
 
-    return parseUTF8Char();
+    case 0x30: case 0x31: case 0x32: case 0x33:
+      _isLastChunk = true;
+      _chunkLength = (code - 0x30) * 256 + read();
+      break;
+
+    default:
+      throw expect("string", code);
+    }
+
+    return true;
   }
 
   /**
@@ -2624,7 +2685,7 @@ public class Hessian2Input
         break;
 
       case 0x34: case 0x35: case 0x36: case 0x37:
-	_isLastChunk = true;
+        _isLastChunk = true;
         _chunkLength = (code - 0x34) * 256 + read();
         break;
 
@@ -2704,18 +2765,18 @@ public class Hessian2Input
           _chunkLength = (read() << 8) + read();
           break;
 
-	case 0x20: case 0x21: case 0x22: case 0x23:
-	case 0x24: case 0x25: case 0x26: case 0x27:
-	case 0x28: case 0x29: case 0x2a: case 0x2b:
-	case 0x2c: case 0x2d: case 0x2e: case 0x2f:
-	  _isLastChunk = true;
-	  _chunkLength = code - 0x20;
-	  break;
-	  
-	case 0x34: case 0x35: case 0x36: case 0x37:
-	  _isLastChunk = true;
-	  _chunkLength = (code - 0x34) * 256 + read();
-	  break;
+        case 0x20: case 0x21: case 0x22: case 0x23:
+        case 0x24: case 0x25: case 0x26: case 0x27:
+        case 0x28: case 0x29: case 0x2a: case 0x2b:
+        case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+          _isLastChunk = true;
+          _chunkLength = code - 0x20;
+          break;
+
+        case 0x34: case 0x35: case 0x36: case 0x37:
+          _isLastChunk = true;
+          _chunkLength = (code - 0x34) * 256 + read();
+          break;
 
         default:
           throw expect("byte[]", code);
@@ -2727,10 +2788,10 @@ public class Hessian2Input
         sublen = length;
 
       if (_length <= _offset && ! readBuffer())
-	return -1;
+        return -1;
       
       if (_length - _offset < sublen)
-	sublen = _length - _offset;
+        sublen = _length - _offset;
 
       System.arraycopy(_buffer, _offset, buffer, offset, sublen);
 
@@ -2809,26 +2870,26 @@ public class Hessian2Input
       _offset--;
 
       try {
-	int offset = _offset;
-	String context
-	  = buildDebugContext(_buffer, 0, _length, offset);
-	  
-	Object obj = readObject();
-
-	if (obj != null) {
-	  return error("expected " + expect
-		       + " at 0x" + Integer.toHexString(ch & 0xff)
-		       + " " + obj.getClass().getName() + " (" + obj + ")"
-		       + "\n  " + context + "");
-	}
-	else
-	  return error("expected " + expect
-		       + " at 0x" + Integer.toHexString(ch & 0xff) + " null");
+        int offset = _offset;
+        String context
+          = buildDebugContext(_buffer, 0, _length, offset);
+
+        Object obj = readObject();
+
+        if (obj != null) {
+          return error("expected " + expect
+                       + " at 0x" + Integer.toHexString(ch & 0xff)
+                       + " " + obj.getClass().getName() + " (" + obj + ")"
+                       + "\n  " + context + "");
+        }
+        else
+          return error("expected " + expect
+                       + " at 0x" + Integer.toHexString(ch & 0xff) + " null");
       } catch (Exception e) {
-	log.log(Level.FINE, e.toString(), e);
-	
-	return error("expected " + expect
-		     + " at 0x" + Integer.toHexString(ch & 0xff));
+        log.log(Level.FINE, e.toString(), e);
+
+        return error("expected " + expect
+                     + " at 0x" + Integer.toHexString(ch & 0xff));
       }
     }
   }
@@ -2881,7 +2942,13 @@ public class Hessian2Input
     else
       return new HessianProtocolException(message);
   }
+  
+  public void free()
+  {
+    reset();
+  }
 
+  @Override
   public void close()
     throws IOException
   {
@@ -2894,29 +2961,29 @@ public class Hessian2Input
   
   class ReadInputStream extends InputStream {
     boolean _isClosed = false;
-	
+
     public int read()
       throws IOException
     {
       if (_isClosed)
-	return -1;
+        return -1;
 
       int ch = parseByte();
       if (ch < 0)
-	_isClosed = true;
+        _isClosed = true;
 
       return ch;
     }
-	
+
     public int read(byte []buffer, int offset, int length)
       throws IOException
     {
       if (_isClosed)
-	return -1;
+        return -1;
 
       int len = Hessian2Input.this.read(buffer, offset, length);
       if (len < 0)
-	_isClosed = true;
+        _isClosed = true;
 
       return len;
     }
diff --git a/com/caucho/hessian/io/Hessian2Output.java b/com/caucho/hessian/io/Hessian2Output.java
index 7a5408b..476181d 100644
--- a/com/caucho/hessian/io/Hessian2Output.java
+++ b/com/caucho/hessian/io/Hessian2Output.java
@@ -78,7 +78,8 @@ public class Hessian2Output
   extends AbstractHessianOutput
   implements Hessian2Constants
 {
-  public final static int SIZE = 4096;
+  // should match Resin buffer size for perf
+  public final static int SIZE = 8 * 1024;
 
   // the output stream/
   protected OutputStream _os;
@@ -86,6 +87,8 @@ public class Hessian2Output
   // map of references
   private final IdentityIntMap _refs
     = new IdentityIntMap(256);
+  
+  private int _refCount = 0;
 
   private boolean _isCloseStreamOnClose;
 
@@ -100,6 +103,18 @@ public class Hessian2Output
   private int _offset;
 
   private boolean _isPacket;
+  
+  private boolean _isUnshared;
+
+  /**
+   * Creates a new Hessian output stream, initialized with an
+   * underlying output stream.
+   *
+   * @param os the underlying output stream.
+   */
+  public Hessian2Output()
+  {
+  }
 
   /**
    * Creates a new Hessian output stream, initialized with an
@@ -112,6 +127,7 @@ public class Hessian2Output
     init(os);
   }
 
+  @Override
   public void init(OutputStream os)
   {
     reset();
@@ -119,6 +135,13 @@ public class Hessian2Output
     _os = os;
   }
 
+  public void initPacket(OutputStream os)
+  {
+    resetReferences();
+
+    _os = os;
+  }
+
   public void setCloseStreamOnClose(boolean isClose)
   {
     _isCloseStreamOnClose = isClose;
@@ -128,6 +151,20 @@ public class Hessian2Output
   {
     return _isCloseStreamOnClose;
   }
+  
+  /**
+   * Sets hessian to be "unshared", meaning it will not detect 
+   * duplicate or circular references.
+   */
+  @Override
+  public boolean setUnshared(boolean isUnshared)
+  {
+    boolean oldIsUnshared = _isUnshared;
+    
+    _isUnshared = isUnshared;
+    
+    return oldIsUnshared;
+  }
 
   /**
    * Writes a complete method call.
@@ -142,8 +179,9 @@ public class Hessian2Output
 
     startCall(method, length);
 
-    for (int i = 0; i < length; i++)
+    for (int i = 0; i < length; i++) {
       writeObject(args[i]);
+    }
 
     completeCall();
 
@@ -163,6 +201,7 @@ public class Hessian2Output
    *
    * @param method the method name to call.
    */
+  @Override
   public void startCall(String method, int length)
     throws IOException
   {
@@ -191,6 +230,7 @@ public class Hessian2Output
    *
    * @param method the method name to call.
    */
+  @Override
   public void startCall()
     throws IOException
   {
@@ -263,6 +303,7 @@ public class Hessian2Output
    * z
    * </pre></code>
    */
+  @Override
   public void completeCall()
     throws IOException
   {
@@ -282,6 +323,7 @@ public class Hessian2Output
    * R
    * </pre>
    */
+  @Override
   public void startReply()
     throws IOException
   {
@@ -311,6 +353,7 @@ public class Hessian2Output
    * z
    * </pre>
    */
+  @Override
   public void completeReply()
     throws IOException
   {
@@ -387,7 +430,7 @@ public class Hessian2Output
     _buffer[_offset++] = (byte) 'F';
     _buffer[_offset++] = (byte) 'H';
 
-    _refs.put(new Object(), _refs.size(), false);
+    addRef(new Object(), _refCount++, false);
 
     writeString("code");
     writeString(code);
@@ -407,6 +450,7 @@ public class Hessian2Output
   /**
    * Writes any object to the output stream.
    */
+  @Override
   public void writeObject(Object object)
     throws IOException
   {
@@ -565,6 +609,7 @@ public class Hessian2Output
   /**
    * Writes the tail of the class definition to the stream.
    */
+  @Override
   public void writeClassFieldLength(int len)
     throws IOException
   {
@@ -574,6 +619,7 @@ public class Hessian2Output
   /**
    * Writes the tail of the object definition to the stream.
    */
+  @Override
   public void writeObjectEnd()
     throws IOException
   {
@@ -623,6 +669,7 @@ public class Hessian2Output
    *
    * @param value the boolean value to write.
    */
+  @Override
   public void writeBoolean(boolean value)
     throws IOException
   {
@@ -645,6 +692,7 @@ public class Hessian2Output
    *
    * @param value the integer value to write.
    */
+  @Override
   public void writeInt(int value)
     throws IOException
   {
@@ -1277,12 +1325,18 @@ public class Hessian2Output
    *
    * @return true if we're writing a ref.
    */
+  @Override
   public boolean addRef(Object object)
     throws IOException
   {
-    int newRef = _refs.size();
+    if (_isUnshared) {
+      _refCount++;
+      return false;
+    }
+    
+    int newRef = _refCount;
 
-    int ref = _refs.put(object, newRef, false);
+    int ref = addRef(object, newRef, false);
     
     if (ref != newRef) {
       writeRef(ref);
@@ -1290,6 +1344,8 @@ public class Hessian2Output
       return true;
     }
     else {
+      _refCount++;
+      
       return false;
     }
   }
@@ -1297,6 +1353,9 @@ public class Hessian2Output
   @Override
   public int getRef(Object obj)
   {
+    if (_isUnshared)
+      return -1;
+    
     return _refs.get(obj);
   }
 
@@ -1307,7 +1366,10 @@ public class Hessian2Output
   public boolean removeRef(Object obj)
     throws IOException
   {
-    if (_refs != null) {
+    if (_isUnshared) {
+      return false;
+    }
+    else if (_refs != null) {
       _refs.remove(obj);
 
       return true;
@@ -1319,13 +1381,18 @@ public class Hessian2Output
   /**
    * Replaces a reference from one object to another.
    */
+  @Override
   public boolean replaceRef(Object oldRef, Object newRef)
     throws IOException
   {
+    if (_isUnshared) {
+      return false;
+    }
+    
     int value = _refs.get(oldRef);
 
     if (value >= 0) {
-      _refs.put(newRef, value, true);
+      addRef(newRef, value, true);
       
       _refs.remove(oldRef);
       
@@ -1334,6 +1401,13 @@ public class Hessian2Output
     else
       return false;
   }
+  
+  private int addRef(Object value, int newRef, boolean isReplace)
+  {
+    int prevRef = _refs.put(value, newRef, isReplace);
+    
+    return prevRef;
+  }
 
   /**
    * Starts the streaming message
@@ -1364,16 +1438,19 @@ public class Hessian2Output
   public void startPacket()
     throws IOException
   {
-    if (_refs != null)
+    if (_refs != null) {
       _refs.clear();
+      _refCount = 0;
+    }
 
     flushBuffer();
 
     _isPacket = true;
-    _offset = 3;
-    _buffer[0] = (byte) 0x55;
+    _offset = 4;
+    _buffer[0] = (byte) 0x05; // 0x05 = binary
     _buffer[1] = (byte) 0x55;
     _buffer[2] = (byte) 0x55;
+    _buffer[3] = (byte) 0x55;
   }
 
   public void endPacket()
@@ -1388,29 +1465,27 @@ public class Hessian2Output
       return;
     }
 
-    int len = offset - 3;
+    int len = offset - 4;
 
-    _buffer[0] = (byte) (0x80);
-    _buffer[1] = (byte) (0x80 + ((len >> 7) & 0x7f));
-    _buffer[2] = (byte) (len & 0x7f);
-
-    // end chunk
-    _buffer[offset++] = (byte) 0x80;
-    _buffer[offset++] = (byte) 0x00;
+    if (len < 0x7e) {
+      _buffer[2] = _buffer[0];
+      _buffer[3] = (byte) (len);
+    } else {
+      _buffer[1] = (byte) (0x7e);
+      _buffer[2] = (byte) (len >> 8);
+      _buffer[3] = (byte) (len);
+    }
 
     _isPacket = false;
     _offset = 0;
 
-    if (os != null) {
-      if (len == 0) {
-        os.write(_buffer, 1, 2);
-      }
-      else if (len < 0x80) {
-        os.write(_buffer, 1, offset - 1);
-      }
-      else {
-        os.write(_buffer, 0, offset);
-      }
+    if (os == null) {
+    }
+    else if (len < 0x7e) {
+      os.write(_buffer, 2, offset - 2);
+    }
+    else {
+      os.write(_buffer, 0, offset);
     }
   }
 
@@ -1552,23 +1627,26 @@ public class Hessian2Output
       if (os != null)
         os.write(_buffer, 0, offset);
     }
-    else if (_isPacket && offset > 3) {
-      int len = offset - 3;
-      _buffer[0] = (byte) 0x80;
-      _buffer[1] = (byte) (0x80 + ((len >> 7) & 0x7f));
-      _buffer[2] = (byte) (len & 0x7f);
-      _offset = 3;
+    else if (_isPacket && offset > 4) {
+      int len = offset - 4;
+      
+      _buffer[0] |= (byte) 0x80;
+      _buffer[1] = (byte) (0x7e);
+      _buffer[2] = (byte) (len >> 8);
+      _buffer[3] = (byte) (len);
+      _offset = 4;
 
       if (os != null)
         os.write(_buffer, 0, offset);
 
-      _buffer[0] = (byte) 0x56;
+      _buffer[0] = (byte) 0x00;
       _buffer[1] = (byte) 0x56;
       _buffer[2] = (byte) 0x56;
-
+      _buffer[3] = (byte) 0x56;
     }
   }
 
+  @Override
   public void close()
     throws IOException
   {
@@ -1598,8 +1676,10 @@ public class Hessian2Output
   @Override
   public void resetReferences()
   {
-    if (_refs != null)
+    if (_refs != null) {
       _refs.clear();
+      _refCount = 0;
+    }
   }
 
   /**
@@ -1607,13 +1687,16 @@ public class Hessian2Output
    */
   public void reset()
   {
-    if (_refs != null)
+    if (_refs != null) {
       _refs.clear();
+      _refCount = 0;
+    }
 
     _classRefs.clear();
     _typeRefs = null;
     _offset = 0;
     _isPacket = false;
+    _isUnshared = false;
   }
 
   class BytesOutputStream extends OutputStream {
diff --git a/com/caucho/hessian/io/Hessian2StreamingInput.java b/com/caucho/hessian/io/Hessian2StreamingInput.java
index ff3bae1..fa9259d 100644
--- a/com/caucho/hessian/io/Hessian2StreamingInput.java
+++ b/com/caucho/hessian/io/Hessian2StreamingInput.java
@@ -55,6 +55,13 @@ import java.util.logging.*;
 
 /**
  * Input stream for Hessian 2 streaming requests using WebSocket.
+ * 
+ * For best performance, use HessianFactory:
+ * 
+ * <code><pre>
+ * HessianFactory factory = new HessianFactory();
+ * Hessian2StreamingInput hIn = factory.createHessian2StreamingInput(is);
+ * </pre></code>
  */
 public class Hessian2StreamingInput
 {
@@ -150,11 +157,11 @@ public class Hessian2StreamingInput
     public boolean isDataAvailable()
     {
       try {
-	return _is != null && _is.available() > 0;
+        return _is != null && _is.available() > 0;
       } catch (IOException e) {
-	log.log(Level.FINER, e.toString(), e);
-	
-	return true;
+        log.log(Level.FINER, e.toString(), e);
+
+        return true;
       }
     }
 
@@ -163,7 +170,7 @@ public class Hessian2StreamingInput
     {
       // skip zero-length packets
       do {
-	_isPacketEnd = false;
+        _isPacketEnd = false;
       } while ((_length = readChunkLength(_is)) == 0);
 
       return _length > 0;
@@ -173,27 +180,34 @@ public class Hessian2StreamingInput
       throws IOException
     {
       while (! _isPacketEnd) {
-	if (_length <= 0)
-	  _length = readChunkLength(_is);
+        if (_length <= 0)
+          _length = readChunkLength(_is);
 
-	if (_length > 0)
-	  _is.skip(_length);
+        if (_length > 0) {
+          _is.skip(_length);
+          _length = 0;
+        }
+      }
+      
+      if (_length > 0) {
+        _is.skip(_length);
+        _length = 0;
       }
     }
 
     public int read()
       throws IOException
     {
-      if (_isPacketEnd)
-	throw new IllegalStateException();
-      
       InputStream is = _is;
       
       if (_length == 0) {
-	_length = readChunkLength(is);
+        if (_isPacketEnd)
+          return -1;
+        
+        _length = readChunkLength(is);
 
-	if (_length <= 0)
-	  return -1;
+        if (_length <= 0)
+          return -1;
       }
 
       _length--;
@@ -201,29 +215,30 @@ public class Hessian2StreamingInput
       return is.read();
     }
 
+    @Override
     public int read(byte []buffer, int offset, int length)
       throws IOException
     {
-      if (_isPacketEnd)
-	throw new IllegalStateException();
-      
       InputStream is = _is;
       
       if (_length <= 0) {
-	_length = readChunkLength(is);
+        if (_isPacketEnd)
+          return -1;
+        
+        _length = readChunkLength(is);
 
-	if (_length <= 0)
-	  return -1;
+        if (_length <= 0)
+          return -1;
       }
 
       int sublen = _length;
       if (length < sublen)
-	sublen = length;
-
+        sublen = length;
+      
       sublen = is.read(buffer, offset, sublen);
 
       if (sublen < 0)
-	return -1;
+        return -1;
 
       _length -= sublen;
 
@@ -234,43 +249,40 @@ public class Hessian2StreamingInput
       throws IOException
     {
       if (_isPacketEnd)
-	return -1;
+        return -1;
       
       int length = 0;
-	
+
       int code = is.read();
 
       if (code < 0) {
         _isPacketEnd = true;
         return -1;
       }
-      else if ((code & 0x80) != 0x80) {
-	int len = 256;
-	StringBuilder sb = new StringBuilder();
-	int ch;
-	
-	while ((len-- > 0 && is.available() > 0 && (ch = is.read()) >= 0))
-	  sb.append((char) ch);
-	
-        throw new IllegalStateException("WebSocket binary must begin with a 0x80 packet at 0x" + Integer.toHexString(code)
-                                        + " ("+ (char) code + ")"
-					+ " context[" + sb + "]");
+      
+      _isPacketEnd = (code & 0x80) == 0;
+      
+      int len = is.read() & 0x7f;
+      
+      if (len < 0x7e) {
+        length = len;
+      }
+      else if (len == 0x7e) {
+        length = (((is.read() & 0xff) << 8)
+                  + (is.read() & 0xff));
       }
-
-      while ((code = is.read()) >= 0) {
-	length = (length << 7) + (code & 0x7f);
-
-	if ((code & 0x80) == 0) {
-	  if (length == 0)
-	    _isPacketEnd = true;
-
-	  return length;
-	}
+      else {
+        length = (((is.read() & 0xff) << 56)
+                  + ((is.read() & 0xff) << 48)
+                  + ((is.read() & 0xff) << 40)
+                  + ((is.read() & 0xff) << 32)
+                  + ((is.read() & 0xff) << 24)
+                  + ((is.read() & 0xff) << 16)
+                  + ((is.read() & 0xff) << 8)
+                  + ((is.read() & 0xff)));
       }
 
-      _isPacketEnd = true;
-
-      return -1;
+      return length;
     }
   }
 }
diff --git a/com/caucho/hessian/io/Hessian2StreamingOutput.java b/com/caucho/hessian/io/Hessian2StreamingOutput.java
index 67a1948..8876082 100644
--- a/com/caucho/hessian/io/Hessian2StreamingOutput.java
+++ b/com/caucho/hessian/io/Hessian2StreamingOutput.java
@@ -50,7 +50,6 @@ package com.caucho.hessian.io;
 
 import java.io.IOException;
 import java.io.OutputStream;
-import java.util.HashMap;
 
 /**
  * Output stream for Hessian 2 streaming requests.
diff --git a/com/caucho/hessian/io/HessianDebugInputStream.java b/com/caucho/hessian/io/HessianDebugInputStream.java
index c3d442a..cf28948 100644
--- a/com/caucho/hessian/io/HessianDebugInputStream.java
+++ b/com/caucho/hessian/io/HessianDebugInputStream.java
@@ -95,6 +95,19 @@ public class HessianDebugInputStream extends InputStream
   {
     this(is, new PrintWriter(new LogWriter(log, level)));
   }
+  
+  /**
+   * Creates an uninitialized Hessian input stream.
+   */
+  public HessianDebugInputStream(Logger log, Level level)
+  {
+    this(null, log, level);
+  }
+  
+  public void initPacket(InputStream is)
+  {
+    _is = is;
+  }
 
   public void startTop2()
   {
@@ -166,24 +179,24 @@ public class HessianDebugInputStream extends InputStream
     public void write(char ch)
     {
       if (ch == '\n' && _sb.length() > 0) {
-	_log.log(_level, _sb.toString());
-	_sb.setLength(0);
+        _log.log(_level, _sb.toString());
+        _sb.setLength(0);
       }
       else
-	_sb.append((char) ch);
+        _sb.append((char) ch);
     }
 
     public void write(char []buffer, int offset, int length)
     {
       for (int i = 0; i < length; i++) {
-	char ch = buffer[offset + i];
-	
-	if (ch == '\n' && _sb.length() > 0) {
-	  _log.log(_level, _sb.toString());
-	  _sb.setLength(0);
-	}
-	else
-	  _sb.append((char) ch);
+        char ch = buffer[offset + i];
+
+        if (ch == '\n' && _sb.length() > 0) {
+          _log.log(_level, _sb.toString());
+          _sb.setLength(0);
+        }
+        else
+          _sb.append((char) ch);
       }
     }
 
diff --git a/com/caucho/hessian/io/HessianDebugOutputStream.java b/com/caucho/hessian/io/HessianDebugOutputStream.java
index 7e8ed1b..14cadd0 100644
--- a/com/caucho/hessian/io/HessianDebugOutputStream.java
+++ b/com/caucho/hessian/io/HessianDebugOutputStream.java
@@ -61,6 +61,9 @@ import java.util.logging.Level;
  */
 public class HessianDebugOutputStream extends OutputStream
 {
+  private static final Logger log
+    = Logger.getLogger(HessianDebugOutputStream.class.getName());
+  
   private OutputStream _os;
   
   private HessianDebugState _state;
@@ -82,6 +85,19 @@ public class HessianDebugOutputStream extends OutputStream
   {
     this(os, new PrintWriter(new LogWriter(log, level)));
   }
+  
+  /**
+   * Creates an uninitialized Hessian input stream.
+   */
+  public HessianDebugOutputStream(Logger log, Level level)
+  {
+    this(null, new PrintWriter(new LogWriter(log, level)));
+  }
+  
+  public void initPacket(OutputStream os)
+  {
+    _os = os;
+  }
 
   public void startTop2()
   {
@@ -96,6 +112,7 @@ public class HessianDebugOutputStream extends OutputStream
   /**
    * Writes a character.
    */
+  @Override
   public void write(int ch)
     throws IOException
   {
@@ -103,9 +120,14 @@ public class HessianDebugOutputStream extends OutputStream
     
     _os.write(ch);
 
-    _state.next(ch);
+    try {
+      _state.next(ch);
+    } catch (Exception e) {
+      log.log(Level.WARNING, e.toString(), e);
+    }
   }
 
+  @Override
   public void flush()
     throws IOException
   {
@@ -115,6 +137,7 @@ public class HessianDebugOutputStream extends OutputStream
   /**
    * closes the stream.
    */
+  @Override
   public void close()
     throws IOException
   {
@@ -143,24 +166,24 @@ public class HessianDebugOutputStream extends OutputStream
     public void write(char ch)
     {
       if (ch == '\n' && _sb.length() > 0) {
-	_log.log(_level, _sb.toString());
-	_sb.setLength(0);
+        _log.log(_level, _sb.toString());
+        _sb.setLength(0);
       }
       else
-	_sb.append((char) ch);
+        _sb.append((char) ch);
     }
 
     public void write(char []buffer, int offset, int length)
     {
       for (int i = 0; i < length; i++) {
-	char ch = buffer[offset + i];
-	
-	if (ch == '\n' && _sb.length() > 0) {
-	  _log.log(_level, _sb.toString());
-	  _sb.setLength(0);
-	}
-	else
-	  _sb.append((char) ch);
+        char ch = buffer[offset + i];
+
+        if (ch == '\n' && _sb.length() > 0) {
+          _log.log(_level, _sb.toString());
+          _sb.setLength(0);
+        }
+        else
+          _sb.append((char) ch);
       }
     }
 
diff --git a/com/caucho/hessian/io/HessianDebugState.java b/com/caucho/hessian/io/HessianDebugState.java
index 84dd5dc..c32596c 100644
--- a/com/caucho/hessian/io/HessianDebugState.java
+++ b/com/caucho/hessian/io/HessianDebugState.java
@@ -49,15 +49,18 @@
 package com.caucho.hessian.io;
 
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.logging.Logger;
 
 /**
  * Debugging input stream for Hessian requests.
  */
 public class HessianDebugState implements Hessian2Constants
 {
+  private static final Logger log
+    = Logger.getLogger(HessianDebugState.class.getName());
+  
   private PrintWriter _dbg;
 
   private State _state;
@@ -148,18 +151,18 @@ public class HessianDebugState implements Hessian2Constants
     case 0x04: case 0x05: case 0x06: case 0x07:
     case 0x08: case 0x09: case 0x0a: case 0x0b:
     case 0x0c: case 0x0d: case 0x0e: case 0x0f:
-	
+
     case 0x10: case 0x11: case 0x12: case 0x13:
     case 0x14: case 0x15: case 0x16: case 0x17:
     case 0x18: case 0x19: case 0x1a: case 0x1b:
     case 0x1c: case 0x1d: case 0x1e: case 0x1f:
 
     case 0x30: case 0x31: case 0x32: case 0x33:
-	
+
     case 'R':
     case 'S':
       return true;
-	
+
     default:
       return false;
     }
@@ -231,18 +234,18 @@ public class HessianDebugState implements Hessian2Constants
     int depth()
     {
       if (_next != null)
-	return _next.depth();
+        return _next.depth();
       else
-	return HessianDebugState.this.getDepth();
+        return HessianDebugState.this.getDepth();
     }
 
     void printIndent(int depth)
     {
       if (_isNewline) {
-	for (int i = _column; i < depth() + depth; i++) {
-	  _dbg.print(" ");
-	  _column++;
-	}
+        for (int i = _column; i < depth() + depth; i++) {
+          _dbg.print(" ");
+          _column++;
+        }
       }
     }
 
@@ -261,9 +264,9 @@ public class HessianDebugState implements Hessian2Constants
 
       int p = string.lastIndexOf('\n');
       if (p > 0)
-	_column = string.length() - p - 1;
+        _column = string.length() - p - 1;
       else
-	_column += string.length();
+        _column += string.length();
     }
 
     void println(String string)
@@ -285,8 +288,8 @@ public class HessianDebugState implements Hessian2Constants
     void println()
     {
       if (! _isNewline) {
-	_dbg.println();
-	_dbg.flush();
+        _dbg.println();
+        _dbg.flush();
       }
 
       _isNewline = true;
@@ -297,7 +300,7 @@ public class HessianDebugState implements Hessian2Constants
     void printObject(String string)
     {
       if (_isObject)
-	println();
+        println();
       
       printIndent(0);
 
@@ -314,32 +317,32 @@ public class HessianDebugState implements Hessian2Constants
     {
       switch (ch) {
       case -1:
-	println();
-	return this;
-	
+        println();
+        return this;
+
       case 'N':
-	if (isShift(null))
-	  return shift(null);
-	else {
-	  printObject("null");
-	  return this;
-	}
-	
+        if (isShift(null))
+          return shift(null);
+        else {
+          printObject("null");
+          return this;
+        }
+
       case 'T':
-	if (isShift(Boolean.TRUE))
-	  return shift(Boolean.TRUE);
-	else {
-	  printObject("true");
-	  return this;
-	}
-	
+        if (isShift(Boolean.TRUE))
+          return shift(Boolean.TRUE);
+        else {
+          printObject("true");
+          return this;
+        }
+
       case 'F':
-	if (isShift(Boolean.FALSE))
-	  return shift(Boolean.FALSE);
-	else {
-	  printObject("false");
-	  return this;
-	}
+        if (isShift(Boolean.FALSE))
+          return shift(Boolean.FALSE);
+        else {
+          printObject("false");
+          return this;
+        }
 
       case 0x80: case 0x81: case 0x82: case 0x83: 
       case 0x84: case 0x85: case 0x86: case 0x87: 
@@ -360,195 +363,195 @@ public class HessianDebugState implements Hessian2Constants
       case 0xb4: case 0xb5: case 0xb6: case 0xb7: 
       case 0xb8: case 0xb9: case 0xba: case 0xbb: 
       case 0xbc: case 0xbd: case 0xbe: case 0xbf:
-	{
-	  Integer value = new Integer(ch - 0x90);
-	  
-	  if (isShift(value))
-	    return shift(value);
-	  else {
-	    printObject(value.toString());
-	    return this;
-	  }
-	}
+        {
+          Integer value = new Integer(ch - 0x90);
+
+          if (isShift(value))
+            return shift(value);
+          else {
+            printObject(value.toString());
+            return this;
+          }
+        }
 
       case 0xc0: case 0xc1: case 0xc2: case 0xc3: 
       case 0xc4: case 0xc5: case 0xc6: case 0xc7: 
       case 0xc8: case 0xc9: case 0xca: case 0xcb: 
       case 0xcc: case 0xcd: case 0xce: case 0xcf:
-	return new IntegerState(this, "int", ch - 0xc8, 3);
+        return new IntegerState(this, "int", ch - 0xc8, 3);
 
       case 0xd0: case 0xd1: case 0xd2: case 0xd3: 
       case 0xd4: case 0xd5: case 0xd6: case 0xd7: 
-	return new IntegerState(this, "int", ch - 0xd4, 2);
+        return new IntegerState(this, "int", ch - 0xd4, 2);
 
       case 'I':
-	return new IntegerState(this, "int");
-	
+        return new IntegerState(this, "int");
+
       case 0xd8: case 0xd9: case 0xda: case 0xdb: 
       case 0xdc: case 0xdd: case 0xde: case 0xdf: 
       case 0xe0: case 0xe1: case 0xe2: case 0xe3: 
       case 0xe4: case 0xe5: case 0xe6: case 0xe7: 
       case 0xe8: case 0xe9: case 0xea: case 0xeb: 
       case 0xec: case 0xed: case 0xee: case 0xef:
-	{
-	  Long value = new Long(ch - 0xe0);
-	  
-	  if (isShift(value))
-	    return shift(value);
-	  else {
-	    printObject(value.toString() + "L");
-	    return this;
-	  }
-	}
-	
+        {
+          Long value = new Long(ch - 0xe0);
+
+          if (isShift(value))
+            return shift(value);
+          else {
+            printObject(value.toString() + "L");
+            return this;
+          }
+        }
+
       case 0xf0: case 0xf1: case 0xf2: case 0xf3: 
       case 0xf4: case 0xf5: case 0xf6: case 0xf7: 
       case 0xf8: case 0xf9: case 0xfa: case 0xfb: 
       case 0xfc: case 0xfd: case 0xfe: case 0xff:
-	return new LongState(this, "long", ch - 0xf8, 7);
-	
+        return new LongState(this, "long", ch - 0xf8, 7);
+
       case 0x38: case 0x39: case 0x3a: case 0x3b: 
       case 0x3c: case 0x3d: case 0x3e: case 0x3f:
-	return new LongState(this, "long", ch - 0x3c, 6);
+        return new LongState(this, "long", ch - 0x3c, 6);
 
       case BC_LONG_INT:
-	return new LongState(this, "long", 0, 4);
+        return new LongState(this, "long", 0, 4);
 
       case 'L':
-	return new LongState(this, "long");
+        return new LongState(this, "long");
 
       case 0x5b: case 0x5c:
-	{
-	  Double value = new Double(ch - 0x5b);
-	  
-	  if (isShift(value))
-	    return shift(value);
-	  else {
-	    printObject(value.toString());
-	    return this;
-	  }
-	}
+        {
+          Double value = new Double(ch - 0x5b);
+
+          if (isShift(value))
+            return shift(value);
+          else {
+            printObject(value.toString());
+            return this;
+          }
+        }
 
       case 0x5d:
-	return new DoubleIntegerState(this, 3);
+        return new DoubleIntegerState(this, 3);
 
       case 0x5e:
-	return new DoubleIntegerState(this, 2);
+        return new DoubleIntegerState(this, 2);
 
       case 0x5f:
-	return new MillsState(this);
-	
+        return new MillsState(this);
+
       case 'D':
-	return new DoubleState(this);
+        return new DoubleState(this);
 
       case 'Q':
-	return new RefState(this);
+        return new RefState(this);
 
       case BC_DATE:
-	return new DateState(this);
+        return new DateState(this);
 
       case BC_DATE_MINUTE:
-	return new DateState(this, true);
+        return new DateState(this, true);
 
       case 0x00:
-	{
-	  String value = "\"\"";
-	  
-	  if (isShift(value))
-	    return shift(value);
-	  else {
-	    printObject(value.toString());
-	    return this;
-	  }
-	}
+        {
+          String value = "\"\"";
+
+          if (isShift(value))
+            return shift(value);
+          else {
+            printObject(value.toString());
+            return this;
+          }
+        }
 
       case 0x01: case 0x02: case 0x03:
       case 0x04: case 0x05: case 0x06: case 0x07:
       case 0x08: case 0x09: case 0x0a: case 0x0b:
       case 0x0c: case 0x0d: case 0x0e: case 0x0f:
-	
+
       case 0x10: case 0x11: case 0x12: case 0x13:
       case 0x14: case 0x15: case 0x16: case 0x17:
       case 0x18: case 0x19: case 0x1a: case 0x1b:
       case 0x1c: case 0x1d: case 0x1e: case 0x1f:
-	return new StringState(this, 'S', ch);
+        return new StringState(this, 'S', ch);
 
       case 0x30: case 0x31: case 0x32: case 0x33:
-	return new StringState(this, 'S', ch - 0x30, true);
-	
+        return new StringState(this, 'S', ch - 0x30, true);
+
       case 'R':
-	return new StringState(this, 'S', false);
+        return new StringState(this, 'S', false);
 
       case 'S':
-	return new StringState(this, 'S', true);
+        return new StringState(this, 'S', true);
 
       case 0x20:
-	{
-	  String value = "binary(0)";
-	  
-	  if (isShift(value))
-	    return shift(value);
-	  else {
-	    printObject(value.toString());
-	    return this;
-	  }
-	}
+        {
+          String value = "binary(0)";
+
+          if (isShift(value))
+            return shift(value);
+          else {
+            printObject(value.toString());
+            return this;
+          }
+        }
 
       case 0x21: case 0x22: case 0x23:
       case 0x24: case 0x25: case 0x26: case 0x27:
       case 0x28: case 0x29: case 0x2a: case 0x2b:
       case 0x2c: case 0x2d: case 0x2e: case 0x2f:
-	return new BinaryState(this, 'B', ch - 0x20);
-	
+        return new BinaryState(this, 'B', ch - 0x20);
+
       case 0x34: case 0x35: case 0x36: case 0x37:
-	return new BinaryState(this, 'B', ch - 0x34, true);
+        return new BinaryState(this, 'B', ch - 0x34, true);
 
       case 'A':
-	return new BinaryState(this, 'B', false);
+        return new BinaryState(this, 'B', false);
 
       case 'B':
-	return new BinaryState(this, 'B', true);
+        return new BinaryState(this, 'B', true);
 
       case 'M':
-	return new MapState(this, _refId++);
+        return new MapState(this, _refId++);
 
       case 'H':
-	return new MapState(this, _refId++, false);
+        return new MapState(this, _refId++, false);
 
       case BC_LIST_VARIABLE:
-	return new ListState(this, _refId++, true);
+        return new ListState(this, _refId++, true);
 
       case BC_LIST_VARIABLE_UNTYPED:
-	return new ListState(this, _refId++, false);
+        return new ListState(this, _refId++, false);
 
       case BC_LIST_FIXED:
-	return new CompactListState(this, _refId++, true);
-	
+        return new CompactListState(this, _refId++, true);
+
       case BC_LIST_FIXED_UNTYPED:
-	return new CompactListState(this, _refId++, false);
+        return new CompactListState(this, _refId++, false);
 
       case 0x70: case 0x71: case 0x72: case 0x73:
       case 0x74: case 0x75: case 0x76: case 0x77:
-	return new CompactListState(this, _refId++, true, ch - 0x70);
+        return new CompactListState(this, _refId++, true, ch - 0x70);
 
       case 0x78: case 0x79: case 0x7a: case 0x7b:
       case 0x7c: case 0x7d: case 0x7e: case 0x7f:
-	return new CompactListState(this, _refId++, false, ch - 0x78);
+        return new CompactListState(this, _refId++, false, ch - 0x78);
 
       case 'C':
-	return new ObjectDefState(this);
+        return new ObjectDefState(this);
 
       case 0x60: case 0x61: case 0x62: case 0x63:
       case 0x64: case 0x65: case 0x66: case 0x67:
       case 0x68: case 0x69: case 0x6a: case 0x6b:
       case 0x6c: case 0x6d: case 0x6e: case 0x6f:
-	return new ObjectState(this, _refId++, ch - 0x60);
-	
+        return new ObjectState(this, _refId++, ch - 0x60);
+
       case 'O':
-	return new ObjectState(this, _refId++);
-	
+        return new ObjectState(this, _refId++);
+
       default:
-	return this;
+        return this;
       }
     }
   }
@@ -567,72 +570,73 @@ public class HessianDebugState implements Hessian2Constants
     {
       switch (ch) {
       case -1:
-	println();
-	return this;
-	
+        println();
+        return this;
+
       case 'N':
-	if (isShift(null))
-	  return shift(null);
-	else {
-	  printObject("null");
-	  return this;
-	}
-	
+        if (isShift(null))
+          return shift(null);
+        else {
+          printObject("null");
+          return this;
+        }
+
       case 'T':
-	if (isShift(Boolean.TRUE))
-	  return shift(Boolean.TRUE);
-	else {
-	  printObject("true");
-	  return this;
-	}
-	
+        if (isShift(Boolean.TRUE))
+          return shift(Boolean.TRUE);
+        else {
+          printObject("true");
+          return this;
+        }
+
       case 'F':
-	if (isShift(Boolean.FALSE))
-	  return shift(Boolean.FALSE);
-	else {
-	  printObject("false");
-	  return this;
-	}
+        if (isShift(Boolean.FALSE))
+          return shift(Boolean.FALSE);
+        else {
+          printObject("false");
+          return this;
+        }
 
       case 'I':
-	return new IntegerState(this, "int");
+        return new IntegerState(this, "int");
 
       case 'L':
-	return new LongState(this, "long");
-	
+        return new LongState(this, "long");
+
       case 'D':
-	return new DoubleState(this);
+        return new DoubleState(this);
 
       case 'Q':
-	return new RefState(this);
+        return new RefState(this);
 
       case 'd':
-	return new DateState(this);
-	
+        return new DateState(this);
+
       case 's':
-	return new StringState(this, 'S', false);
+        return new StringState(this, 'S', false);
 
       case 'S':
-	return new StringState(this, 'S', true);
+        return new StringState(this, 'S', true);
 
       case 'b':
-	return new BinaryState(this, 'B', false);
+      case 'A':
+        return new BinaryState(this, 'B', false);
 
       case 'B':
-	return new BinaryState(this, 'B', true);
+        return new BinaryState(this, 'B', true);
 
       case 'M':
-	return new MapState1(this, _refId++);
+        return new MapState1(this, _refId++);
 
       case 'V':
-	return new ListState1(this, _refId++);
+        return new ListState1(this, _refId++);
 
       case 'R':
-	return new IntegerState(new RefState1(this), "ref");
-	
+        return new IntegerState(new RefState1(this), "ref");
+
       default:
-	printObject("x" + String.format("%02x", ch));
-	return this;
+        printObject("x" + String.format("%02x", ch));
+        return this;
       }
     }
   }
@@ -657,13 +661,13 @@ public class HessianDebugState implements Hessian2Constants
       println();
       
       if (ch == 'r') {
-	return new ReplyState1(this);
+        return new ReplyState1(this);
       }
       else if (ch == 'c') {
-	return new CallState1(this);
+        return new CallState1(this);
       }
       else
-	return nextObject(ch);
+        return nextObject(ch);
     }
   }
   
@@ -673,25 +677,25 @@ public class HessianDebugState implements Hessian2Constants
       println();
       
       if (ch == 'R') {
-	return new Reply2State(this);
+        return new Reply2State(this);
       }
       else if (ch == 'F') {
-	return new Fault2State(this);
+        return new Fault2State(this);
       }
       else if (ch == 'C') {
-	return new Call2State(this);
+        return new Call2State(this);
       }
       else if (ch == 'H') {
-	return new Hessian2State(this);
+        return new Hessian2State(this);
       }
       else if (ch == 'r') {
-	return new ReplyState1(this);
+        return new ReplyState1(this);
       }
       else if (ch == 'c') {
-	return new CallState1(this);
+        return new CallState1(this);
       }
       else
-	return nextObject(ch);
+        return nextObject(ch);
     }
   }
   
@@ -723,18 +727,18 @@ public class HessianDebugState implements Hessian2Constants
       _value = 256 * _value + (ch & 0xff);
 
       if (++_length == 4) {
-	Integer value = new Integer(_value);
-	
-	if (_next.isShift(value))
-	  return _next.shift(value);
-	else {
-	  printObject(value.toString());
-	  
-	  return _next;
-	}
+        Integer value = new Integer(_value);
+
+        if (_next.isShift(value))
+          return _next.shift(value);
+        else {
+          printObject(value.toString());
+
+          return _next;
+        }
       }
       else
-	return this;
+        return this;
     }
   }
   
@@ -766,18 +770,18 @@ public class HessianDebugState implements Hessian2Constants
       _value = 256 * _value + (ch & 0xff);
 
       if (++_length == 8) {
-	Long value = new Long(_value);
-	
-	if (_next.isShift(value))
-	  return _next.shift(value);
-	else {
-	  printObject(value.toString() + "L");
-	  
-	  return _next;
-	}
+        Long value = new Long(_value);
+
+        if (_next.isShift(value))
+          return _next.shift(value);
+        else {
+          printObject(value.toString() + "L");
+
+          return _next;
+        }
       }
       else
-	return this;
+        return this;
     }
   }
   
@@ -796,25 +800,25 @@ public class HessianDebugState implements Hessian2Constants
     State next(int ch)
     {
       if (_isFirst)
-	_value = (byte) ch;
+        _value = (byte) ch;
       else
-	_value = 256 * _value + (ch & 0xff);
+        _value = 256 * _value + (ch & 0xff);
 
       _isFirst = false;
 
       if (++_length == 4) {
-	Double value = new Double(_value);
-	
-	if (_next.isShift(value))
-	  return _next.shift(value);
-	else {
-	  printObject(value.toString());
-	  
-	  return _next;
-	}
+        Double value = new Double(_value);
+
+        if (_next.isShift(value))
+          return _next.shift(value);
+        else {
+          printObject(value.toString());
+
+          return _next;
+        }
       }
       else
-	return this;
+        return this;
     }
   }
   
@@ -920,23 +924,23 @@ public class HessianDebugState implements Hessian2Constants
       _value = 256 * _value + (ch & 0xff);
 
       if (++_length == 8) {
-	java.util.Date value;
+        java.util.Date value;
 
-	if (_isMinute)
-	  value = new java.util.Date(_value * 60000L);
-	else
-	  value = new java.util.Date(_value);
+        if (_isMinute)
+          value = new java.util.Date(_value * 60000L);
+        else
+          value = new java.util.Date(_value);
 
-	if (_next.isShift(value))
-	  return _next.shift(value);
-	else {
-	  printObject(value.toString());
-	  
-	  return _next;
-	}
+        if (_next.isShift(value))
+          return _next.shift(value);
+        else {
+          printObject(value.toString());
+
+          return _next;
+        }
       }
       else
-	return this;
+        return this;
     }
   }
   
@@ -954,18 +958,18 @@ public class HessianDebugState implements Hessian2Constants
       _value = 256 * _value + (ch & 0xff);
 
       if (++_length == 8) {
-	Double value = Double.longBitsToDouble(_value);
+        Double value = Double.longBitsToDouble(_value);
+
+        if (_next.isShift(value))
+          return _next.shift(value);
+        else {
+          printObject(value.toString());
 
-	if (_next.isShift(value))
-	  return _next.shift(value);
-	else {
-	  printObject(value.toString());
-	  
-	  return _next;
-	}
+          return _next;
+        }
       }
       else
-	return this;
+        return this;
     }
   }
   
@@ -983,18 +987,18 @@ public class HessianDebugState implements Hessian2Constants
       _value = 256 * _value + (ch & 0xff);
 
       if (++_length == 4) {
-	Double value = 0.001 * _value;
+        Double value = 0.001 * _value;
+
+        if (_next.isShift(value))
+          return _next.shift(value);
+        else {
+          printObject(value.toString());
 
-	if (_next.isShift(value))
-	  return _next.shift(value);
-	else {
-	  printObject(value.toString());
-	  
-	  return _next;
-	}
+          return _next;
+        }
       }
       else
-	return this;
+        return this;
     }
   }
   
@@ -1045,98 +1049,98 @@ public class HessianDebugState implements Hessian2Constants
     State next(int ch)
     {
       if (_lengthIndex < 2) {
-	_length = 256 * _length + (ch & 0xff);
-	
-	if (++_lengthIndex == 2 && _length == 0 && _isLastChunk) {
-	  if (_next.isShift(_value.toString()))
-	    return _next.shift(_value.toString());
-	  else {
-	    printObject("\"" + _value + "\"");
-	    return _next;
-	  }
-	}
-	else
-	  return this;
+        _length = 256 * _length + (ch & 0xff);
+
+        if (++_lengthIndex == 2 && _length == 0 && _isLastChunk) {
+          if (_next.isShift(_value.toString()))
+            return _next.shift(_value.toString());
+          else {
+            printObject("\"" + _value + "\"");
+            return _next;
+          }
+        }
+        else
+          return this;
       }
       else if (_length == 0) {
-	if (ch == 's' || ch == 'x') {
-	  _isLastChunk = false;
-	  _lengthIndex = 0;
-	  return this;
-	}
-	else if (ch == 'S' || ch == 'X') {
-	  _isLastChunk = true;
-	  _lengthIndex = 0;
-	  return this;
-	}
-	else if (ch == 0x00) {
-	  if (_next.isShift(_value.toString()))
-	    return _next.shift(_value.toString());
-	  else {
-	    printObject("\"" + _value + "\"");
-	    return _next;
-	  }
-	}
-	else if (0x00 <= ch && ch < 0x20) {
-	  _isLastChunk = true;
-	  _lengthIndex = 2;
-	  _length = ch & 0xff;
-	  return this;
-	}
-	else if (0x30 <= ch && ch < 0x34) {
-	  _isLastChunk = true;
-	  _lengthIndex = 1;
-	  _length = (ch - 0x30);
-	  return this;
-	}
-	else {
-	  println(String.valueOf((char) ch) + ": unexpected character");
-	  return _next;
-	}
+        if (ch == 's' || ch == 'x') {
+          _isLastChunk = false;
+          _lengthIndex = 0;
+          return this;
+        }
+        else if (ch == 'S' || ch == 'X') {
+          _isLastChunk = true;
+          _lengthIndex = 0;
+          return this;
+        }
+        else if (ch == 0x00) {
+          if (_next.isShift(_value.toString()))
+            return _next.shift(_value.toString());
+          else {
+            printObject("\"" + _value + "\"");
+            return _next;
+          }
+        }
+        else if (0x00 <= ch && ch < 0x20) {
+          _isLastChunk = true;
+          _lengthIndex = 2;
+          _length = ch & 0xff;
+          return this;
+        }
+        else if (0x30 <= ch && ch < 0x34) {
+          _isLastChunk = true;
+          _lengthIndex = 1;
+          _length = (ch - 0x30);
+          return this;
+        }
+        else {
+          println(this + " " + String.valueOf((char) ch) + ": unexpected character");
+          return _next;
+        }
       }
 
       switch (_utfState) {
       case TOP:
-	if (ch < 0x80) {
-	  _length--;
-
-	  _value.append((char) ch);
-	}
-	else if (ch < 0xe0) {
-	  _ch = (char) ((ch & 0x1f) << 6);
-	  _utfState = UTF_2_1;
-	}
-	else {
-	  _ch = (char) ((ch & 0xf) << 12);
-	  _utfState = UTF_3_1;
-	}
-	break;
+        if (ch < 0x80) {
+          _length--;
+
+          _value.append((char) ch);
+        }
+        else if (ch < 0xe0) {
+          _ch = (char) ((ch & 0x1f) << 6);
+          _utfState = UTF_2_1;
+        }
+        else {
+          _ch = (char) ((ch & 0xf) << 12);
+          _utfState = UTF_3_1;
+        }
+        break;
 
       case UTF_2_1:
       case UTF_3_2:
-	_ch += ch & 0x3f;
-	_value.append(_ch);
-	_length--;
-	_utfState = TOP;
-	break;
+        _ch += ch & 0x3f;
+        _value.append(_ch);
+        _length--;
+        _utfState = TOP;
+        break;
 
       case UTF_3_1:
-	_ch += (char) ((ch & 0x3f) << 6);
-	_utfState = UTF_3_2;
-	break;
+        _ch += (char) ((ch & 0x3f) << 6);
+        _utfState = UTF_3_2;
+        break;
       }
 
       if (_length == 0 && _isLastChunk) {
-	if (_next.isShift(_value.toString()))
-	  return _next.shift(_value.toString());
-	else {
-	  printObject("\"" + _value + "\"");
-	  
-	  return _next;
-	}
+        if (_next.isShift(_value.toString()))
+          return _next.shift(_value.toString());
+        else {
+          printObject("\"" + _value + "\"");
+
+          return _next;
+        }
       }
       else
-	return this;
+        return this;
     }
   }
   
@@ -1177,73 +1181,74 @@ public class HessianDebugState implements Hessian2Constants
       _lengthIndex = 1;
     }
     
+    @Override
     State next(int ch)
     {
       if (_lengthIndex < 2) {
-	_length = 256 * _length + (ch & 0xff);
-	
-	if (++_lengthIndex == 2 && _length == 0 && _isLastChunk) {
-	  String value = "binary(" + _totalLength + ")";
-	  
-	  if (_next.isShift(value))
-	    return _next.shift(value);
-	  else {
-	    printObject(value);
-	    return _next;
-	  }
-	}
-	else
-	  return this;
+        _length = 256 * _length + (ch & 0xff);
+
+        if (++_lengthIndex == 2 && _length == 0 && _isLastChunk) {
+          String value = "binary(" + _totalLength + ")";
+
+          if (_next.isShift(value))
+            return _next.shift(value);
+          else {
+            printObject(value);
+            return _next;
+          }
+        }
+        else
+          return this;
       }
       else if (_length == 0) {
-	if (ch == 'b') {
-	  _isLastChunk = false;
-	  _lengthIndex = 0;
-	  return this;
-	}
-	else if (ch == 'B') {
-	  _isLastChunk = true;
-	  _lengthIndex = 0;
-	  return this;
-	}
-	else if (ch == 0x20) {
-	  String value = "binary(" + _totalLength + ")";
-	  
-	  if (_next.isShift(value))
-	    return _next.shift(value);
-	  else {
-	    printObject(value);
-	    return _next;
-	  }
-	}
-	else if (0x20 <=ch && ch < 0x30) {
-	  _isLastChunk = true;
-	  _lengthIndex = 2;
-	  _length = (ch & 0xff) - 0x20;
-	  return this;
-	}
-	else {
-	  println(String.valueOf((char) ch) + ": unexpected character");
-	  return _next;
-	}
+        if (ch == 'b' || ch == 'A') {
+          _isLastChunk = false;
+          _lengthIndex = 0;
+          return this;
+        }
+        else if (ch == 'B') {
+          _isLastChunk = true;
+          _lengthIndex = 0;
+          return this;
+        }
+        else if (ch == 0x20) {
+          String value = "binary(" + _totalLength + ")";
+
+          if (_next.isShift(value))
+            return _next.shift(value);
+          else {
+            printObject(value);
+            return _next;
+          }
+        }
+        else if (0x20 <= ch && ch < 0x30) {
+          _isLastChunk = true;
+          _lengthIndex = 2;
+          _length = (ch & 0xff) - 0x20;
+          return this;
+        }
+        else {
+          println(this + " 0x" + Integer.toHexString(ch) + " " + String.valueOf((char) ch) + ": unexpected character");
+          return _next;
+        }
       }
       
       _length--;
       _totalLength++;
 
       if (_length == 0 && _isLastChunk) {
-	String value = "binary(" + _totalLength + ")";
-	
-	if (_next.isShift(value))
-	  return _next.shift(value);
-	else {
-	  printObject(value);
-	  
-	  return _next;
-	}
+        String value = "binary(" + _totalLength + ")";
+
+        if (_next.isShift(value))
+          return _next.shift(value);
+        else {
+          printObject(value);
+
+          return _next;
+        }
       }
       else
-	return this;
+        return this;
     }
   }
   
@@ -1273,10 +1278,10 @@ public class HessianDebugState implements Hessian2Constants
       _refId = refId;
 
       if (isType)
-	_state = TYPE;
+        _state = TYPE;
       else {
-	printObject("map (#" + _refId + ")");
-	_state = VALUE;
+        printObject("map (#" + _refId + ")");
+        _state = VALUE;
       }
     }
 
@@ -1290,71 +1295,74 @@ public class HessianDebugState implements Hessian2Constants
     State shift(Object type)
     {
       if (_state == TYPE) {
-	if (type instanceof String) {
-	  _typeDefList.add((String) type);
-	}
-	else if (type instanceof Integer) {
-	  int iValue = (Integer) type;
-
-	  if (iValue >= 0 && iValue < _typeDefList.size())
-	    type = _typeDefList.get(iValue);
-	}
-	
-	printObject("map " + type + " (#" + _refId + ")");
-
-	_state = VALUE;
+        if (type instanceof String) {
+          _typeDefList.add((String) type);
+        }
+        else if (type instanceof Integer) {
+          int iValue = (Integer) type;
+
+          if (iValue >= 0 && iValue < _typeDefList.size())
+            type = _typeDefList.get(iValue);
+        }
+
+        printObject("map " + type + " (#" + _refId + ")");
+
+        _state = VALUE;
       
-	return this;
+        return this;
+      }
+      else {
+        printObject(this + " unknown shift state= " + _state + " type=" + type);
+        
+        return this;
       }
-      else
-	throw new IllegalStateException();
     }
 
     @Override
     int depth()
     {
       if (_state == TYPE)
-	return _next.depth();
+        return _next.depth();
       else if (_state == KEY)
-	return _next.depth() + 2;
+        return _next.depth() + 2;
       else
-	return _valueDepth;
+        return _valueDepth;
     }
     
     State next(int ch)
     {
       switch (_state) {
       case TYPE:
-	return nextObject(ch);
-	
+        return nextObject(ch);
+
       case VALUE:
-	if (ch == 'Z') {
-	  if (_hasData)
-	    println();
-	  
-	  return _next;
-	}
-	else {
-	  if (_hasData)
-	    println();
-
-	  _hasData = true;
-	  _state = KEY;
-	  
-	  return nextObject(ch);
-	}
-	
+        if (ch == 'Z') {
+          if (_hasData)
+            println();
+
+          return _next;
+        }
+        else {
+          if (_hasData)
+            println();
+
+          _hasData = true;
+          _state = KEY;
+
+          return nextObject(ch);
+        }
+
       case KEY:
-	print(" => ");
-	_isObject = false;
-	_valueDepth = _column;
+        print(" => ");
+        _isObject = false;
+        _valueDepth = _column;
 
-	_state = VALUE;
-	
-	return nextObject(ch);
+        _state = VALUE;
+
+        return nextObject(ch);
 
       default:
-	throw new IllegalStateException();
+        throw new IllegalStateException();
       }
     }
   }
@@ -1385,10 +1393,10 @@ public class HessianDebugState implements Hessian2Constants
       _refId = refId;
 
       if (isType)
-	_state = TYPE;
+        _state = TYPE;
       else {
-	printObject("map (#" + _refId + ")");
-	_state = VALUE;
+        printObject("map (#" + _refId + ")");
+        _state = VALUE;
       }
     }
 
@@ -1402,83 +1410,83 @@ public class HessianDebugState implements Hessian2Constants
     State shift(Object type)
     {
       if (_state == TYPE) {
-	if (type instanceof String) {
-	  _typeDefList.add((String) type);
-	}
-	else if (type instanceof Integer) {
-	  int iValue = (Integer) type;
-
-	  if (iValue >= 0 && iValue < _typeDefList.size())
-	    type = _typeDefList.get(iValue);
-	}
-	
-	printObject("map " + type + " (#" + _refId + ")");
-
-	_state = VALUE;
+        if (type instanceof String) {
+          _typeDefList.add((String) type);
+        }
+        else if (type instanceof Integer) {
+          int iValue = (Integer) type;
+
+          if (iValue >= 0 && iValue < _typeDefList.size())
+            type = _typeDefList.get(iValue);
+        }
+
+        printObject("map " + type + " (#" + _refId + ")");
+
+        _state = VALUE;
       
-	return this;
+        return this;
       }
       else
-	throw new IllegalStateException();
+        throw new IllegalStateException();
     }
 
     @Override
     int depth()
     {
       if (_state == TYPE)
-	return _next.depth();
+        return _next.depth();
       else if (_state == KEY)
-	return _next.depth() + 2;
+        return _next.depth() + 2;
       else
-	return _valueDepth;
+        return _valueDepth;
     }
     
     State next(int ch)
     {
       switch (_state) {
       case TYPE:
-	if (ch == 't') {
-	  return new StringState(this, 't', true);
-	}
-	else if (ch == 'z') {
-	  println("map (#" + _refId + ")");
-	  return _next;
-	}
-	else {
-	  println("map (#" + _refId + ")");
-	  _hasData = true;
-	  _state = KEY;
-	  return nextObject(ch);
-	}
-	
+        if (ch == 't') {
+          return new StringState(this, 't', true);
+        }
+        else if (ch == 'z') {
+          println("map (#" + _refId + ")");
+          return _next;
+        }
+        else {
+          println("map (#" + _refId + ")");
+          _hasData = true;
+          _state = KEY;
+          return nextObject(ch);
+        }
+
       case VALUE:
-	if (ch == 'z') {
-	  if (_hasData)
-	    println();
-	  
-	  return _next;
-	}
-	else {
-	  if (_hasData)
-	    println();
-
-	  _hasData = true;
-	  _state = KEY;
-	  
-	  return nextObject(ch);
-	}
-	
+        if (ch == 'z') {
+          if (_hasData)
+            println();
+
+          return _next;
+        }
+        else {
+          if (_hasData)
+            println();
+
+          _hasData = true;
+          _state = KEY;
+
+          return nextObject(ch);
+        }
+
       case KEY:
-	print(" => ");
-	_isObject = false;
-	_valueDepth = _column;
+        print(" => ");
+        _isObject = false;
+        _valueDepth = _column;
 
-	_state = VALUE;
-	
-	return nextObject(ch);
+        _state = VALUE;
+
+        return nextObject(ch);
 
       default:
-	throw new IllegalStateException();
+        throw new IllegalStateException();
       }
     }
   }
@@ -1489,10 +1497,7 @@ public class HessianDebugState implements Hessian2Constants
     private static final int FIELD = 3;
     private static final int COMPLETE = 4;
 
-    private int _refId;
-
     private int _state;
-    private boolean _hasData;
     private int _count;
 
     private String _type;
@@ -1515,33 +1520,33 @@ public class HessianDebugState implements Hessian2Constants
     State shift(Object object)
     {
       if (_state == TYPE) {
-	_type = (String) object;
+        _type = (String) object;
 
-	print("/* defun " + _type + " [");
+        print("/* defun " + _type + " [");
 
-	_objectDefList.add(new ObjectDef(_type, _fields));
+        _objectDefList.add(new ObjectDef(_type, _fields));
 
-	_state = COUNT;
+        _state = COUNT;
       }
       else if (_state == COUNT) {
-	_count = (Integer) object;
+        _count = (Integer) object;
 
-	_state = FIELD;
+        _state = FIELD;
       }
       else if (_state == FIELD) {
-	String field = (String) object;
+        String field = (String) object;
 
-	_count--;
+        _count--;
 
-	_fields.add(field);
+        _fields.add(field);
 
-	if (_fields.size() == 1)
-	  print(field);
-	else
-	  print(", " + field);
+        if (_fields.size() == 1)
+          print(field);
+        else
+          print(", " + field);
       }
       else {
-	throw new UnsupportedOperationException();
+        throw new UnsupportedOperationException();
       }
 
       return this;
@@ -1551,32 +1556,32 @@ public class HessianDebugState implements Hessian2Constants
     int depth()
     {
       if (_state <= TYPE)
-	return _next.depth();
+        return _next.depth();
       else
-	return _next.depth() + 2;
+        return _next.depth() + 2;
     }
     
     State next(int ch)
     {
       switch (_state) {
       case TYPE:
-	return nextObject(ch);
-	
+        return nextObject(ch);
+
       case COUNT:
-	return nextObject(ch);
-	
+        return nextObject(ch);
+
       case FIELD:
-	if (_count == 0) {
-	  println("] */");
-	  _next.printIndent(0);
+        if (_count == 0) {
+          println("] */");
+          _next.printIndent(0);
 
-	  return _next.nextObject(ch);
-	}
-	else
-	  return nextObject(ch);
+          return _next.nextObject(ch);
+        }
+        else
+          return nextObject(ch);
 
       default:
-	throw new IllegalStateException();
+        throw new IllegalStateException();
       }
     }
   }
@@ -1608,10 +1613,15 @@ public class HessianDebugState implements Hessian2Constants
       _state = FIELD;
 
       if (def < 0 || _objectDefList.size() <= def) {
-	throw new IllegalStateException(def + " is an unknown object type");
+        log.warning(this + " " + def + " is an unknown object type");
+        
+        println(this + " object unknown  (#" + _refId + ")");
       }
 
       _def = _objectDefList.get(def);
+      
+      if (_isObject)
+        println();
 
       println("object " + _def.getType() + " (#" + _refId + ")");
     }
@@ -1620,25 +1630,25 @@ public class HessianDebugState implements Hessian2Constants
     boolean isShift(Object value)
     {
       if (_state == TYPE)
-	return true;
+        return true;
       else
-	return false;
+        return false;
     }
 
     @Override
     State shift(Object object)
     {
       if (_state == TYPE) {
-	int def = (Integer) object;
+        int def = (Integer) object;
 
-	_def = _objectDefList.get(def);
+        _def = _objectDefList.get(def);
 
-	println("object " + _def.getType() + " (#" + _refId + ")");
+        println("object " + _def.getType() + " (#" + _refId + ")");
 
-	_state = FIELD;
+        _state = FIELD;
 
-	if (_def.getFields().size() == 0)
-	  return _next;
+        if (_def.getFields().size() == 0)
+          return _next;
       }
 
       return this;
@@ -1648,32 +1658,32 @@ public class HessianDebugState implements Hessian2Constants
     int depth()
     {
       if (_state <= TYPE)
-	return _next.depth();
+        return _next.depth();
       else
-	return _fieldDepth;
+        return _fieldDepth;
     }
     
     State next(int ch)
     {
       switch (_state) {
       case TYPE:
-	return nextObject(ch);
-	
+        return nextObject(ch);
+
       case FIELD:
-	if (_def.getFields().size() <= _count)
-	  return _next.next(ch);
+        if (_def.getFields().size() <= _count)
+          return _next.next(ch);
 
-	_fieldDepth = _next.depth() + 2;
-	println();
-	print(_def.getFields().get(_count++) + ": ");
+        _fieldDepth = _next.depth() + 2;
+        println();
+        print(_def.getFields().get(_count++) + ": ");
 
-	_fieldDepth = _column;
+        _fieldDepth = _column;
 
-	_isObject = false;
-	return nextObject(ch);
+        _isObject = false;
+        return nextObject(ch);
 
       default:
-	throw new IllegalStateException();
+        throw new IllegalStateException();
       }
     }
   }
@@ -1686,7 +1696,6 @@ public class HessianDebugState implements Hessian2Constants
     private int _refId;
 
     private int _state;
-    private boolean _hasData;
     private int _count;
     private int _valueDepth;
 
@@ -1709,87 +1718,87 @@ public class HessianDebugState implements Hessian2Constants
     State shift(Object object)
     {
       if (_state == TYPE) {
-	Object type = object;
-	
-	if (type instanceof String) {
-	  _typeDefList.add((String) type);
-	}
-	else if (object instanceof Integer) {
-	  int index = (Integer) object;
-
-	  if (index >= 0 && index < _typeDefList.size())
-	    type = _typeDefList.get(index);
-	  else
-	    type = "type-unknown(" + index + ")";
-	}
-	
-	printObject("list " + type + "(#" + _refId + ")");
+        Object type = object;
+
+        if (type instanceof String) {
+          _typeDefList.add((String) type);
+        }
+        else if (object instanceof Integer) {
+          int index = (Integer) object;
+
+          if (index >= 0 && index < _typeDefList.size())
+            type = _typeDefList.get(index);
+          else
+            type = "type-unknown(" + index + ")";
+        }
+
+        printObject("list " + type + "(#" + _refId + ")");
       
-	_state = VALUE;
+        _state = VALUE;
       
-	return this;
+        return this;
       }
       else if (_state == LENGTH) {
-	_state = VALUE;
+        _state = VALUE;
 
-	return this;
+        return this;
       }
       else
-	return this;
+        return this;
     }
 
     @Override
     int depth()
     {
       if (_state <= LENGTH)
-	return _next.depth();
+        return _next.depth();
       else if (_state == VALUE)
-	return _valueDepth;
+        return _valueDepth;
       else
-	return _next.depth() + 2;
+        return _next.depth() + 2;
     }
     
     State next(int ch)
     {
       switch (_state) {
       case TYPE:
-	if (ch == 'z') {
-	  printObject("list (#" + _refId + ")");
-	  
-	  return _next;
-	}
-	else if (ch == 't') {
-	  return new StringState(this, 't', true);
-	}
-	else {
-	  printObject("list (#" + _refId + ")");
-	  printObject("  " + _count++ + ": ");
-	  _valueDepth = _column;
-	  _isObject = false;
-	  _state = VALUE;
-	  
-	  return nextObject(ch);
-	}
-	
+        if (ch == 'z') {
+          printObject("list (#" + _refId + ")");
+
+          return _next;
+        }
+        else if (ch == 't') {
+          return new StringState(this, 't', true);
+        }
+        else {
+          printObject("list (#" + _refId + ")");
+          printObject("  " + _count++ + ": ");
+          _valueDepth = _column;
+          _isObject = false;
+          _state = VALUE;
+
+          return nextObject(ch);
+        }
+
       case VALUE:
-	if (ch == 'z') {
-	  if (_count > 0)
-	    println();
-	  
-	  return _next;
-	}
-	else {
-	  _valueDepth = _next.depth() + 2;
-	  println();
-	  printObject(_count++ + ": ");
-	  _valueDepth = _column;
-	  _isObject = false;
-	  
-	  return nextObject(ch);
-	}
+        if (ch == 'z') {
+          if (_count > 0)
+            println();
+
+          return _next;
+        }
+        else {
+          _valueDepth = _next.depth() + 2;
+          println();
+          printObject(_count++ + ": ");
+          _valueDepth = _column;
+          _isObject = false;
+
+          return nextObject(ch);
+        }
 
       default:
-	throw new IllegalStateException();
+        throw new IllegalStateException();
       }
     }
   }
@@ -1802,7 +1811,6 @@ public class HessianDebugState implements Hessian2Constants
     private int _refId;
 
     private int _state;
-    private boolean _hasData;
     private int _count;
     private int _valueDepth;
 
@@ -1813,10 +1821,10 @@ public class HessianDebugState implements Hessian2Constants
       _refId = refId;
       
       if (isType)
-	_state = TYPE;
+        _state = TYPE;
       else {
-	printObject("list (#" + _refId + ")");
-	_state = VALUE;
+        printObject("list (#" + _refId + ")");
+        _state = VALUE;
       }
     }
 
@@ -1830,71 +1838,71 @@ public class HessianDebugState implements Hessian2Constants
     State shift(Object object)
     {
       if (_state == TYPE) {
-	Object type = object;
-	
-	if (type instanceof String) {
-	  _typeDefList.add((String) type);
-	}
-	else if (object instanceof Integer) {
-	  int index = (Integer) object;
-
-	  if (index >= 0 && index < _typeDefList.size())
-	    type = _typeDefList.get(index);
-	  else
-	    type = "type-unknown(" + index + ")";
-	}
-	
-	printObject("list " + type + "(#" + _refId + ")");
+        Object type = object;
+
+        if (type instanceof String) {
+          _typeDefList.add((String) type);
+        }
+        else if (object instanceof Integer) {
+          int index = (Integer) object;
+
+          if (index >= 0 && index < _typeDefList.size())
+            type = _typeDefList.get(index);
+          else
+            type = "type-unknown(" + index + ")";
+        }
+
+        printObject("list " + type + "(#" + _refId + ")");
       
-	_state = VALUE;
+        _state = VALUE;
       
-	return this;
+        return this;
       }
       else if (_state == LENGTH) {
-	_state = VALUE;
+        _state = VALUE;
 
-	return this;
+        return this;
       }
       else
-	return this;
+        return this;
     }
 
     @Override
     int depth()
     {
       if (_state <= LENGTH)
-	return _next.depth();
+        return _next.depth();
       else if (_state == VALUE)
-	return _valueDepth;
+        return _valueDepth;
       else
-	return _next.depth() + 2;
+        return _next.depth() + 2;
     }
     
     State next(int ch)
     {
       switch (_state) {
       case TYPE:
-	return nextObject(ch);
-	
+        return nextObject(ch);
+
       case VALUE:
-	if (ch == 'Z') {
-	  if (_count > 0)
-	    println();
-	  
-	  return _next;
-	}
-	else {
-	  _valueDepth = _next.depth() + 2;
-	  println();
-	  printObject(_count++ + ": ");
-	  _valueDepth = _column;
-	  _isObject = false;
-	  
-	  return nextObject(ch);
-	}
+        if (ch == 'Z') {
+          if (_count > 0)
+            println();
+
+          return _next;
+        }
+        else {
+          _valueDepth = _next.depth() + 2;
+          println();
+          printObject(_count++ + ": ");
+          _valueDepth = _column;
+          _isObject = false;
+
+          return nextObject(ch);
+        }
 
       default:
-	throw new IllegalStateException();
+        throw new IllegalStateException();
       }
     }
   }
@@ -1910,7 +1918,6 @@ public class HessianDebugState implements Hessian2Constants
     private boolean _isLength;
 
     private int _state;
-    private boolean _hasData;
     private int _length;
     private int _count;
     private int _valueDepth;
@@ -1923,9 +1930,9 @@ public class HessianDebugState implements Hessian2Constants
       _refId = refId;
       
       if (isTyped)
-	_state = TYPE;
+        _state = TYPE;
       else
-	_state = LENGTH;
+        _state = LENGTH;
     }
 
     CompactListState(State next, int refId, boolean isTyped, int length)
@@ -1939,11 +1946,11 @@ public class HessianDebugState implements Hessian2Constants
       _isLength = true;
       
       if (isTyped)
-	_state = TYPE;
+        _state = TYPE;
       else {
-	printObject("list (#" + _refId + ")");
-	
-	_state = VALUE;
+        printObject("list (#" + _refId + ")");
+
+        _state = VALUE;
       }
     }
 
@@ -1957,84 +1964,84 @@ public class HessianDebugState implements Hessian2Constants
     State shift(Object object)
     {
       if (_state == TYPE) {
-	Object type = object;
-	
-	if (object instanceof Integer) {
-	  int index = (Integer) object;
-
-	  if (index >= 0 && index < _typeDefList.size())
-	    type = _typeDefList.get(index);
-	  else
-	    type = "type-unknown(" + index + ")";
-	}
-	else if (object instanceof String)
-	  _typeDefList.add((String) object);
-	
-	printObject("list " + type + " (#" + _refId + ")");
-
-	if (_isLength) {
-	  _state = VALUE;
-
-	  if (_length == 0)
-	    return _next;
-	}
-	else
-	  _state = LENGTH;
+        Object type = object;
+
+        if (object instanceof Integer) {
+          int index = (Integer) object;
+
+          if (index >= 0 && index < _typeDefList.size())
+            type = _typeDefList.get(index);
+          else
+            type = "type-unknown(" + index + ")";
+        }
+        else if (object instanceof String)
+          _typeDefList.add((String) object);
+
+        printObject("list " + type + " (#" + _refId + ")");
+
+        if (_isLength) {
+          _state = VALUE;
+
+          if (_length == 0)
+            return _next;
+        }
+        else
+          _state = LENGTH;
       
-	return this;
+        return this;
       }
       else if (_state == LENGTH) {
-	_length = (Integer) object;
+        _length = (Integer) object;
+
+        if (! _isTyped)
+          printObject("list (#" + _refId + ")");
 
-	if (! _isTyped)
-	  printObject("list (#" + _refId + ")");
-	
-	_state = VALUE;
+        _state = VALUE;
 
-	if (_length == 0)
-	  return _next;
-	else
-	  return this;
+        if (_length == 0)
+          return _next;
+        else
+          return this;
       }
       else
-	return this;
+        return this;
     }
 
     @Override
     int depth()
     {
       if (_state <= LENGTH)
-	return _next.depth();
+        return _next.depth();
       else if (_state == VALUE)
-	return _valueDepth;
+        return _valueDepth;
       else
-	return _next.depth() + 2;
+        return _next.depth() + 2;
     }
     
     State next(int ch)
     {
       switch (_state) {
       case TYPE:
-	return nextObject(ch);
-	
+        return nextObject(ch);
+
       case LENGTH:
-	return nextObject(ch);
-	
+        return nextObject(ch);
+
       case VALUE:
-	if (_length <= _count)
-	  return _next.next(ch);
-	else {
-	  _valueDepth = _next.depth() + 2;
-	  println();
-	  printObject(_count++ + ": ");
-	  _valueDepth = _column;
-	  _isObject = false;
-	  
-	  return nextObject(ch);
-	}
+        if (_length <= _count)
+          return _next.next(ch);
+        else {
+          _valueDepth = _next.depth() + 2;
+          println();
+          printObject(_count++ + ": ");
+          _valueDepth = _column;
+          _isObject = false;
+
+          return nextObject(ch);
+        }
 
       default:
-	throw new IllegalStateException();
+        throw new IllegalStateException();
       }
     }
   }
@@ -2061,17 +2068,17 @@ public class HessianDebugState implements Hessian2Constants
     {
       switch (_state) {
       case MAJOR:
-	_major = ch;
-	_state = MINOR;
-	return this;
-	
+        _major = ch;
+        _state = MINOR;
+        return this;
+
       case MINOR:
-	_minor = ch;
-	println(-2, "Hessian " + _major + "." + _minor);
-	return _next;
+        _minor = ch;
+        println(-2, "Hessian " + _major + "." + _minor);
+        return _next;
 
       default:
-	throw new IllegalStateException();
+        throw new IllegalStateException();
       }
     }
   }
@@ -2102,52 +2109,52 @@ public class HessianDebugState implements Hessian2Constants
     {
       switch (_state) {
       case MAJOR:
-	_major = ch;
-	_state = MINOR;
-	return this;
-	
+        _major = ch;
+        _state = MINOR;
+        return this;
+
       case MINOR:
-	_minor = ch;
-	_state = HEADER;
-	println(-2, "call " + _major + "." + _minor);
-	return this;
-	
+        _minor = ch;
+        _state = HEADER;
+        println(-2, "call " + _major + "." + _minor);
+        return this;
+
       case HEADER:
-	if (ch == 'H') {
-	  println();
-	  print("header ");
-	  _isObject = false;
-	  _state = VALUE;
-	  return new StringState(this, 'H', true);
-	}
- 	else if (ch == 'm') {
-	  println();
-	  print("method ");
-	  _isObject = false;
-	  _state = ARG;
-	  return new StringState(this, 'm', true);
-	}
-	else {
-	  println((char) ch + ": unexpected char");
-	  return popStack();
-	}
-	
+        if (ch == 'H') {
+          println();
+          print("header ");
+          _isObject = false;
+          _state = VALUE;
+          return new StringState(this, 'H', true);
+        }
+         else if (ch == 'm') {
+          println();
+          print("method ");
+          _isObject = false;
+          _state = ARG;
+          return new StringState(this, 'm', true);
+        }
+        else {
+          println((char) ch + ": unexpected char");
+          return popStack();
+        }
+
       case VALUE:
-	print(" => ");
-	_isObject = false;
-	_state = HEADER;
-	return nextObject(ch);
-	
+        print(" => ");
+        _isObject = false;
+        _state = HEADER;
+        return nextObject(ch);
+
       case ARG:
-	if (ch == 'z') {
-	  println();
-	  return _next;
-	}
-	else
-	  return nextObject(ch);
+        if (ch == 'z') {
+          println();
+          return _next;
+        }
+        else
+          return nextObject(ch);
 
       default:
-	throw new IllegalStateException();
+        throw new IllegalStateException();
       }
     }
   }
@@ -2181,26 +2188,26 @@ public class HessianDebugState implements Hessian2Constants
     State shift(Object object)
     {
       if (_state == METHOD) {
-	println(-5, "Call " + object);
+        println(-5, "Call " + object);
 
-	_state = COUNT;
-	return this;
+        _state = COUNT;
+        return this;
       }
       else if (_state == COUNT) {
-	Integer count = (Integer) object;
+        Integer count = (Integer) object;
 
-	_count = count;
+        _count = count;
       
-	_state = ARG;
+        _state = ARG;
 
-	if (_count == 0) {
-	  return _next;
-	}
-	else
-	  return this;
+        if (_count == 0) {
+          return _next;
+        }
+        else
+          return this;
       }
       else {
-	return this;
+        return this;
       }
     }
 
@@ -2209,25 +2216,25 @@ public class HessianDebugState implements Hessian2Constants
     {
       switch (_state) {
       case COUNT:
-	return nextObject(ch);
-	
+        return nextObject(ch);
+
       case METHOD:
-	return nextObject(ch);
-	
+        return nextObject(ch);
+
       case ARG:
-	if (_count <= _i) {
-	  println();
-	  return _next.next(ch);
-	}
-	else {
-	  println();
-	  print(-3, _i++ + ": ");
-	  
-	  return nextObject(ch);
-	}
+        if (_count <= _i) {
+          println();
+          return _next.next(ch);
+        }
+        else {
+          println();
+          print(-3, _i++ + ": ");
+
+          return nextObject(ch);
+        }
 
       default:
-	throw new IllegalStateException();
+        throw new IllegalStateException();
       }
     }
   }
@@ -2257,49 +2264,49 @@ public class HessianDebugState implements Hessian2Constants
     {
       switch (_state) {
       case MAJOR:
-	if (ch == 't' || ch == 'S')
-	  return new RemoteState(this).next(ch);
-	
-	_major = ch;
-	_state = MINOR;
-	return this;
-	
+        if (ch == 't' || ch == 'S')
+          return new RemoteState(this).next(ch);
+
+        _major = ch;
+        _state = MINOR;
+        return this;
+
       case MINOR:
-	_minor = ch;
-	_state = HEADER;
-	println(-2, "reply " + _major + "." + _minor);
-	return this;
-	
+        _minor = ch;
+        _state = HEADER;
+        println(-2, "reply " + _major + "." + _minor);
+        return this;
+
       case HEADER:
-	if (ch == 'H') {
-	  _state = VALUE;
-	  return new StringState(this, 'H', true);
-	}
-	else if (ch == 'f') {
-	  print("fault ");
-	  _isObject = false;
-	  _state = END;
-	  return new MapState(this, 0);
-	}
- 	else {
-	  _state = END;
-	  return nextObject(ch);
-	}
-	
+        if (ch == 'H') {
+          _state = VALUE;
+          return new StringState(this, 'H', true);
+        }
+        else if (ch == 'f') {
+          print("fault ");
+          _isObject = false;
+          _state = END;
+          return new MapState(this, 0);
+        }
+         else {
+          _state = END;
+          return nextObject(ch);
+        }
+
       case VALUE:
-	_state = HEADER;
-	return nextObject(ch);
-	
+        _state = HEADER;
+        return nextObject(ch);
+
       case END:
-	println();
-	if (ch == 'z') {
-	  return _next;
-	}
-	else
-	  return _next.next(ch);
+        println();
+        if (ch == 'z') {
+          return _next;
+        }
+        else
+          return _next.next(ch);
 
       default:
-	throw new IllegalStateException();
+        throw new IllegalStateException();
       }
     }
   }
@@ -2321,11 +2328,11 @@ public class HessianDebugState implements Hessian2Constants
     State next(int ch)
     {
       if (ch < 0) {
-	println();
-	return _next;
+        println();
+        return _next;
       }
       else {
-	return nextObject(ch);
+        return nextObject(ch);
       }
     }
   }
@@ -2386,39 +2393,41 @@ public class HessianDebugState implements Hessian2Constants
       super(next);
     }
     
+    @Override
     State next(int ch)
     {
       switch (_state) {
       case TYPE:
-	println(-1, "remote");
-	if (ch == 't') {
-	  _state = VALUE;
-	  return new StringState(this, 't', false);
-	}
-	else {
-	  _state = END;
-	  return nextObject(ch);
-	}
+        println(-1, "remote");
+        if (ch == 't') {
+          _state = VALUE;
+          return new StringState(this, 't', false);
+        }
+        else {
+          _state = END;
+          return nextObject(ch);
+        }
 
       case VALUE:
-	_state = END;
-	return _next.nextObject(ch);
+        _state = END;
+        return _next.nextObject(ch);
 
       case END:
-	return _next.next(ch);
+        return _next.next(ch);
 
       default:
-	throw new IllegalStateException();
+        throw new IllegalStateException();
       }
     }
   }
   
   class StreamingState extends State {
-    private int _digit;
-    private int _code;
-    private int _length;
+    private long _length;
+    private int _metaLength;
     private boolean _isLast;
     private boolean _isFirst = true;
+    
+    private boolean _isLengthState;
 
     private State _childState;
 
@@ -2432,55 +2441,66 @@ public class HessianDebugState implements Hessian2Constants
     
     State next(int ch)
     {
-      if (_digit >= 0) {
-        if (_digit == 0) {
-          _code = ch;
-          _digit = 1;
-          _length = 0;
+      if (_metaLength > 0) {
+        _length = 256 * _length + ch;
+        _metaLength--;
         
-          return this;
+        if (_metaLength == 0 && _isFirst) {
+          if (_isLast)
+            println(-1, "--- packet-start(" + _length + ")");
+          else
+            println(-1, "--- packet-start(fragment)");
+          _isFirst = false;
         }
-        else if ((ch & 0x80) == 0x80) {
-          _length = 128 * _length + (ch & 0x7f);
         
-          return this;
-        }
-        else {
-          _length = 128 * _length + (ch & 0x7f);
-          _digit = -1;
-        }
+        return this;
+      }
+      
+      if (_length > 0) {
+        _length--;
+        _childState = _childState.next(ch);
         
-        if (_isFirst)
-          println(-1, "packet-start(" + _length + ")");
-        _isFirst = false;
+        return this;
+      }
+      
+      if (! _isLengthState) {
+        _isLengthState = true;
         
-        if (_length == 0) {
-          _isFirst = true;
+        if (_isLast) {
           println(-1, "");
-          println(-1, "packet-end");
+          println(-1, "--- packet-end");
           _refId = 0;
-          _digit = 0;
+          
+          _isFirst = true;
         }
         
-        return this;
-      }
-      else if (_length == 0) {
-	_digit = 0;
-	
-	return this;
+        _isLast = (ch & 0x80) == 0x00;
+        _isLengthState = true;
       }
-
-      _childState = _childState.next(ch);
-
-      _length--;
-
-      if (_length <= 0) {
-	_digit = 0;
-	_length = 0;
-	return this;
+      else {
+        _isLengthState = false;
+        _length = (ch & 0x7f);
+        
+        if (_length == 0x7e) {
+          _length = 0;
+          _metaLength = 2;
+        }
+        else if (_length == 0x7f) {
+          _length = 0;
+          _metaLength = 8;
+        }
+        else {
+          if (_isFirst) {
+            if (_isLast)
+              println(-1, "--- packet-start(" + _length + ")");
+            else
+              println(-1, "--- packet-start(fragment)");
+            _isFirst = false;
+          }
+        }
       }
-      else
-	return this;
+      
+      return this;
     }
   }
 
diff --git a/com/caucho/hessian/io/HessianFactory.java b/com/caucho/hessian/io/HessianFactory.java
index 50d5f8b..2331423 100644
--- a/com/caucho/hessian/io/HessianFactory.java
+++ b/com/caucho/hessian/io/HessianFactory.java
@@ -102,8 +102,15 @@ public class HessianFactory
    */
   public Hessian2Input createHessian2Input(InputStream is)
   {
-    Hessian2Input in = new Hessian2Input(is);
-    in.setSerializerFactory(_serializerFactory);
+    Hessian2Input in = _freeHessian2Input.allocate();
+    
+    if (in == null) {
+      in = new Hessian2Input(is);
+      in.setSerializerFactory(getSerializerFactory());
+    }
+    else {
+      in.init(is);
+    }
 
     return in;
   }
@@ -113,14 +120,12 @@ public class HessianFactory
    */
   public void freeHessian2Input(Hessian2Input in)
   {
-    /*
     if (in == null)
       return;
 
     in.free();
 
     _freeHessian2Input.free(in);
-    */
   }
 
   /**
@@ -129,7 +134,7 @@ public class HessianFactory
   public Hessian2StreamingInput createHessian2StreamingInput(InputStream is)
   {
     Hessian2StreamingInput in = new Hessian2StreamingInput(is);
-    in.setSerializerFactory(_serializerFactory);
+    in.setSerializerFactory(getSerializerFactory());
 
     return in;
   }
@@ -154,14 +159,25 @@ public class HessianFactory
    */
   public Hessian2Output createHessian2Output(OutputStream os)
   {
+    Hessian2Output out = createHessian2Output();
+    
+    out.init(os);
+    
+    return out;
+  }
+
+  /**
+   * Creates a new Hessian 2.0 serializer.
+   */
+  public Hessian2Output createHessian2Output()
+  {
     Hessian2Output out = _freeHessian2Output.allocate();
 
-    if (out != null)
-      out.init(os);
-    else
-      out = new Hessian2Output(os);
+    if (out == null) {
+      out = new Hessian2Output();
 
-    out.setSerializerFactory(_serializerFactory);
+      out.setSerializerFactory(getSerializerFactory());
+    }
 
     return out;
   }
diff --git a/com/caucho/hessian/io/HessianInput.java b/com/caucho/hessian/io/HessianInput.java
index 5a690e1..e31c72b 100644
--- a/com/caucho/hessian/io/HessianInput.java
+++ b/com/caucho/hessian/io/HessianInput.java
@@ -358,12 +358,12 @@ public class HessianInput extends AbstractHessianInput {
       _replyFault = (Throwable) detail;
       
       if (message != null && _detailMessageField != null) {
-	try {
-	  _detailMessageField.set(_replyFault, message);
-	} catch (Throwable e) {
-	}
+        try {
+          _detailMessageField.set(_replyFault, message);
+        } catch (Throwable e) {
+        }
       }
-	
+
       return _replyFault;
     }
 
@@ -1023,14 +1023,14 @@ public class HessianInput extends AbstractHessianInput {
 
       // hessian/3386
       if ("".equals(type)) {
-	Deserializer reader;
-	reader = _serializerFactory.getDeserializer(cl);
+        Deserializer reader;
+        reader = _serializerFactory.getDeserializer(cl);
 
-	return reader.readMap(this);
+        return reader.readMap(this);
       }
       else {
-	Deserializer reader;
-	reader = _serializerFactory.getObjectDeserializer(type);
+        Deserializer reader;
+        reader = _serializerFactory.getObjectDeserializer(type);
 
         return reader.readMap(this);
       }
@@ -1566,42 +1566,42 @@ public class HessianInput extends AbstractHessianInput {
     }
     
     return new InputStream() {
-	boolean _isClosed = false;
-	
-	public int read()
-	  throws IOException
-	{
-	  if (_isClosed || _is == null)
-	    return -1;
-
-	  int ch = parseByte();
-	  if (ch < 0)
-	    _isClosed = true;
-
-	  return ch;
-	}
-	
-	public int read(byte []buffer, int offset, int length)
-	  throws IOException
-	{
-	  if (_isClosed || _is == null)
-	    return -1;
-
-	  int len = HessianInput.this.read(buffer, offset, length);
-	  if (len < 0)
-	    _isClosed = true;
-
-	  return len;
-	}
-
-	public void close()
-	  throws IOException
-	{
-	  while (read() >= 0) {
-	  }
-
-	  _isClosed = true;
-	}
+        boolean _isClosed = false;
+
+        public int read()
+          throws IOException
+        {
+          if (_isClosed || _is == null)
+            return -1;
+
+          int ch = parseByte();
+          if (ch < 0)
+            _isClosed = true;
+
+          return ch;
+        }
+
+        public int read(byte []buffer, int offset, int length)
+          throws IOException
+        {
+          if (_isClosed || _is == null)
+            return -1;
+
+          int len = HessianInput.this.read(buffer, offset, length);
+          if (len < 0)
+            _isClosed = true;
+
+          return len;
+        }
+
+        public void close()
+          throws IOException
+        {
+          while (read() >= 0) {
+          }
+
+          _isClosed = true;
+        }
       };
   }
   
diff --git a/com/caucho/hessian/io/HessianInputFactory.java b/com/caucho/hessian/io/HessianInputFactory.java
index dac7ca5..75fd0cc 100644
--- a/com/caucho/hessian/io/HessianInputFactory.java
+++ b/com/caucho/hessian/io/HessianInputFactory.java
@@ -82,9 +82,9 @@ public class HessianInputFactory
       
     case 'c':
       if (major >= 2)
-	return HeaderType.CALL_1_REPLY_2;
+        return HeaderType.CALL_1_REPLY_2;
       else
-	return HeaderType.CALL_1_REPLY_1;
+        return HeaderType.CALL_1_REPLY_1;
     case 'r':
       return HeaderType.REPLY_1;
       
@@ -110,10 +110,10 @@ public class HessianInputFactory
     case 'r':
     case 'R':
       if (major >= 2) {
-	return _factory.createHessian2Input(is);
+        return _factory.createHessian2Input(is);
       }
       else {
-	return _factory.createHessianInput(is);
+        return _factory.createHessianInput(is);
       }
 
     default:
@@ -133,9 +133,9 @@ public class HessianInputFactory
       switch (this) {
       case CALL_1_REPLY_1:
       case CALL_1_REPLY_2:
-	return true;
+        return true;
       default:
-	return false;
+        return false;
       }
     }
 
@@ -143,9 +143,9 @@ public class HessianInputFactory
     {
       switch (this) {
       case HESSIAN_2:
-	return true;
+        return true;
       default:
-	return false;
+        return false;
       }
     }
 
@@ -153,9 +153,9 @@ public class HessianInputFactory
     {
       switch (this) {
       case CALL_1_REPLY_1:
-	return true;
+        return true;
       default:
-	return false;
+        return false;
       }
     }
 
@@ -164,9 +164,9 @@ public class HessianInputFactory
       switch (this) {
       case CALL_1_REPLY_2:
       case HESSIAN_2:
-	return true;
+        return true;
       default:
-	return false;
+        return false;
       }
     }
   }
diff --git a/com/caucho/hessian/io/HessianOutput.java b/com/caucho/hessian/io/HessianOutput.java
index f626722..c590229 100644
--- a/com/caucho/hessian/io/HessianOutput.java
+++ b/com/caucho/hessian/io/HessianOutput.java
@@ -567,11 +567,11 @@ public class HessianOutput extends AbstractHessianOutput {
       while (length > 0x8000) {
         int sublen = 0x8000;
 
-	// chunk can't end in high surrogate
-	char tail = value.charAt(offset + sublen - 1);
+        // chunk can't end in high surrogate
+        char tail = value.charAt(offset + sublen - 1);
 
-	if (0xd800 <= tail && tail <= 0xdbff)
-	  sublen--;
+        if (0xd800 <= tail && tail <= 0xdbff)
+          sublen--;
         
         os.write('s');
         os.write(sublen >> 8);
@@ -617,11 +617,11 @@ public class HessianOutput extends AbstractHessianOutput {
       while (length > 0x8000) {
         int sublen = 0x8000;
 
-	// chunk can't end in high surrogate
-	char tail = buffer[offset + sublen - 1];
+        // chunk can't end in high surrogate
+        char tail = buffer[offset + sublen - 1];
 
-	if (0xd800 <= tail && tail <= 0xdbff)
-	  sublen--;
+        if (0xd800 <= tail && tail <= 0xdbff)
+          sublen--;
         
         os.write('s');
         os.write(sublen >> 8);
@@ -734,7 +734,7 @@ public class HessianOutput extends AbstractHessianOutput {
       int sublen = length;
 
       if (0x8000 < sublen)
-	sublen = 0x8000;
+        sublen = 0x8000;
 
       os.write('b');
       os.write(sublen >> 8);
diff --git a/com/caucho/hessian/io/EnumerationDeserializer.java b/com/caucho/hessian/io/IteratorDeserializer.java
similarity index 88%
copy from com/caucho/hessian/io/EnumerationDeserializer.java
copy to com/caucho/hessian/io/IteratorDeserializer.java
index 875759b..937ea1a 100644
--- a/com/caucho/hessian/io/EnumerationDeserializer.java
+++ b/com/caucho/hessian/io/IteratorDeserializer.java
@@ -49,26 +49,27 @@
 package com.caucho.hessian.io;
 
 import java.io.IOException;
-import java.util.Vector;
+import java.util.ArrayList;
 
 /**
  * Deserializing a JDK 1.2 Collection.
  */
-public class EnumerationDeserializer extends AbstractListDeserializer {
-  private static EnumerationDeserializer _deserializer;
+public class IteratorDeserializer extends AbstractListDeserializer {
+  private static IteratorDeserializer _deserializer;
 
-  public static EnumerationDeserializer create()
+  public static IteratorDeserializer create()
   {
     if (_deserializer == null)
-      _deserializer = new EnumerationDeserializer();
+      _deserializer = new IteratorDeserializer();
 
     return _deserializer;
   }
   
+  @Override
   public Object readList(AbstractHessianInput in, int length)
     throws IOException
   {
-    Vector list = new Vector();
+    ArrayList list = new ArrayList();
 
     in.addRef(list);
 
@@ -77,7 +78,7 @@ public class EnumerationDeserializer extends AbstractListDeserializer {
 
     in.readEnd();
 
-    return list.elements();
+    return list.iterator();
   }
 }
 
diff --git a/com/caucho/hessian/io/JavaDeserializer.java b/com/caucho/hessian/io/JavaDeserializer.java
index 7e74a31..72df269 100644
--- a/com/caucho/hessian/io/JavaDeserializer.java
+++ b/com/caucho/hessian/io/JavaDeserializer.java
@@ -89,24 +89,24 @@ public class JavaDeserializer extends AbstractMapDeserializer {
       long cost = 0;
 
       for (int j = 0; j < param.length; j++) {
-	cost = 4 * cost;
-
-	if (Object.class.equals(param[j]))
-	  cost += 1;
-	else if (String.class.equals(param[j]))
-	  cost += 2;
-	else if (int.class.equals(param[j]))
-	  cost += 3;
-	else if (long.class.equals(param[j]))
-	  cost += 4;
-	else if (param[j].isPrimitive())
-	  cost += 5;
-	else
-	  cost += 6;
+        cost = 4 * cost;
+
+        if (Object.class.equals(param[j]))
+          cost += 1;
+        else if (String.class.equals(param[j]))
+          cost += 2;
+        else if (int.class.equals(param[j]))
+          cost += 3;
+        else if (long.class.equals(param[j]))
+          cost += 4;
+        else if (param[j].isPrimitive())
+          cost += 5;
+        else
+          cost += 6;
       }
 
       if (cost < 0 || cost > (1 << 48))
-	cost = 1 << 48;
+        cost = 1 << 48;
 
       cost += (long) param.length << 48;
 
@@ -160,6 +160,7 @@ public class JavaDeserializer extends AbstractMapDeserializer {
     return new FieldDeserializer[len];
   }
 
+  @Override
   public Object createField(String name)
   {
     Object reader = _fieldMap.get(name);
@@ -215,11 +216,11 @@ public class JavaDeserializer extends AbstractMapDeserializer {
       Method []methods = cl.getDeclaredMethods();
       
       for (int i = 0; i < methods.length; i++) {
-	Method method = methods[i];
+        Method method = methods[i];
 
-	if (method.getName().equals("readResolve")
+        if (method.getName().equals("readResolve")
             && method.getParameterTypes().length == 0)
-	  return method;
+          return method;
       }
     }
 
@@ -238,7 +239,7 @@ public class JavaDeserializer extends AbstractMapDeserializer {
         FieldDeserializer deser = _fieldMap.get(key);
 
         if (deser != null)
-	  deser.deserialize(in, obj);
+          deser.deserialize(in, obj);
         else
           in.readObject();
       }
@@ -248,7 +249,7 @@ public class JavaDeserializer extends AbstractMapDeserializer {
       Object resolve = resolve(in, obj);
 
       if (obj != resolve)
-	in.setRef(ref, resolve);
+        in.setRef(ref, resolve);
 
       return resolve;
     } catch (IOException e) {
@@ -273,7 +274,7 @@ public class JavaDeserializer extends AbstractMapDeserializer {
       Object resolve = resolve(in, obj);
 
       if (obj != resolve)
-	in.setRef(ref, resolve);
+        in.setRef(ref, resolve);
 
       return resolve;
     } catch (IOException e) {
@@ -335,9 +336,9 @@ public class JavaDeserializer extends AbstractMapDeserializer {
   {
     try {
       if (_constructor != null)
-	return _constructor.newInstance(_constructorArgs);
+        return _constructor.newInstance(_constructorArgs);
       else
-	return _type.newInstance();
+        return _type.newInstance();
     } catch (Exception e) {
       throw new HessianProtocolException("'" + _type.getName() + "' could not be instantiated", e);
     }
@@ -357,7 +358,7 @@ public class JavaDeserializer extends AbstractMapDeserializer {
         Field field = fields[i];
 
         if (Modifier.isTransient(field.getModifiers())
-	    || Modifier.isStatic(field.getModifiers()))
+            || Modifier.isStatic(field.getModifiers()))
           continue;
         else if (fieldMap.get(field.getName()) != null)
           continue;
@@ -369,44 +370,44 @@ public class JavaDeserializer extends AbstractMapDeserializer {
           e.printStackTrace();
         }
 
-	Class<?> type = field.getType();
-	FieldDeserializer deser;
-
-	if (String.class.equals(type))
-	  deser = new StringFieldDeserializer(field);
-	else if (byte.class.equals(type)) {
-	  deser = new ByteFieldDeserializer(field);
-	}
-	else if (short.class.equals(type)) {
-	  deser = new ShortFieldDeserializer(field);
-	}
-	else if (int.class.equals(type)) {
-	  deser = new IntFieldDeserializer(field);
-	}
-	else if (long.class.equals(type)) {
-	  deser = new LongFieldDeserializer(field);
-	}
-	else if (float.class.equals(type)) {
-	  deser = new FloatFieldDeserializer(field);
-	}
-	else if (double.class.equals(type)) {
-	  deser = new DoubleFieldDeserializer(field);
-	}
-	else if (boolean.class.equals(type)) {
-	  deser = new BooleanFieldDeserializer(field);
-	}
-	else if (java.sql.Date.class.equals(type)) {
-	  deser = new SqlDateFieldDeserializer(field);
-	}
-	else if (java.sql.Timestamp.class.equals(type)) {
-	  deser = new SqlTimestampFieldDeserializer(field);
-	}
-	else if (java.sql.Time.class.equals(type)) {
-	  deser = new SqlTimeFieldDeserializer(field);
-	}
-	else {
-	  deser = new ObjectFieldDeserializer(field);
-	}
+        Class<?> type = field.getType();
+        FieldDeserializer deser;
+
+        if (String.class.equals(type))
+          deser = new StringFieldDeserializer(field);
+        else if (byte.class.equals(type)) {
+          deser = new ByteFieldDeserializer(field);
+        }
+        else if (short.class.equals(type)) {
+          deser = new ShortFieldDeserializer(field);
+        }
+        else if (int.class.equals(type)) {
+          deser = new IntFieldDeserializer(field);
+        }
+        else if (long.class.equals(type)) {
+          deser = new LongFieldDeserializer(field);
+        }
+        else if (float.class.equals(type)) {
+          deser = new FloatFieldDeserializer(field);
+        }
+        else if (double.class.equals(type)) {
+          deser = new DoubleFieldDeserializer(field);
+        }
+        else if (boolean.class.equals(type)) {
+          deser = new BooleanFieldDeserializer(field);
+        }
+        else if (java.sql.Date.class.equals(type)) {
+          deser = new SqlDateFieldDeserializer(field);
+        }
+        else if (java.sql.Timestamp.class.equals(type)) {
+          deser = new SqlTimestampFieldDeserializer(field);
+        }
+        else if (java.sql.Time.class.equals(type)) {
+          deser = new SqlTimeFieldDeserializer(field);
+        }
+        else {
+          deser = new ObjectFieldDeserializer(field);
+        }
 
         fieldMap.put(field.getName(), deser);
       }
@@ -447,8 +448,10 @@ public class JavaDeserializer extends AbstractMapDeserializer {
       throws IOException;
   }
   
-  static class NullFieldDeserializer {
+  static class NullFieldDeserializer extends FieldDeserializer {
     static NullFieldDeserializer DESER = new NullFieldDeserializer();
+    
+    @Override
     void deserialize(AbstractHessianInput in, Object obj)
       throws IOException
     {
@@ -470,9 +473,9 @@ public class JavaDeserializer extends AbstractMapDeserializer {
       Object value = null;
       
       try {
-	value = in.readObject(_field.getType());
-	
-	_field.set(obj, value);
+        value = in.readObject(_field.getType());
+
+        _field.set(obj, value);
       } catch (Exception e) {
         logDeserializeError(_field, obj, value, e);
       }
@@ -493,9 +496,9 @@ public class JavaDeserializer extends AbstractMapDeserializer {
       boolean value = false;
       
       try {
-	value = in.readBoolean();
-	
-	_field.setBoolean(obj, value);
+        value = in.readBoolean();
+
+        _field.setBoolean(obj, value);
       } catch (Exception e) {
         logDeserializeError(_field, obj, value, e);
       }
@@ -516,9 +519,9 @@ public class JavaDeserializer extends AbstractMapDeserializer {
       int value = 0;
       
       try {
-	value = in.readInt();
-	
-	_field.setByte(obj, (byte) value);
+        value = in.readInt();
+
+        _field.setByte(obj, (byte) value);
       } catch (Exception e) {
         logDeserializeError(_field, obj, value, e);
       }
@@ -539,9 +542,9 @@ public class JavaDeserializer extends AbstractMapDeserializer {
       int value = 0;
       
       try {
-	value = in.readInt();
-	
-	_field.setShort(obj, (short) value);
+        value = in.readInt();
+
+        _field.setShort(obj, (short) value);
       } catch (Exception e) {
         logDeserializeError(_field, obj, value, e);
       }
@@ -562,9 +565,9 @@ public class JavaDeserializer extends AbstractMapDeserializer {
       int value = 0;
       
       try {
-	value = in.readInt();
-	
-	_field.setInt(obj, value);
+        value = in.readInt();
+
+        _field.setInt(obj, value);
       } catch (Exception e) {
         logDeserializeError(_field, obj, value, e);
       }
@@ -585,9 +588,9 @@ public class JavaDeserializer extends AbstractMapDeserializer {
       long value = 0;
       
       try {
-	value = in.readLong();
-	
-	_field.setLong(obj, value);
+        value = in.readLong();
+
+        _field.setLong(obj, value);
       } catch (Exception e) {
         logDeserializeError(_field, obj, value, e);
       }
@@ -608,9 +611,9 @@ public class JavaDeserializer extends AbstractMapDeserializer {
       double value = 0;
       
       try {
-	value = in.readDouble();
-	
-	_field.setFloat(obj, (float) value);
+        value = in.readDouble();
+
+        _field.setFloat(obj, (float) value);
       } catch (Exception e) {
         logDeserializeError(_field, obj, value, e);
       }
@@ -631,9 +634,9 @@ public class JavaDeserializer extends AbstractMapDeserializer {
       double value = 0;
       
       try {
-	value = in.readDouble();
-	
-	_field.setDouble(obj, value);
+        value = in.readDouble();
+
+        _field.setDouble(obj, value);
       } catch (Exception e) {
         logDeserializeError(_field, obj, value, e);
       }
@@ -654,9 +657,9 @@ public class JavaDeserializer extends AbstractMapDeserializer {
       String value = null;
       
       try {
-	value = in.readString();
-	
-	_field.set(obj, value);
+        value = in.readString();
+
+        _field.set(obj, value);
       } catch (Exception e) {
         logDeserializeError(_field, obj, value, e);
       }
@@ -678,9 +681,15 @@ public class JavaDeserializer extends AbstractMapDeserializer {
 
       try {
         java.util.Date date = (java.util.Date) in.readObject();
-        value = new java.sql.Date(date.getTime());
+        
+        if (date != null) {
+          value = new java.sql.Date(date.getTime());
 
-        _field.set(obj, value);
+          _field.set(obj, value);
+        }
+        else {
+          _field.set(obj, null);
+        }
       } catch (Exception e) {
         logDeserializeError(_field, obj, value, e);
       }
@@ -702,9 +711,15 @@ public class JavaDeserializer extends AbstractMapDeserializer {
 
       try {
         java.util.Date date = (java.util.Date) in.readObject();
-        value = new java.sql.Timestamp(date.getTime());
+        
+        if (date != null) {
+          value = new java.sql.Timestamp(date.getTime());
 
-        _field.set(obj, value);
+          _field.set(obj, value);
+        }
+        else {
+          _field.set(obj, null);
+        }
       } catch (Exception e) {
         logDeserializeError(_field, obj, value, e);
       }
@@ -726,9 +741,15 @@ public class JavaDeserializer extends AbstractMapDeserializer {
 
       try {
         java.util.Date date = (java.util.Date) in.readObject();
-        value = new java.sql.Time(date.getTime());
+        
+        if (date != null) {
+          value = new java.sql.Time(date.getTime());
 
-        _field.set(obj, value);
+          _field.set(obj, value);
+        }
+        else {
+          _field.set(obj, null);
+        }
       } catch (Exception e) {
         logDeserializeError(_field, obj, value, e);
       }
@@ -749,7 +770,7 @@ public class JavaDeserializer extends AbstractMapDeserializer {
     
     if (value != null)
       throw new HessianFieldException(fieldName + ": " + value.getClass().getName() + " (" + value + ")"
-				      + " cannot be assigned to '" + field.getType().getName() + "'", e);
+                                      + " cannot be assigned to '" + field.getType().getName() + "'", e);
     else
        throw new HessianFieldException(fieldName + ": " + field.getType().getName() + " cannot be assigned from null", e);
   }
diff --git a/com/caucho/hessian/io/JavaSerializer.java b/com/caucho/hessian/io/JavaSerializer.java
index d43e865..1d25339 100644
--- a/com/caucho/hessian/io/JavaSerializer.java
+++ b/com/caucho/hessian/io/JavaSerializer.java
@@ -49,7 +49,6 @@
 package com.caucho.hessian.io;
 
 import java.io.IOException;
-import java.io.Serializable;
 import java.lang.ref.SoftReference;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
@@ -59,6 +58,8 @@ import java.util.WeakHashMap;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import com.caucho.hessian.HessianUnshared;
+
 /**
  * Serializing an object for known object types.
  */
@@ -81,6 +82,9 @@ public class JavaSerializer extends AbstractSerializer
     introspect(cl);
 
     _writeReplace = getWriteReplace(cl);
+
+    if (_writeReplace != null)
+      _writeReplace.setAccessible(true);
   }
 
   public static Serializer create(Class<?> cl)
@@ -92,9 +96,13 @@ public class JavaSerializer extends AbstractSerializer
       JavaSerializer base = baseRef != null ? baseRef.get() : null;
 
       if (base == null) {
-	base = new JavaSerializer(cl);
-	baseRef = new SoftReference<JavaSerializer>(base);
-	_serializerMap.put(cl, baseRef);
+        if (cl.isAnnotationPresent(HessianUnshared.class))
+          base = new JavaUnsharedSerializer(cl);
+        else
+          base = new JavaSerializer(cl);
+        
+        baseRef = new SoftReference<JavaSerializer>(base);
+        _serializerMap.put(cl, baseRef);
       }
 
       return base;
@@ -112,25 +120,25 @@ public class JavaSerializer extends AbstractSerializer
     for (; cl != null; cl = cl.getSuperclass()) {
       Field []fields = cl.getDeclaredFields();
       for (int i = 0; i < fields.length; i++) {
-	Field field = fields[i];
+        Field field = fields[i];
 
-	if (Modifier.isTransient(field.getModifiers())
-	    || Modifier.isStatic(field.getModifiers()))
-	  continue;
+        if (Modifier.isTransient(field.getModifiers())
+            || Modifier.isStatic(field.getModifiers()))
+          continue;
 
-	// XXX: could parameterize the handler to only deal with public
-	field.setAccessible(true);
+        // XXX: could parameterize the handler to only deal with public
+        field.setAccessible(true);
 
-	if (field.getType().isPrimitive()
-	    || (field.getType().getName().startsWith("java.lang.")
-		&& ! field.getType().equals(Object.class)))
-	  primitiveFields.add(field);
-	else
-	  compoundFields.add(field);
+        if (field.getType().isPrimitive()
+            || (field.getType().getName().startsWith("java.lang.")
+                && ! field.getType().equals(Object.class)))
+          primitiveFields.add(field);
+        else
+          compoundFields.add(field);
       }
     }
 
-    ArrayList fields = new ArrayList();
+    ArrayList<Field> fields = new ArrayList<Field>();
     fields.addAll(primitiveFields);
     fields.addAll(compoundFields);
 
@@ -147,17 +155,17 @@ public class JavaSerializer extends AbstractSerializer
   /**
    * Returns the writeReplace method
    */
-  protected static Method getWriteReplace(Class cl)
+  protected static Method getWriteReplace(Class<?> cl)
   {
     for (; cl != null; cl = cl.getSuperclass()) {
       Method []methods = cl.getDeclaredMethods();
       
       for (int i = 0; i < methods.length; i++) {
-	Method method = methods[i];
+        Method method = methods[i];
 
-	if (method.getName().equals("writeReplace")
+        if (method.getName().equals("writeReplace")
             && method.getParameterTypes().length == 0)
-	  return method;
+          return method;
       }
     }
 
@@ -167,20 +175,21 @@ public class JavaSerializer extends AbstractSerializer
   /**
    * Returns the writeReplace method
    */
-  protected Method getWriteReplace(Class cl, Class param)
+  protected Method getWriteReplace(Class<?> cl, Class<?> param)
   {
     for (; cl != null; cl = cl.getSuperclass()) {
       for (Method method : cl.getDeclaredMethods()) {
-	if (method.getName().equals("writeReplace")
-	    && method.getParameterTypes().length == 1
-	    && param.equals(method.getParameterTypes()[0]))
-	  return method;
+        if (method.getName().equals("writeReplace")
+            && method.getParameterTypes().length == 1
+            && param.equals(method.getParameterTypes()[0]))
+          return method;
       }
     }
 
     return null;
   }
   
+  @Override
   public void writeObject(Object obj, AbstractHessianOutput out)
     throws IOException
   {
@@ -192,20 +201,36 @@ public class JavaSerializer extends AbstractSerializer
 
     try {
       if (_writeReplace != null) {
-	Object repl;
+        Object repl;
+
+        if (_writeReplaceFactory != null)
+          repl = _writeReplace.invoke(_writeReplaceFactory, obj);
+        else
+          repl = _writeReplace.invoke(obj);
+
+        // out.removeRef(obj);
 
-	if (_writeReplaceFactory != null)
-	  repl = _writeReplace.invoke(_writeReplaceFactory, obj);
-	else
-	  repl = _writeReplace.invoke(obj);
+        /*
+        out.writeObject(repl);
 
-	// out.removeRef(obj);
+        out.replaceRef(repl, obj);
+        */
 
-	out.writeObject(repl);
+        //hessian/3a5a
+        int ref = out.writeObjectBegin(cl.getName());
 
-	out.replaceRef(repl, obj);
+        if (ref < -1) {
+          writeObject10(repl, out);
+        } else {
+          if (ref == -1) {
+            writeDefinition20(out);
+            out.writeObjectBegin(cl.getName());
+          }
 
-	return;
+          writeInstance(repl, out);
+        }
+
+        return;
       }
     } catch (RuntimeException e) {
       throw e;
@@ -221,8 +246,8 @@ public class JavaSerializer extends AbstractSerializer
     }
     else {
       if (ref == -1) {
-	writeDefinition20(out);
-	out.writeObjectBegin(cl.getName());
+        writeDefinition20(out);
+        out.writeObjectBegin(cl.getName());
       }
 
       writeInstance(obj, out);
@@ -236,7 +261,7 @@ public class JavaSerializer extends AbstractSerializer
       Field field = _fields[i];
 
       out.writeString(field.getName());
-	
+
       _fieldSerializers[i].serialize(out, obj, field);
     }
       
@@ -247,7 +272,7 @@ public class JavaSerializer extends AbstractSerializer
     throws IOException
   {
     out.writeClassFieldLength(_fields.length);
-	
+
     for (int i = 0; i < _fields.length; i++) {
       Field field = _fields[i];
       
@@ -255,29 +280,30 @@ public class JavaSerializer extends AbstractSerializer
     }
   }
   
+  @Override
   public void writeInstance(Object obj, AbstractHessianOutput out)
     throws IOException
   {
     try {
       for (int i = 0; i < _fields.length; i++) {
-	Field field = _fields[i];
+        Field field = _fields[i];
 
-	_fieldSerializers[i].serialize(out, obj, field);
+        _fieldSerializers[i].serialize(out, obj, field);
       }
     } catch (RuntimeException e) {
       throw new RuntimeException(e.getMessage() + "\n class: "
-				 + obj.getClass().getName()
-				 + " (object=" + obj + ")",
-				 e);
+                                 + obj.getClass().getName()
+                                 + " (object=" + obj + ")",
+                                 e);
     } catch (IOException e) {
       throw new IOExceptionWrapper(e.getMessage() + "\n class: "
-				   + obj.getClass().getName()
-				   + " (object=" + obj + ")",
-				   e);
+                                   + obj.getClass().getName()
+                                   + " (object=" + obj + ")",
+                                   e);
     }
   }
 
-  private static FieldSerializer getFieldSerializer(Class type)
+  private static FieldSerializer getFieldSerializer(Class<?> type)
   {
     if (int.class.equals(type)
         || byte.class.equals(type)
@@ -315,25 +341,25 @@ public class JavaSerializer extends AbstractSerializer
       throws IOException
     {
       Object value = null;
-	
+
       try {
-	value = field.get(obj);
+        value = field.get(obj);
       } catch (IllegalAccessException e) {
-	log.log(Level.FINE, e.toString(), e);
+        log.log(Level.FINE, e.toString(), e);
       }
 
       try {
-	out.writeObject(value);
+        out.writeObject(value);
       } catch (RuntimeException e) {
-	throw new RuntimeException(e.getMessage() + "\n field: "
-				   + field.getDeclaringClass().getName()
-				   + '.' + field.getName(),
-				   e);
+        throw new RuntimeException(e.getMessage() + "\n field: "
+                                   + field.getDeclaringClass().getName()
+                                   + '.' + field.getName(),
+                                   e);
       } catch (IOException e) {
-	throw new IOExceptionWrapper(e.getMessage() + "\n field: "
-				     + field.getDeclaringClass().getName()
-				     + '.' + field.getName(),
-				     e);
+        throw new IOExceptionWrapper(e.getMessage() + "\n field: "
+                                     + field.getDeclaringClass().getName()
+                                     + '.' + field.getName(),
+                                     e);
       }
     }
   }
@@ -345,11 +371,11 @@ public class JavaSerializer extends AbstractSerializer
       throws IOException
     {
       boolean value = false;
-	
+
       try {
-	value = field.getBoolean(obj);
+        value = field.getBoolean(obj);
       } catch (IllegalAccessException e) {
-	log.log(Level.FINE, e.toString(), e);
+        log.log(Level.FINE, e.toString(), e);
       }
 
       out.writeBoolean(value);
@@ -363,11 +389,11 @@ public class JavaSerializer extends AbstractSerializer
       throws IOException
     {
       int value = 0;
-	
+
       try {
-	value = field.getInt(obj);
+        value = field.getInt(obj);
       } catch (IllegalAccessException e) {
-	log.log(Level.FINE, e.toString(), e);
+        log.log(Level.FINE, e.toString(), e);
       }
 
       out.writeInt(value);
@@ -381,11 +407,11 @@ public class JavaSerializer extends AbstractSerializer
       throws IOException
     {
       long value = 0;
-	
+
       try {
-	value = field.getLong(obj);
+        value = field.getLong(obj);
       } catch (IllegalAccessException e) {
-	log.log(Level.FINE, e.toString(), e);
+        log.log(Level.FINE, e.toString(), e);
       }
 
       out.writeLong(value);
@@ -399,11 +425,11 @@ public class JavaSerializer extends AbstractSerializer
       throws IOException
     {
       double value = 0;
-	
+
       try {
-	value = field.getDouble(obj);
+        value = field.getDouble(obj);
       } catch (IllegalAccessException e) {
-	log.log(Level.FINE, e.toString(), e);
+        log.log(Level.FINE, e.toString(), e);
       }
 
       out.writeDouble(value);
@@ -417,11 +443,11 @@ public class JavaSerializer extends AbstractSerializer
       throws IOException
     {
       String value = null;
-	
+
       try {
-	value = (String) field.get(obj);
+        value = (String) field.get(obj);
       } catch (IllegalAccessException e) {
-	log.log(Level.FINE, e.toString(), e);
+        log.log(Level.FINE, e.toString(), e);
       }
 
       out.writeString(value);
diff --git a/com/caucho/hessian/io/ThrowableSerializer.java b/com/caucho/hessian/io/JavaUnsharedSerializer.java
similarity index 77%
copy from com/caucho/hessian/io/ThrowableSerializer.java
copy to com/caucho/hessian/io/JavaUnsharedSerializer.java
index c7303bb..1ce9e45 100644
--- a/com/caucho/hessian/io/ThrowableSerializer.java
+++ b/com/caucho/hessian/io/JavaUnsharedSerializer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001-2004 Caucho Technology, Inc.  All rights reserved.
+ * Copyright (c) 2001-2008 Caucho Technology, Inc.  All rights reserved.
  *
  * The Apache Software License, Version 1.1
  *
@@ -49,23 +49,38 @@
 package com.caucho.hessian.io;
 
 import java.io.IOException;
+import java.lang.ref.SoftReference;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.WeakHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 /**
  * Serializing an object for known object types.
  */
-public class ThrowableSerializer extends JavaSerializer {
-  public ThrowableSerializer(Class cl, ClassLoader loader)
+public class JavaUnsharedSerializer extends JavaSerializer
+{
+  private static final Logger log
+    = Logger.getLogger(JavaUnsharedSerializer.class.getName());
+  
+  public JavaUnsharedSerializer(Class<?> cl)
   {
     super(cl);
   }
   
+  @Override
   public void writeObject(Object obj, AbstractHessianOutput out)
     throws IOException
   {
-    Throwable e = (Throwable) obj;
-
-    e.getStackTrace();
-
-    super.writeObject(obj, out);
+    boolean oldUnshared = out.setUnshared(true);
+    
+    try {
+      super.writeObject(obj, out);
+    } finally {
+      out.setUnshared(oldUnshared);
+    }
   }
 }
diff --git a/com/caucho/hessian/io/LocaleHandle.java b/com/caucho/hessian/io/LocaleHandle.java
index 68239f8..d4ac7c8 100644
--- a/com/caucho/hessian/io/LocaleHandle.java
+++ b/com/caucho/hessian/io/LocaleHandle.java
@@ -73,10 +73,10 @@ public class LocaleHandle implements java.io.Serializable, HessianHandle {
 
     int i = 0;
     for (;
-	 i < len && ('a' <= (ch = s.charAt(i)) && ch <= 'z'
-		     || 'A' <= ch && ch <= 'Z'
-		     || '0' <= ch && ch <= '9');
-	 i++) {
+         i < len && ('a' <= (ch = s.charAt(i)) && ch <= 'z'
+                     || 'A' <= ch && ch <= 'Z'
+                     || '0' <= ch && ch <= '9');
+         i++) {
     }
 
     String language = s.substring(0, i);
@@ -87,10 +87,10 @@ public class LocaleHandle implements java.io.Serializable, HessianHandle {
       int head = ++i;
       
       for (;
-	   i < len && ('a' <= (ch = s.charAt(i)) && ch <= 'z'
-		       || 'A' <= ch && ch <= 'Z'
-		       || '0' <= ch && ch <= '9');
-	   i++) {
+           i < len && ('a' <= (ch = s.charAt(i)) && ch <= 'z'
+                       || 'A' <= ch && ch <= 'Z'
+                       || '0' <= ch && ch <= '9');
+           i++) {
       }
       
       country = s.substring(head, i);
@@ -100,10 +100,10 @@ public class LocaleHandle implements java.io.Serializable, HessianHandle {
       int head = ++i;
       
       for (;
-	   i < len && ('a' <= (ch = s.charAt(i)) && ch <= 'z'
-		       || 'A' <= ch && ch <= 'Z'
-		       || '0' <= ch && ch <= '9');
-	   i++) {
+           i < len && ('a' <= (ch = s.charAt(i)) && ch <= 'z'
+                       || 'A' <= ch && ch <= 'Z'
+                       || '0' <= ch && ch <= '9');
+           i++) {
       }
       
       var = s.substring(head, i);
diff --git a/com/caucho/hessian/io/MapDeserializer.java b/com/caucho/hessian/io/MapDeserializer.java
index 8a9197b..246f6ab 100644
--- a/com/caucho/hessian/io/MapDeserializer.java
+++ b/com/caucho/hessian/io/MapDeserializer.java
@@ -69,14 +69,14 @@ public class MapDeserializer extends AbstractMapDeserializer {
     Constructor<?> []ctors = type.getConstructors();
     for (int i = 0; i < ctors.length; i++) {
       if (ctors[i].getParameterTypes().length == 0)
-	_ctor = ctors[i];
+        _ctor = ctors[i];
     }
 
     if (_ctor == null) {
       try {
-	_ctor = HashMap.class.getConstructor(new Class[0]);
+        _ctor = HashMap.class.getConstructor(new Class[0]);
       } catch (Exception e) {
-	throw new IllegalStateException(e);
+        throw new IllegalStateException(e);
       }
     }
   }
@@ -121,7 +121,7 @@ public class MapDeserializer extends AbstractMapDeserializer {
 
   @Override
   public Object readObject(AbstractHessianInput in,
-			   Object []fields)
+                           Object []fields)
     throws IOException
   {
     String []fieldNames = (String []) fields;
diff --git a/com/caucho/hessian/io/MapSerializer.java b/com/caucho/hessian/io/MapSerializer.java
index 42d8986..818e40f 100644
--- a/com/caucho/hessian/io/MapSerializer.java
+++ b/com/caucho/hessian/io/MapSerializer.java
@@ -83,14 +83,30 @@ public class MapSerializer extends AbstractSerializer {
 
     Map map = (Map) obj;
 
-    Class cl = obj.getClass();
+    Class<?> cl = obj.getClass();
     
     if (cl.equals(HashMap.class)
-	|| ! _isSendJavaType
-	|| ! (obj instanceof java.io.Serializable))
+        || ! (obj instanceof java.io.Serializable))
       out.writeMapBegin(null);
-    else
-      out.writeMapBegin(obj.getClass().getName());
+    else if (! _isSendJavaType) {
+      // hessian/3a19
+      for (; cl != null; cl = cl.getSuperclass()) {
+        if (cl.equals(HashMap.class)) {
+          out.writeMapBegin(null);
+          break;
+        }
+        else if (cl.getName().startsWith("java.")) {
+          out.writeMapBegin(cl.getName());
+          break;
+        }
+      }
+      
+      if (cl == null)
+        out.writeMapBegin(null);
+    }
+    else {
+      out.writeMapBegin(cl.getName());
+    }
 
     Iterator iter = map.entrySet().iterator();
     while (iter.hasNext()) {
diff --git a/com/caucho/hessian/io/ObjectHandleSerializer.java b/com/caucho/hessian/io/ObjectHandleSerializer.java
index bb4c429..781a3f2 100644
--- a/com/caucho/hessian/io/ObjectHandleSerializer.java
+++ b/com/caucho/hessian/io/ObjectHandleSerializer.java
@@ -63,18 +63,18 @@ public class ObjectHandleSerializer extends AbstractSerializer {
       out.writeNull();
     else {
       if (out.addRef(obj))
-	return;
+        return;
       
       int ref = out.writeObjectBegin("object");
 
       if (ref < -1) {
-	out.writeMapEnd();
+        out.writeMapEnd();
       }
       else {
-	if (ref == -1) {
-	  out.writeInt(0);
-	  out.writeObjectBegin("object");
-	}
+        if (ref == -1) {
+          out.writeInt(0);
+          out.writeObjectBegin("object");
+        }
       }
     }
   }
diff --git a/com/caucho/hessian/io/ObjectNameDeserializer.java b/com/caucho/hessian/io/ObjectNameDeserializer.java
index eff0d20..8597f99 100644
--- a/com/caucho/hessian/io/ObjectNameDeserializer.java
+++ b/com/caucho/hessian/io/ObjectNameDeserializer.java
@@ -48,7 +48,6 @@
 
 package com.caucho.hessian.io;
 
-import java.io.IOException;
 import javax.management.ObjectName;
 
 import com.caucho.hessian.HessianException;
@@ -58,7 +57,7 @@ import com.caucho.hessian.HessianException;
  */
 public class ObjectNameDeserializer extends AbstractStringValueDeserializer {
   @Override
-  public Class getType()
+  public Class<?> getType()
   {
     return ObjectName.class;
   }
diff --git a/com/caucho/hessian/io/SerializerFactory.java b/com/caucho/hessian/io/SerializerFactory.java
index 54ad118..09bb94d 100644
--- a/com/caucho/hessian/io/SerializerFactory.java
+++ b/com/caucho/hessian/io/SerializerFactory.java
@@ -57,6 +57,7 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.lang.annotation.Annotation;
 import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
 import java.util.concurrent.ConcurrentHashMap;
 import javax.management.*;
 
@@ -81,7 +82,7 @@ public class SerializerFactory extends AbstractSerializerFactory
     = new WeakHashMap<ClassLoader,SoftReference<SerializerFactory>>();
 
   private ContextSerializerFactory _contextFactory;
-  private ClassLoader _loader;
+  private WeakReference<ClassLoader> _loaderRef;
 
   protected Serializer _defaultSerializer;
 
@@ -109,7 +110,7 @@ public class SerializerFactory extends AbstractSerializerFactory
 
   public SerializerFactory(ClassLoader loader)
   {
-    _loader = loader;
+    _loaderRef = new WeakReference<ClassLoader>(loader);
 
     _contextFactory = ContextSerializerFactory.create(loader);
   }
@@ -141,7 +142,7 @@ public class SerializerFactory extends AbstractSerializerFactory
 
   public ClassLoader getClassLoader()
   {
-    return _loader;
+    return _loaderRef.get();
   }
 
   /**
@@ -231,7 +232,7 @@ public class SerializerFactory extends AbstractSerializerFactory
     return serializer;
   }
 
-  protected Serializer loadSerializer(Class cl)
+  protected Serializer loadSerializer(Class<?> cl)
     throws HessianProtocolException
   {
     Serializer serializer = null;
@@ -277,7 +278,7 @@ public class SerializerFactory extends AbstractSerializerFactory
     else if (JavaSerializer.getWriteReplace(cl) != null) {
       Serializer baseSerializer = getDefaultSerializer(cl);
       
-      return new WriteReplaceSerializer(cl, _loader, baseSerializer);
+      return new WriteReplaceSerializer(cl, getClassLoader(), baseSerializer);
     }
 
     else if (Map.class.isAssignableFrom(cl)) {
@@ -415,26 +416,29 @@ public class SerializerFactory extends AbstractSerializerFactory
     if (Collection.class.isAssignableFrom(cl))
       deserializer = new CollectionDeserializer(cl);
 
-    else if (Map.class.isAssignableFrom(cl))
+    else if (Map.class.isAssignableFrom(cl)) {
       deserializer = new MapDeserializer(cl);
-
-    else if (Annotation.class.isAssignableFrom(cl))
+    }
+    else if (Iterator.class.isAssignableFrom(cl)) {
+      deserializer = IteratorDeserializer.create();
+    }
+    else if (Annotation.class.isAssignableFrom(cl)) {
       deserializer = new AnnotationDeserializer(cl);
-
-    else if (cl.isInterface())
+    }
+    else if (cl.isInterface()) {
       deserializer = new ObjectDeserializer(cl);
-
-    else if (cl.isArray())
+    }
+    else if (cl.isArray()) {
       deserializer = new ArrayDeserializer(cl.getComponentType());
-
-    else if (Enumeration.class.isAssignableFrom(cl))
+    }
+    else if (Enumeration.class.isAssignableFrom(cl)) {
       deserializer = EnumerationDeserializer.create();
-
+    }
     else if (Enum.class.isAssignableFrom(cl))
       deserializer = new EnumDeserializer(cl);
 
     else if (Class.class.equals(cl))
-      deserializer = new ClassDeserializer(_loader);
+      deserializer = new ClassDeserializer(getClassLoader());
 
     else
       deserializer = getDefaultDeserializer(cl);
@@ -663,10 +667,10 @@ public class SerializerFactory extends AbstractSerializerFactory
     }
     else {
       try {
-        Class cl = Class.forName(type, false, _loader);
+        Class cl = Class.forName(type, false, getClassLoader());
         deserializer = getDeserializer(cl);
       } catch (Exception e) {
-        log.warning("Hessian/Burlap: '" + type + "' is an unknown class in " + _loader + ":\n" + e);
+        log.warning("Hessian/Burlap: '" + type + "' is an unknown class in " + getClassLoader() + ":\n" + e);
 
         log.log(Level.FINER, e.toString(), e);
       }
@@ -704,6 +708,7 @@ public class SerializerFactory extends AbstractSerializerFactory
     addBasic(Double.class, "double", BasicSerializer.DOUBLE);
     addBasic(Character.class, "char", BasicSerializer.CHARACTER_OBJECT);
     addBasic(String.class, "string", BasicSerializer.STRING);
+    addBasic(StringBuilder.class, "string", BasicSerializer.STRING_BUILDER);
     addBasic(Object.class, "object", BasicSerializer.OBJECT);
     addBasic(java.util.Date.class, "date", BasicSerializer.DATE);
 
diff --git a/com/caucho/hessian/io/SqlDateDeserializer.java b/com/caucho/hessian/io/SqlDateDeserializer.java
index b54979d..9185cc3 100644
--- a/com/caucho/hessian/io/SqlDateDeserializer.java
+++ b/com/caucho/hessian/io/SqlDateDeserializer.java
@@ -86,9 +86,9 @@ public class SqlDateDeserializer extends AbstractDeserializer {
       String key = in.readString();
 
       if (key.equals("value"))
-	initValue = in.readUTCDate();
+        initValue = in.readUTCDate();
       else
-	in.readString();
+        in.readString();
     }
 
     in.readMapEnd();
@@ -114,9 +114,9 @@ public class SqlDateDeserializer extends AbstractDeserializer {
       String key = fieldNames[i];
 
       if (key.equals("value"))
-	initValue = in.readUTCDate();
+        initValue = in.readUTCDate();
       else
-	in.readObject();
+        in.readObject();
     }
 
     Object value = create(initValue);
diff --git a/com/caucho/hessian/io/SqlDateSerializer.java b/com/caucho/hessian/io/SqlDateSerializer.java
index 2c12884..764b0a4 100644
--- a/com/caucho/hessian/io/SqlDateSerializer.java
+++ b/com/caucho/hessian/io/SqlDateSerializer.java
@@ -65,23 +65,23 @@ public class SqlDateSerializer extends AbstractSerializer
       Class cl = obj.getClass();
 
       if (out.addRef(obj))
-	return;
+        return;
       
       int ref = out.writeObjectBegin(cl.getName());
 
       if (ref < -1) {
-	out.writeString("value");
-	out.writeUTCDate(((Date) obj).getTime());
-	out.writeMapEnd();
+        out.writeString("value");
+        out.writeUTCDate(((Date) obj).getTime());
+        out.writeMapEnd();
       }
       else {
-	if (ref == -1) {
-	  out.writeInt(1);
-	  out.writeString("value");
-	  out.writeObjectBegin(cl.getName());
-	}
+        if (ref == -1) {
+          out.writeInt(1);
+          out.writeString("value");
+          out.writeObjectBegin(cl.getName());
+        }
 
-	out.writeUTCDate(((Date) obj).getTime());
+        out.writeUTCDate(((Date) obj).getTime());
       }
     }
   }
diff --git a/com/caucho/hessian/io/StringValueDeserializer.java b/com/caucho/hessian/io/StringValueDeserializer.java
index 22718d7..6aee3cf 100644
--- a/com/caucho/hessian/io/StringValueDeserializer.java
+++ b/com/caucho/hessian/io/StringValueDeserializer.java
@@ -87,7 +87,7 @@ public class StringValueDeserializer extends AbstractStringValueDeserializer {
       return _constructor.newInstance(new Object[] { value });
     } catch (Exception e) {
       throw new HessianException(_cl.getName() + ": value=" + value + "\n" + e,
-				 e);
+                                 e);
     }
   }
 }
diff --git a/com/caucho/hessian/io/StringValueSerializer.java b/com/caucho/hessian/io/StringValueSerializer.java
index b77b2bf..5740567 100644
--- a/com/caucho/hessian/io/StringValueSerializer.java
+++ b/com/caucho/hessian/io/StringValueSerializer.java
@@ -63,25 +63,25 @@ public class StringValueSerializer extends AbstractSerializer {
       out.writeNull();
     else {
       if (out.addRef(obj))
-	return;
+        return;
       
       Class cl = obj.getClass();
 
       int ref = out.writeObjectBegin(cl.getName());
 
       if (ref < -1) {
-	out.writeString("value");
-	out.writeString(obj.toString());
-	out.writeMapEnd();
+        out.writeString("value");
+        out.writeString(obj.toString());
+        out.writeMapEnd();
       }
       else {
-	if (ref == -1) {
-	  out.writeInt(1);
-	  out.writeString("value");
-	  out.writeObjectBegin(cl.getName());
-	}
+        if (ref == -1) {
+          out.writeInt(1);
+          out.writeString("value");
+          out.writeObjectBegin(cl.getName());
+        }
 
-	out.writeString(obj.toString());
+        out.writeString(obj.toString());
       }
     }
   }
diff --git a/com/caucho/hessian/io/ThrowableSerializer.java b/com/caucho/hessian/io/ThrowableSerializer.java
index c7303bb..5c5173b 100644
--- a/com/caucho/hessian/io/ThrowableSerializer.java
+++ b/com/caucho/hessian/io/ThrowableSerializer.java
@@ -54,11 +54,12 @@ import java.io.IOException;
  * Serializing an object for known object types.
  */
 public class ThrowableSerializer extends JavaSerializer {
-  public ThrowableSerializer(Class cl, ClassLoader loader)
+  public ThrowableSerializer(Class<?> cl, ClassLoader loader)
   {
     super(cl);
   }
   
+  @Override
   public void writeObject(Object obj, AbstractHessianOutput out)
     throws IOException
   {
diff --git a/com/caucho/hessian/io/UnsafeDeserializer.java b/com/caucho/hessian/io/UnsafeDeserializer.java
index 32e2f34..f8891e0 100644
--- a/com/caucho/hessian/io/UnsafeDeserializer.java
+++ b/com/caucho/hessian/io/UnsafeDeserializer.java
@@ -389,6 +389,8 @@ public class UnsafeDeserializer extends AbstractMapDeserializer {
   
   static class NullFieldDeserializer extends FieldDeserializer {
     static NullFieldDeserializer DESER = new NullFieldDeserializer();
+    
+    @Override
     void deserialize(AbstractHessianInput in, Object obj)
       throws IOException
     {
@@ -690,9 +692,14 @@ public class UnsafeDeserializer extends AbstractMapDeserializer {
 
       try {
         java.util.Date date = (java.util.Date) in.readObject();
-        value = new java.sql.Date(date.getTime());
+        
+        if (date != null) {
+          value = new java.sql.Date(date.getTime());
 
-        _unsafe.putObject(obj, _offset, value);
+          _unsafe.putObject(obj, _offset, value);
+        } else {
+          _unsafe.putObject(obj, _offset, null);
+        }
       } catch (Exception e) {
         logDeserializeError(_field, obj, value, e);
       }
@@ -718,9 +725,15 @@ public class UnsafeDeserializer extends AbstractMapDeserializer {
 
       try {
         java.util.Date date = (java.util.Date) in.readObject();
-        value = new java.sql.Timestamp(date.getTime());
+        
+        if (date != null) {
+          value = new java.sql.Timestamp(date.getTime());
 
-        _unsafe.putObject(obj, _offset, value);
+          _unsafe.putObject(obj, _offset, value);
+        }
+        else {
+          _unsafe.putObject(obj, _offset, null);
+        }
       } catch (Exception e) {
         logDeserializeError(_field, obj, value, e);
       }
@@ -746,9 +759,14 @@ public class UnsafeDeserializer extends AbstractMapDeserializer {
 
       try {
         java.util.Date date = (java.util.Date) in.readObject();
-        value = new java.sql.Time(date.getTime());
+        
+        if (date != null) {
+          value = new java.sql.Time(date.getTime());
 
-        _unsafe.putObject(obj, _offset, value);
+          _unsafe.putObject(obj, _offset, value);
+        } else {
+          _unsafe.putObject(obj, _offset, null);
+        }
       } catch (Exception e) {
         logDeserializeError(_field, obj, value, e);
       }
diff --git a/com/caucho/hessian/io/UnsafeSerializer.java b/com/caucho/hessian/io/UnsafeSerializer.java
index c0addb2..e0828cc 100644
--- a/com/caucho/hessian/io/UnsafeSerializer.java
+++ b/com/caucho/hessian/io/UnsafeSerializer.java
@@ -59,6 +59,8 @@ import java.util.WeakHashMap;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import com.caucho.hessian.HessianUnshared;
+
 import sun.misc.Unsafe;
 
 /**
@@ -70,7 +72,7 @@ public class UnsafeSerializer extends AbstractSerializer
     = Logger.getLogger(UnsafeSerializer.class.getName());
 
   private static boolean _isEnabled;
-  private static Unsafe _unsafe;
+  private static final Unsafe _unsafe;
   
   private static final WeakHashMap<Class<?>,SoftReference<UnsafeSerializer>> _serializerMap
     = new WeakHashMap<Class<?>,SoftReference<UnsafeSerializer>>();
@@ -101,7 +103,11 @@ public class UnsafeSerializer extends AbstractSerializer
       UnsafeSerializer base = baseRef != null ? baseRef.get() : null;
 
       if (base == null) {
-        base = new UnsafeSerializer(cl);
+        if (cl.isAnnotationPresent(HessianUnshared.class))
+          base = new UnsafeUnsharedSerializer(cl);
+        else
+          base = new UnsafeSerializer(cl);
+        
         baseRef = new SoftReference<UnsafeSerializer>(base);
         _serializerMap.put(cl, baseRef);
       }
@@ -533,30 +539,32 @@ public class UnsafeSerializer extends AbstractSerializer
   
   static {
     boolean isEnabled = false;
+    Unsafe unsafe = null;
     
     try {
-      Class unsafe = Class.forName("sun.misc.Unsafe");
+      Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
       Field theUnsafe = null;
-      for (Field field : unsafe.getDeclaredFields()) {
+      for (Field field : unsafeClass.getDeclaredFields()) {
         if (field.getName().equals("theUnsafe"))
           theUnsafe = field;
       }
       
       if (theUnsafe != null) {
         theUnsafe.setAccessible(true);
-        _unsafe = (Unsafe) theUnsafe.get(null);
+        unsafe = (Unsafe) theUnsafe.get(null);
       }
       
-      isEnabled = _unsafe != null;
+      isEnabled = unsafe != null;
       
       String unsafeProp = System.getProperty("com.caucho.hessian.unsafe");
       
       if ("false".equals(unsafeProp))
         isEnabled = false;
     } catch (Throwable e) {
-      log.log(Level.FINER, e.toString(), e);
+      log.log(Level.ALL, e.toString(), e);
     }
     
+    _unsafe = unsafe;
     _isEnabled = isEnabled;
   }
 }
diff --git a/com/caucho/hessian/io/ThrowableSerializer.java b/com/caucho/hessian/io/UnsafeUnsharedSerializer.java
similarity index 77%
copy from com/caucho/hessian/io/ThrowableSerializer.java
copy to com/caucho/hessian/io/UnsafeUnsharedSerializer.java
index c7303bb..c3dc53c 100644
--- a/com/caucho/hessian/io/ThrowableSerializer.java
+++ b/com/caucho/hessian/io/UnsafeUnsharedSerializer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001-2004 Caucho Technology, Inc.  All rights reserved.
+ * Copyright (c) 2001-2008 Caucho Technology, Inc.  All rights reserved.
  *
  * The Apache Software License, Version 1.1
  *
@@ -49,23 +49,38 @@
 package com.caucho.hessian.io;
 
 import java.io.IOException;
+import java.lang.ref.SoftReference;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.WeakHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 /**
  * Serializing an object for known object types.
  */
-public class ThrowableSerializer extends JavaSerializer {
-  public ThrowableSerializer(Class cl, ClassLoader loader)
+public class UnsafeUnsharedSerializer extends UnsafeSerializer
+{
+  private static final Logger log
+    = Logger.getLogger(UnsafeUnsharedSerializer.class.getName());
+  
+  public UnsafeUnsharedSerializer(Class<?> cl)
   {
     super(cl);
   }
   
+  @Override
   public void writeObject(Object obj, AbstractHessianOutput out)
     throws IOException
   {
-    Throwable e = (Throwable) obj;
-
-    e.getStackTrace();
-
-    super.writeObject(obj, out);
+    boolean oldUnshared = out.setUnshared(true);
+    
+    try {
+      super.writeObject(obj, out);
+    } finally {
+      out.setUnshared(oldUnshared);
+    }
   }
 }
diff --git a/com/caucho/hessian/io/ValueDeserializer.java b/com/caucho/hessian/io/ValueDeserializer.java
index d4d7ac0..35148c3 100644
--- a/com/caucho/hessian/io/ValueDeserializer.java
+++ b/com/caucho/hessian/io/ValueDeserializer.java
@@ -65,7 +65,7 @@ abstract public class ValueDeserializer extends AbstractDeserializer {
       if (key.equals("value"))
         initValue = in.readString();
       else
-	in.readObject();
+        in.readObject();
     }
 
     in.readMapEnd();
@@ -82,7 +82,7 @@ abstract public class ValueDeserializer extends AbstractDeserializer {
       if ("value".equals(fieldNames[i]))
         initValue = in.readString();
       else
-	in.readObject();
+        in.readObject();
     }
 
     return create(initValue);
diff --git a/com/caucho/hessian/io/WriteReplaceSerializer.java b/com/caucho/hessian/io/WriteReplaceSerializer.java
index 1479117..342ab4c 100644
--- a/com/caucho/hessian/io/WriteReplaceSerializer.java
+++ b/com/caucho/hessian/io/WriteReplaceSerializer.java
@@ -74,8 +74,8 @@ public class WriteReplaceSerializer extends AbstractSerializer
   private Serializer _baseSerializer;
   
   public WriteReplaceSerializer(Class<?> cl,
-				ClassLoader loader,
-				Serializer baseSerializer)
+                                ClassLoader loader,
+                                Serializer baseSerializer)
   {
     introspectWriteReplace(cl, loader);
     
@@ -94,8 +94,8 @@ public class WriteReplaceSerializer extends AbstractSerializer
       Method writeReplace = getWriteReplace(serializerClass, cl);
 
       if (writeReplace != null) {
-	_writeReplaceFactory = serializerObject;
-	_writeReplace = writeReplace;
+        _writeReplaceFactory = serializerObject;
+        _writeReplace = writeReplace;
       }
     } catch (ClassNotFoundException e) {
     } catch (Exception e) {
@@ -114,10 +114,10 @@ public class WriteReplaceSerializer extends AbstractSerializer
   {
     for (; cl != null; cl = cl.getSuperclass()) {
       for (Method method : cl.getDeclaredMethods()) {
-	if (method.getName().equals("writeReplace")
-	    && method.getParameterTypes().length == 1
-	    && param.equals(method.getParameterTypes()[0]))
-	  return method;
+        if (method.getName().equals("writeReplace")
+            && method.getParameterTypes().length == 1
+            && param.equals(method.getParameterTypes()[0]))
+          return method;
       }
     }
 
@@ -133,11 +133,11 @@ public class WriteReplaceSerializer extends AbstractSerializer
       Method []methods = cl.getDeclaredMethods();
       
       for (int i = 0; i < methods.length; i++) {
-	Method method = methods[i];
+        Method method = methods[i];
 
-	if (method.getName().equals("writeReplace") &&
-	    method.getParameterTypes().length == 0)
-	  return method;
+        if (method.getName().equals("writeReplace") &&
+            method.getParameterTypes().length == 0)
+          return method;
       }
     }
 
@@ -166,6 +166,7 @@ public class WriteReplaceSerializer extends AbstractSerializer
         }
         
         _baseSerializer.writeObject(obj, out);
+
         return;
       }
 
diff --git a/com/caucho/hessian/jmx/MBeanAttributeInfoDeserializer.java b/com/caucho/hessian/jmx/MBeanAttributeInfoDeserializer.java
index e558493..7c0c931 100644
--- a/com/caucho/hessian/jmx/MBeanAttributeInfoDeserializer.java
+++ b/com/caucho/hessian/jmx/MBeanAttributeInfoDeserializer.java
@@ -77,19 +77,19 @@ public class MBeanAttributeInfoDeserializer extends AbstractDeserializer {
       String key = in.readString();
 
       if ("name".equals(key))
-	name = in.readString();
+        name = in.readString();
       else if ("attributeType".equals(key))
-	type = in.readString();
+        type = in.readString();
       else if ("description".equals(key))
-	description = in.readString();
+        description = in.readString();
       else if ("isRead".equals(key))
-	isRead = in.readBoolean();
+        isRead = in.readBoolean();
       else if ("isWrite".equals(key))
-	isWrite = in.readBoolean();
+        isWrite = in.readBoolean();
       else if ("is".equals(key))
-	isIs = in.readBoolean();
+        isIs = in.readBoolean();
       else {
-	in.readObject();
+        in.readObject();
       }
     }
 
@@ -99,7 +99,7 @@ public class MBeanAttributeInfoDeserializer extends AbstractDeserializer {
       MBeanAttributeInfo info;
 
       info = new MBeanAttributeInfo(name, type, description,
-				    isRead, isWrite, isIs);
+                                    isRead, isWrite, isIs);
 
       return info;
     } catch (Exception e) {
diff --git a/com/caucho/hessian/jmx/MBeanConstructorInfoDeserializer.java b/com/caucho/hessian/jmx/MBeanConstructorInfoDeserializer.java
index 67e6b57..ce8db5c 100644
--- a/com/caucho/hessian/jmx/MBeanConstructorInfoDeserializer.java
+++ b/com/caucho/hessian/jmx/MBeanConstructorInfoDeserializer.java
@@ -75,13 +75,13 @@ public class MBeanConstructorInfoDeserializer extends AbstractDeserializer {
       String key = in.readString();
 
       if ("name".equals(key))
-	name = in.readString();
+        name = in.readString();
       else if ("description".equals(key))
-	description = in.readString();
+        description = in.readString();
       else if ("signature".equals(key))
-	sig = (MBeanParameterInfo[]) in.readObject(MBeanParameterInfo[].class);
+        sig = (MBeanParameterInfo[]) in.readObject(MBeanParameterInfo[].class);
       else {
-	in.readObject();
+        in.readObject();
       }
     }
 
diff --git a/com/caucho/hessian/jmx/MBeanInfoDeserializer.java b/com/caucho/hessian/jmx/MBeanInfoDeserializer.java
index c64271d..2222eab 100644
--- a/com/caucho/hessian/jmx/MBeanInfoDeserializer.java
+++ b/com/caucho/hessian/jmx/MBeanInfoDeserializer.java
@@ -81,20 +81,20 @@ public class MBeanInfoDeserializer extends AbstractDeserializer {
       String key = in.readString();
 
       if ("className".equals(key))
-	className = in.readString();
+        className = in.readString();
       else if ("description".equals(key))
-	description = in.readString();
+        description = in.readString();
       else if ("attributes".equals(key)) {
-	attributes = (MBeanAttributeInfo []) in.readObject(MBeanAttributeInfo[].class);
+        attributes = (MBeanAttributeInfo []) in.readObject(MBeanAttributeInfo[].class);
       }
       /*
       else if ("isWrite".equals(key))
-	isWrite = in.readBoolean();
+        isWrite = in.readBoolean();
       else if ("isIs".equals(key))
-	isIs = in.readBoolean();
+        isIs = in.readBoolean();
       */
       else
-	in.readObject();
+        in.readObject();
     }
 
     in.readMapEnd();
@@ -103,7 +103,7 @@ public class MBeanInfoDeserializer extends AbstractDeserializer {
       MBeanInfo info;
       
       info = new MBeanInfo(className, description, attributes,
-			   constructors, operations, notifications);
+                           constructors, operations, notifications);
 
       return info;
     } catch (Exception e) {
diff --git a/com/caucho/hessian/jmx/MBeanNotificationInfoDeserializer.java b/com/caucho/hessian/jmx/MBeanNotificationInfoDeserializer.java
index 7014625..c307b38 100644
--- a/com/caucho/hessian/jmx/MBeanNotificationInfoDeserializer.java
+++ b/com/caucho/hessian/jmx/MBeanNotificationInfoDeserializer.java
@@ -74,13 +74,13 @@ public class MBeanNotificationInfoDeserializer extends AbstractDeserializer {
       String key = in.readString();
 
       if ("name".equals(key))
-	name = in.readString();
+        name = in.readString();
       else if ("description".equals(key))
-	description = in.readString();
+        description = in.readString();
       else if ("types".equals(key))
-	types = (String[]) in.readObject(String[].class);
+        types = (String[]) in.readObject(String[].class);
       else {
-	in.readObject();
+        in.readObject();
       }
     }
 
diff --git a/com/caucho/hessian/jmx/MBeanOperationInfoDeserializer.java b/com/caucho/hessian/jmx/MBeanOperationInfoDeserializer.java
index 8abd9f8..83412b2 100644
--- a/com/caucho/hessian/jmx/MBeanOperationInfoDeserializer.java
+++ b/com/caucho/hessian/jmx/MBeanOperationInfoDeserializer.java
@@ -77,18 +77,18 @@ public class MBeanOperationInfoDeserializer extends AbstractDeserializer {
       String key = in.readString();
 
       if ("name".equals(key))
-	name = in.readString();
+        name = in.readString();
       else if ("description".equals(key))
-	description = in.readString();
+        description = in.readString();
       else if ("type".equals(key))
-	type = in.readString();
+        type = in.readString();
       else if ("impact".equals(key))
-	impact = in.readInt();
+        impact = in.readInt();
       else if ("signature".equals(key)) {
-	sig = (MBeanParameterInfo[]) in.readObject(MBeanParameterInfo[].class);
+        sig = (MBeanParameterInfo[]) in.readObject(MBeanParameterInfo[].class);
       }
       else {
-	in.readObject();
+        in.readObject();
       }
     }
 
diff --git a/com/caucho/hessian/jmx/MBeanParameterInfoDeserializer.java b/com/caucho/hessian/jmx/MBeanParameterInfoDeserializer.java
index 1b94a7d..074bc2a 100644
--- a/com/caucho/hessian/jmx/MBeanParameterInfoDeserializer.java
+++ b/com/caucho/hessian/jmx/MBeanParameterInfoDeserializer.java
@@ -77,13 +77,13 @@ public class MBeanParameterInfoDeserializer extends AbstractDeserializer {
       String key = in.readString();
 
       if ("name".equals(key))
-	name = in.readString();
+        name = in.readString();
       else if ("type".equals(key))
-	type = in.readString();
+        type = in.readString();
       else if ("description".equals(key))
-	description = in.readString();
+        description = in.readString();
       else {
-	in.readObject();
+        in.readObject();
       }
     }
 
diff --git a/com/caucho/hessian/jmx/ObjectInstanceDeserializer.java b/com/caucho/hessian/jmx/ObjectInstanceDeserializer.java
index 7d86b6b..d917454 100644
--- a/com/caucho/hessian/jmx/ObjectInstanceDeserializer.java
+++ b/com/caucho/hessian/jmx/ObjectInstanceDeserializer.java
@@ -76,11 +76,11 @@ public class ObjectInstanceDeserializer extends AbstractDeserializer {
       String key = in.readString();
 
       if ("className".equals(key))
-	className = in.readString();
+        className = in.readString();
       else if ("name".equals(key))
-	objectName = (ObjectName) in.readObject(ObjectName.class);
+        objectName = (ObjectName) in.readObject(ObjectName.class);
       else
-	in.readObject();
+        in.readObject();
     }
 
     in.readMapEnd();
diff --git a/com/caucho/hessian/security/X509Encryption.java b/com/caucho/hessian/security/X509Encryption.java
index 885545e..1c8018b 100644
--- a/com/caucho/hessian/security/X509Encryption.java
+++ b/com/caucho/hessian/security/X509Encryption.java
@@ -169,7 +169,7 @@ public class X509Encryption extends HessianEnvelope {
 
     if (! method.equals(getClass().getName()))
       throw new IOException("expected hessian Envelope method '" +
-			    getClass().getName() + "' at '" + method + "'");
+                            getClass().getName() + "' at '" + method + "'");
 
     return unwrapHeaders(in);
   }
@@ -280,12 +280,12 @@ public class X509Encryption extends HessianEnvelope {
       _out = null;
 
       if (out != null) {
-	_cipherOut.close();
-	_bodyOut.close();
+        _cipherOut.close();
+        _bodyOut.close();
 
-	out.writeInt(0);
+        out.writeInt(0);
         out.completeEnvelope();
-	out.close();
+        out.close();
       }
     }
   }
@@ -363,17 +363,17 @@ public class X509Encryption extends HessianEnvelope {
       _in = null;
 
       if (in != null) {
-	_cipherIn.close();
-	_bodyIn.close();
+        _cipherIn.close();
+        _bodyIn.close();
 
-	int len = in.readInt();
+        int len = in.readInt();
 
-	if (len != 0)
-	  throw new IOException("Unexpected footer");
+        if (len != 0)
+          throw new IOException("Unexpected footer");
 
         in.completeEnvelope();
 
-	in.close();
+        in.close();
       }
     }
   }
diff --git a/com/caucho/hessian/security/X509Signature.java b/com/caucho/hessian/security/X509Signature.java
index 7116e57..0fcd64c 100644
--- a/com/caucho/hessian/security/X509Signature.java
+++ b/com/caucho/hessian/security/X509Signature.java
@@ -164,7 +164,7 @@ public class X509Signature extends HessianEnvelope {
 
     if (! method.equals(getClass().getName()))
       throw new IOException("expected hessian Envelope method '" +
-			    getClass().getName() + "' at '" + method + "'");
+                            getClass().getName() + "' at '" + method + "'");
 
     return unwrapHeaders(in);
   }
@@ -261,7 +261,7 @@ public class X509Signature extends HessianEnvelope {
       _out = null;
 
       if (out == null)
-	return;
+        return;
       
       _bodyOut.close();
 
@@ -334,7 +334,7 @@ public class X509Signature extends HessianEnvelope {
       int ch = _bodyIn.read();
 
       if (ch < 0)
-	return ch;
+        return ch;
 
       _mac.update((byte) ch);
 
@@ -347,7 +347,7 @@ public class X509Signature extends HessianEnvelope {
       int len = _bodyIn.read(buffer, offset, length);
 
       if (len < 0)
-	return len;
+        return len;
 
       _mac.update(buffer, offset, len);
 
@@ -361,36 +361,36 @@ public class X509Signature extends HessianEnvelope {
       _in = null;
 
       if (in != null) {
-	_bodyIn.close();
+        _bodyIn.close();
 
-	int len = in.readInt();
-	byte []signature = null;
+        int len = in.readInt();
+        byte []signature = null;
 
-	for (int i = 0; i < len; i++) {
-	  String header = in.readString();
+        for (int i = 0; i < len; i++) {
+          String header = in.readString();
 
-	  if ("signature".equals(header))
-	    signature = in.readBytes();
-	}
+          if ("signature".equals(header))
+            signature = in.readBytes();
+        }
 
         in.completeEnvelope();
         in.close();
           
 
-	if (signature == null)
-	  throw new IOException("Expected signature");
+        if (signature == null)
+          throw new IOException("Expected signature");
 
-	byte []sig = _mac.doFinal();
+        byte []sig = _mac.doFinal();
 
-	if (sig.length != signature.length)
-	  throw new IOException("mismatched signature");
+        if (sig.length != signature.length)
+          throw new IOException("mismatched signature");
 
-	for (int i = 0; i < sig.length; i++) {
-	  if (signature[i] != sig[i])
-	    throw new IOException("mismatched signature");
-	}
+        for (int i = 0; i < sig.length; i++) {
+          if (signature[i] != sig[i])
+            throw new IOException("mismatched signature");
+        }
 
-	// XXX: save principal
+        // XXX: save principal
       }
     }
   }
diff --git a/com/caucho/hessian/server/HessianServlet.java b/com/caucho/hessian/server/HessianServlet.java
index d074954..7cef0a3 100644
--- a/com/caucho/hessian/server/HessianServlet.java
+++ b/com/caucho/hessian/server/HessianServlet.java
@@ -48,10 +48,12 @@
 
 package com.caucho.hessian.server;
 
-import com.caucho.hessian.io.*;
-import com.caucho.services.server.GenericService;
-import com.caucho.services.server.Service;
-import com.caucho.services.server.ServiceContext;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.logging.Logger;
 
 import javax.servlet.GenericServlet;
 import javax.servlet.Servlet;
@@ -59,21 +61,24 @@ import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.io.*;
-import java.util.logging.*;
+
+import com.caucho.hessian.io.Hessian2Input;
+import com.caucho.hessian.io.SerializerFactory;
+import com.caucho.services.server.Service;
+import com.caucho.services.server.ServiceContext;
 
 /**
  * Servlet for serving Hessian services.
  */
-public class HessianServlet extends GenericServlet {
-  private Logger _log = Logger.getLogger(HessianServlet.class.getName());
-  
-  private Class _homeAPI;
+ at SuppressWarnings("serial")
+public class HessianServlet extends HttpServlet {
+  private Class<?> _homeAPI;
   private Object _homeImpl;
   
-  private Class _objectAPI;
+  private Class<?> _objectAPI;
   private Object _objectImpl;
   
   private HessianSkeleton _homeSkeleton;
@@ -81,8 +86,6 @@ public class HessianServlet extends GenericServlet {
 
   private SerializerFactory _serializerFactory;
 
-  private boolean _isDebug;
-
   public HessianServlet()
   {
   }
@@ -95,7 +98,7 @@ public class HessianServlet extends GenericServlet {
   /**
    * Sets the home api.
    */
-  public void setHomeAPI(Class api)
+  public void setHomeAPI(Class<?> api)
   {
     _homeAPI = api;
   }
@@ -111,7 +114,7 @@ public class HessianServlet extends GenericServlet {
   /**
    * Sets the object api.
    */
-  public void setObjectAPI(Class api)
+  public void setObjectAPI(Class<?> api)
   {
     _objectAPI = api;
   }
@@ -135,7 +138,7 @@ public class HessianServlet extends GenericServlet {
   /**
    * Sets the api-class.
    */
-  public void setAPIClass(Class api)
+  public void setAPIClass(Class<?> api)
   {
     setHomeAPI(api);
   }
@@ -143,7 +146,7 @@ public class HessianServlet extends GenericServlet {
   /**
    * Gets the api-class.
    */
-  public Class getAPIClass()
+  public Class<?> getAPIClass()
   {
     return _homeAPI;
   }
@@ -180,7 +183,6 @@ public class HessianServlet extends GenericServlet {
    */
   public void setDebug(boolean isDebug)
   {
-    _isDebug = isDebug;
   }
 
   /**
@@ -188,7 +190,7 @@ public class HessianServlet extends GenericServlet {
    */
   public void setLogName(String name)
   {
-    _log = Logger.getLogger(name);
+    // _log = Logger.getLogger(name);
   }
 
   /**
@@ -203,87 +205,90 @@ public class HessianServlet extends GenericServlet {
       if (_homeImpl != null) {
       }
       else if (getInitParameter("home-class") != null) {
-	String className = getInitParameter("home-class");
-	
-	Class homeClass = loadClass(className);
+        String className = getInitParameter("home-class");
+
+        Class<?> homeClass = loadClass(className);
+
+        _homeImpl = homeClass.newInstance();
 
-	_homeImpl = homeClass.newInstance();
-	
-	init(_homeImpl);
+        init(_homeImpl);
       }
       else if (getInitParameter("service-class") != null) {
-	String className = getInitParameter("service-class");
-	
-	Class homeClass = loadClass(className);
+        String className = getInitParameter("service-class");
 
-	_homeImpl = homeClass.newInstance();
-	
-	init(_homeImpl);
+        Class<?> homeClass = loadClass(className);
+
+        _homeImpl = homeClass.newInstance();
+
+        init(_homeImpl);
       }
       else {
-	if (getClass().equals(HessianServlet.class))
-	  throw new ServletException("server must extend HessianServlet");
+        if (getClass().equals(HessianServlet.class))
+          throw new ServletException("server must extend HessianServlet");
 
-	_homeImpl = this;
+        _homeImpl = this;
       }
 
       if (_homeAPI != null) {
       }
       else if (getInitParameter("home-api") != null) {
-	String className = getInitParameter("home-api");
-	
-	_homeAPI = loadClass(className);
+        String className = getInitParameter("home-api");
+
+        _homeAPI = loadClass(className);
       }
       else if (getInitParameter("api-class") != null) {
-	String className = getInitParameter("api-class");
+        String className = getInitParameter("api-class");
 
-	_homeAPI = loadClass(className);
+        _homeAPI = loadClass(className);
       }
       else if (_homeImpl != null) {
-	_homeAPI = findRemoteAPI(_homeImpl.getClass());
+        _homeAPI = findRemoteAPI(_homeImpl.getClass());
 
-	if (_homeAPI == null)
-	  _homeAPI = _homeImpl.getClass();
+        if (_homeAPI == null)
+          _homeAPI = _homeImpl.getClass();
+        
+        _homeAPI = _homeImpl.getClass();
       }
       
       if (_objectImpl != null) {
       }
       else if (getInitParameter("object-class") != null) {
-	String className = getInitParameter("object-class");
-	
-	Class objectClass = loadClass(className);
+        String className = getInitParameter("object-class");
+
+        Class<?> objectClass = loadClass(className);
 
-	_objectImpl = objectClass.newInstance();
+        _objectImpl = objectClass.newInstance();
 
-	init(_objectImpl);
+        init(_objectImpl);
       }
 
       if (_objectAPI != null) {
       }
       else if (getInitParameter("object-api") != null) {
-	String className = getInitParameter("object-api");
-	
-	_objectAPI = loadClass(className);
+        String className = getInitParameter("object-api");
+
+        _objectAPI = loadClass(className);
       }
       else if (_objectImpl != null)
-	_objectAPI = _objectImpl.getClass();
+        _objectAPI = _objectImpl.getClass();
 
       _homeSkeleton = new HessianSkeleton(_homeImpl, _homeAPI);
+      
       if (_objectAPI != null)
-	_homeSkeleton.setObjectClass(_objectAPI);
+        _homeSkeleton.setObjectClass(_objectAPI);
 
       if (_objectImpl != null) {
-	_objectSkeleton = new HessianSkeleton(_objectImpl, _objectAPI);
-	_objectSkeleton.setHomeClass(_homeAPI);
+        _objectSkeleton = new HessianSkeleton(_objectImpl, _objectAPI);
+        _objectSkeleton.setHomeClass(_homeAPI);
       }
       else
-	_objectSkeleton = _homeSkeleton;
+        _objectSkeleton = _homeSkeleton;
 
-      if ("true".equals(getInitParameter("debug")))
-	_isDebug = true;
+      if ("true".equals(getInitParameter("debug"))) {
+      }
 
       if ("false".equals(getInitParameter("send-collection-type")))
-	setSendCollectionType(false);
+        setSendCollectionType(false);
     } catch (ServletException e) {
       throw e;
     } catch (Exception e) {
@@ -291,8 +296,12 @@ public class HessianServlet extends GenericServlet {
     }
   }
 
-  private Class findRemoteAPI(Class implClass)
+  private Class<?> findRemoteAPI(Class<?> implClass)
   {
+    // hessian/34d0
+    return null;
+    
+    /*
     if (implClass == null || implClass.equals(GenericService.class))
       return null;
     
@@ -302,9 +311,10 @@ public class HessianServlet extends GenericServlet {
       return interfaces[0];
 
     return findRemoteAPI(implClass.getSuperclass());
+    */
   }
 
-  private Class loadClass(String className)
+  private Class<?> loadClass(String className)
     throws ClassNotFoundException
   {
     ClassLoader loader = getContextClassLoader();
@@ -342,7 +352,7 @@ public class HessianServlet extends GenericServlet {
     HttpServletResponse res = (HttpServletResponse) response;
 
     if (! req.getMethod().equals("POST")) {
-      res.setStatus(500, "Hessian Requires POST");
+      res.setStatus(500); // , "Hessian Requires POST");
       PrintWriter out = res.getWriter();
 
       res.setContentType("text/html");
@@ -356,13 +366,13 @@ public class HessianServlet extends GenericServlet {
     if (objectId == null)
       objectId = req.getParameter("ejbid");
 
-    ServiceContext.begin(req, serviceId, objectId);
+    ServiceContext.begin(req, res, serviceId, objectId);
 
     try {
       InputStream is = request.getInputStream();
       OutputStream os = response.getOutputStream();
 
-      response.setContentType("application/x-hessian");
+      response.setContentType("x-application/hessian");
 
       SerializerFactory serializerFactory = getSerializerFactory();
 
@@ -406,24 +416,24 @@ public class HessianServlet extends GenericServlet {
     public void write(char ch)
     {
       if (ch == '\n' && _sb.length() > 0) {
-	_log.fine(_sb.toString());
-	_sb.setLength(0);
+        _log.fine(_sb.toString());
+        _sb.setLength(0);
       }
       else
-	_sb.append((char) ch);
+        _sb.append((char) ch);
     }
 
     public void write(char []buffer, int offset, int length)
     {
       for (int i = 0; i < length; i++) {
-	char ch = buffer[offset + i];
-	
-	if (ch == '\n' && _sb.length() > 0) {
-	  _log.fine(_sb.toString());
-	  _sb.setLength(0);
-	}
-	else
-	  _sb.append((char) ch);
+        char ch = buffer[offset + i];
+
+        if (ch == '\n' && _sb.length() > 0) {
+          _log.fine(_sb.toString());
+          _sb.setLength(0);
+        }
+        else
+          _sb.append((char) ch);
       }
     }
 
diff --git a/com/caucho/hessian/server/HessianSkeleton.java b/com/caucho/hessian/server/HessianSkeleton.java
index 7c84a9e..133a462 100644
--- a/com/caucho/hessian/server/HessianSkeleton.java
+++ b/com/caucho/hessian/server/HessianSkeleton.java
@@ -48,20 +48,6 @@
 
 package com.caucho.hessian.server;
 
-import com.caucho.hessian.io.AbstractHessianInput;
-import com.caucho.hessian.io.AbstractHessianOutput;
-import com.caucho.hessian.io.Hessian2Input;
-import com.caucho.hessian.io.Hessian2Output;
-import com.caucho.hessian.io.HessianFactory;
-import com.caucho.hessian.io.HessianInput;
-import com.caucho.hessian.io.HessianOutput;
-import com.caucho.hessian.io.HessianDebugInputStream;
-import com.caucho.hessian.io.HessianDebugOutputStream;
-import com.caucho.hessian.io.HessianInputFactory;
-import com.caucho.hessian.io.SerializerFactory;
-import com.caucho.services.server.AbstractSkeleton;
-import com.caucho.services.server.ServiceContext;
-
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -72,6 +58,16 @@ import java.lang.reflect.Method;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import com.caucho.hessian.io.AbstractHessianInput;
+import com.caucho.hessian.io.AbstractHessianOutput;
+import com.caucho.hessian.io.HessianDebugInputStream;
+import com.caucho.hessian.io.HessianDebugOutputStream;
+import com.caucho.hessian.io.HessianFactory;
+import com.caucho.hessian.io.HessianInputFactory;
+import com.caucho.hessian.io.SerializerFactory;
+import com.caucho.services.server.AbstractSkeleton;
+import com.caucho.services.server.ServiceContext;
+
 /**
  * Proxy class for Hessian services.
  */
@@ -92,7 +88,7 @@ public class HessianSkeleton extends AbstractSkeleton {
    * @param service the underlying service object.
    * @param apiClass the API interface
    */
-  public HessianSkeleton(Object service, Class apiClass)
+  public HessianSkeleton(Object service, Class<?> apiClass)
   {
     super(apiClass);
 
@@ -111,7 +107,7 @@ public class HessianSkeleton extends AbstractSkeleton {
    * @param service the underlying service object.
    * @param apiClass the API interface
    */
-  public HessianSkeleton(Class apiClass)
+  public HessianSkeleton(Class<?> apiClass)
   {
     super(apiClass);
   }
@@ -277,7 +273,7 @@ public class HessianSkeleton extends AbstractSkeleton {
     }
     else if (method == null) {
       out.writeFault("NoSuchMethodException",
-                     "The service has no method named: " + in.getMethod(),
+                     escapeMessage("The service has no method named: " + in.getMethod()),
                      null);
       out.close();
       return;
@@ -287,7 +283,7 @@ public class HessianSkeleton extends AbstractSkeleton {
 
     if (argLength != args.length && argLength >= 0) {
       out.writeFault("NoSuchMethod",
-                     "method " + method + " argument length mismatch, received length=" + argLength,
+                     escapeMessage("method " + method + " argument length mismatch, received length=" + argLength),
                      null);
       out.close();
       return;
@@ -311,7 +307,9 @@ public class HessianSkeleton extends AbstractSkeleton {
 
       log.log(Level.FINE, this + " " + e1.toString(), e1);
 
-      out.writeFault("ServiceException", e1.getMessage(), e1);
+      out.writeFault("ServiceException", 
+                     escapeMessage(e1.getMessage()), 
+                     e1);
       out.close();
       return;
     }
@@ -324,11 +322,44 @@ public class HessianSkeleton extends AbstractSkeleton {
 
     out.close();
   }
+  
+  private String escapeMessage(String msg)
+  {
+    if (msg == null)
+      return null;
+    
+    StringBuilder sb = new StringBuilder();
+    
+    int length = msg.length();
+    for (int i = 0; i < length; i++) {
+      char ch = msg.charAt(i);
+      
+      switch (ch) {
+      case '<':
+        sb.append("<");
+        break;
+      case '>':
+        sb.append(">");
+        break;
+      case 0x0:
+        sb.append("�");
+        break;
+      case '&':
+        sb.append("&");
+        break;
+      default:
+        sb.append(ch);
+        break;
+      }
+    }
+    
+    return sb.toString();
+  }
 
   protected boolean isDebugInvoke()
   {
     return (log.isLoggable(Level.FINEST)
-	    || isDebug() && log.isLoggable(Level.FINE));
+            || isDebug() && log.isLoggable(Level.FINE));
   }
   
   /**
diff --git a/com/caucho/hessian/test/A0.java b/com/caucho/hessian/test/A0.java
deleted file mode 100644
index 5102927..0000000
--- a/com/caucho/hessian/test/A0.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * Empty object for short-encoding testing
- */
-public class A0 implements java.io.Serializable {
-  public boolean equals(Object v)
-  {
-    return v != null && getClass().equals(v.getClass());
-  }
-  
-  public String toString()
-  {
-    return getClass().getName() + "[]";
-  }
-}
diff --git a/com/caucho/hessian/test/A1.java b/com/caucho/hessian/test/A1.java
deleted file mode 100644
index 9e21420..0000000
--- a/com/caucho/hessian/test/A1.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * Empty object for short-encoding testing
- */
-public class A1 implements java.io.Serializable {
-  public boolean equals(Object v)
-  {
-    return v != null && getClass().equals(v.getClass());
-  }
-  
-  public String toString()
-  {
-    return getClass().getName() + "[]";
-  }
-}
diff --git a/com/caucho/hessian/test/A10.java b/com/caucho/hessian/test/A10.java
deleted file mode 100644
index 5e59132..0000000
--- a/com/caucho/hessian/test/A10.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * Empty object for short-encoding testing
- */
-public class A10 implements java.io.Serializable {
-  public boolean equals(Object v)
-  {
-    return v != null && getClass().equals(v.getClass());
-  }
-  
-  public String toString()
-  {
-    return getClass().getName() + "[]";
-  }
-}
diff --git a/com/caucho/hessian/test/A11.java b/com/caucho/hessian/test/A11.java
deleted file mode 100644
index 6827085..0000000
--- a/com/caucho/hessian/test/A11.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * Empty object for short-encoding testing
- */
-public class A11 implements java.io.Serializable {
-  public boolean equals(Object v)
-  {
-    return v != null && getClass().equals(v.getClass());
-  }
-  
-  public String toString()
-  {
-    return getClass().getName() + "[]";
-  }
-}
diff --git a/com/caucho/hessian/test/A12.java b/com/caucho/hessian/test/A12.java
deleted file mode 100644
index 8e78681..0000000
--- a/com/caucho/hessian/test/A12.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * Empty object for short-encoding testing
- */
-public class A12 implements java.io.Serializable {
-  public boolean equals(Object v)
-  {
-    return v != null && getClass().equals(v.getClass());
-  }
-  
-  public String toString()
-  {
-    return getClass().getName() + "[]";
-  }
-}
diff --git a/com/caucho/hessian/test/A13.java b/com/caucho/hessian/test/A13.java
deleted file mode 100644
index 1147c59..0000000
--- a/com/caucho/hessian/test/A13.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * Empty object for short-encoding testing
- */
-public class A13 implements java.io.Serializable {
-  public boolean equals(Object v)
-  {
-    return v != null && getClass().equals(v.getClass());
-  }
-  
-  public String toString()
-  {
-    return getClass().getName() + "[]";
-  }
-}
diff --git a/com/caucho/hessian/test/A14.java b/com/caucho/hessian/test/A14.java
deleted file mode 100644
index 08d9b2f..0000000
--- a/com/caucho/hessian/test/A14.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * Empty object for short-encoding testing
- */
-public class A14 implements java.io.Serializable {
-  public boolean equals(Object v)
-  {
-    return v != null && getClass().equals(v.getClass());
-  }
-  
-  public String toString()
-  {
-    return getClass().getName() + "[]";
-  }
-}
diff --git a/com/caucho/hessian/test/A15.java b/com/caucho/hessian/test/A15.java
deleted file mode 100644
index 8023c08..0000000
--- a/com/caucho/hessian/test/A15.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * Empty object for short-encoding testing
- */
-public class A15 implements java.io.Serializable {
-  public boolean equals(Object v)
-  {
-    return v != null && getClass().equals(v.getClass());
-  }
-  
-  public String toString()
-  {
-    return getClass().getName() + "[]";
-  }
-}
diff --git a/com/caucho/hessian/test/A16.java b/com/caucho/hessian/test/A16.java
deleted file mode 100644
index 3d8a061..0000000
--- a/com/caucho/hessian/test/A16.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * Empty object for short-encoding testing
- */
-public class A16 implements java.io.Serializable {
-  public boolean equals(Object v)
-  {
-    return v != null && getClass().equals(v.getClass());
-  }
-  
-  public String toString()
-  {
-    return getClass().getName() + "[]";
-  }
-}
diff --git a/com/caucho/hessian/test/A2.java b/com/caucho/hessian/test/A2.java
deleted file mode 100644
index 2d23d89..0000000
--- a/com/caucho/hessian/test/A2.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * Empty object for short-encoding testing
- */
-public class A2 implements java.io.Serializable {
-  public boolean equals(Object v)
-  {
-    return v != null && getClass().equals(v.getClass());
-  }
-  
-  public String toString()
-  {
-    return getClass().getName() + "[]";
-  }
-}
diff --git a/com/caucho/hessian/test/A3.java b/com/caucho/hessian/test/A3.java
deleted file mode 100644
index 24b70be..0000000
--- a/com/caucho/hessian/test/A3.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * Empty object for short-encoding testing
- */
-public class A3 implements java.io.Serializable {
-  public boolean equals(Object v)
-  {
-    return v != null && getClass().equals(v.getClass());
-  }
-  
-  public String toString()
-  {
-    return getClass().getName() + "[]";
-  }
-}
diff --git a/com/caucho/hessian/test/A4.java b/com/caucho/hessian/test/A4.java
deleted file mode 100644
index 219e882..0000000
--- a/com/caucho/hessian/test/A4.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * Empty object for short-encoding testing
- */
-public class A4 implements java.io.Serializable {
-  public boolean equals(Object v)
-  {
-    return v != null && getClass().equals(v.getClass());
-  }
-  
-  public String toString()
-  {
-    return getClass().getName() + "[]";
-  }
-}
diff --git a/com/caucho/hessian/test/A5.java b/com/caucho/hessian/test/A5.java
deleted file mode 100644
index 5ed13a1..0000000
--- a/com/caucho/hessian/test/A5.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * Empty object for short-encoding testing
- */
-public class A5 implements java.io.Serializable {
-  public boolean equals(Object v)
-  {
-    return v != null && getClass().equals(v.getClass());
-  }
-  
-  public String toString()
-  {
-    return getClass().getName() + "[]";
-  }
-}
diff --git a/com/caucho/hessian/test/A6.java b/com/caucho/hessian/test/A6.java
deleted file mode 100644
index 688f5e8..0000000
--- a/com/caucho/hessian/test/A6.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * Empty object for short-encoding testing
- */
-public class A6 implements java.io.Serializable {
-  public boolean equals(Object v)
-  {
-    return v != null && getClass().equals(v.getClass());
-  }
-  
-  public String toString()
-  {
-    return getClass().getName() + "[]";
-  }
-}
diff --git a/com/caucho/hessian/test/A7.java b/com/caucho/hessian/test/A7.java
deleted file mode 100644
index aee3089..0000000
--- a/com/caucho/hessian/test/A7.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * Empty object for short-encoding testing
- */
-public class A7 implements java.io.Serializable {
-  public boolean equals(Object v)
-  {
-    return v != null && getClass().equals(v.getClass());
-  }
-  
-  public String toString()
-  {
-    return getClass().getName() + "[]";
-  }
-}
diff --git a/com/caucho/hessian/test/A8.java b/com/caucho/hessian/test/A8.java
deleted file mode 100644
index 9b89834..0000000
--- a/com/caucho/hessian/test/A8.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * Empty object for short-encoding testing
- */
-public class A8 implements java.io.Serializable {
-  public boolean equals(Object v)
-  {
-    return v != null && getClass().equals(v.getClass());
-  }
-  
-  public String toString()
-  {
-    return getClass().getName() + "[]";
-  }
-}
diff --git a/com/caucho/hessian/test/A9.java b/com/caucho/hessian/test/A9.java
deleted file mode 100644
index 9d42eae..0000000
--- a/com/caucho/hessian/test/A9.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * Empty object for short-encoding testing
- */
-public class A9 implements java.io.Serializable {
-  public boolean equals(Object v)
-  {
-    return v != null && getClass().equals(v.getClass());
-  }
-  
-  public String toString()
-  {
-    return getClass().getName() + "[]";
-  }
-}
diff --git a/com/caucho/hessian/test/Test.java b/com/caucho/hessian/test/Test.java
deleted file mode 100644
index 65f867a..0000000
--- a/com/caucho/hessian/test/Test.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * The Test service is a quick sanity check service.  Developers of a
- * new Hessian implementation can use this service as an initial test.
- */
-public interface Test {
-  /**
-   * Does nothing.
-   */
-  public void nullCall();
-  
-  /**
-   * Hello, World.
-   */
-  public String hello();
-  
-  /**
-   * Subtraction
-   */
-  public int subtract(int a, int b);
-  
-  /**
-   * Echos the object to the server.
-   * <pre>
-   */
-  public Object echo(Object value);
-  
-  /**
-   * Throws an application fault.
-   */
-  public void fault()
-    throws IOException;
-}
diff --git a/com/caucho/hessian/test/TestCons.java b/com/caucho/hessian/test/TestCons.java
deleted file mode 100644
index da70727..0000000
--- a/com/caucho/hessian/test/TestCons.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-import java.util.*;
-
-/**
- * Cons-cell for testing
- */
-public class TestCons implements java.io.Serializable {
-  private Object _first;
-  private Object _rest;
-
-  public TestCons()
-  {
-  }
-
-  public TestCons(Object first)
-  {
-    _first = first;
-  }
-
-  public TestCons(Object first, Object rest)
-  {
-    _first = first;
-    _rest = rest;
-  }
-
-  public Object getFirst()
-  {
-    return _first;
-  }
-
-  public void setFirst(Object first)
-  {
-    _first = first;
-  }
-
-  public Object getRest()
-  {
-    return _rest;
-  }
-
-  public void setRest(Object rest)
-  {
-    _rest = rest;
-  }
-
-  public boolean equals(Object o)
-  {
-    return toString().equals(o.toString());
-  }
-  
-  public String toString()
-  {
-    return toString(new HashMap());
-  }
-  
-  public String toString(HashMap map)
-  {
-    Object ref = map.get(this);
-
-    if (ref != null)
-      return "#" + ref;
-
-    map.put(this, map.size());
-
-    StringBuilder sb = new StringBuilder();
-    sb.append(getClass().getSimpleName()).append("[");
-
-    if (_first instanceof TestCons)
-      sb.append(((TestCons) _first).toString(map));
-    else
-      sb.append(_first);
-
-    sb.append(",");
-
-    if (_rest instanceof TestCons)
-      sb.append(((TestCons) _rest).toString(map));
-    else
-      sb.append(_rest);
-
-    sb.append("[");
-    
-    return sb.toString();
-  }
-}
diff --git a/com/caucho/hessian/test/TestHessian2.java b/com/caucho/hessian/test/TestHessian2.java
deleted file mode 100644
index f310132..0000000
--- a/com/caucho/hessian/test/TestHessian2.java
+++ /dev/null
@@ -1,1833 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * The Test service is a quick sanity check service.  Developers of a
- * new Hessian implementation can use this service as an initial test.
- *
- * http://hessian.caucho.com/test/test2
- */
-public interface TestHessian2 {
-  /**
-   * trivial null method call
-   *
-   * <code><pre>
-   * H x02 x00
-   * C
-   *   x0a methodNull
-   *   x90
-   * </pre></code>
-   *
-   * <code><pre>
-   * R N
-   * </pre></code>
-   */
-  public void methodNull();
-
-  //
-  // result values
-  //
-
-  /**
-   * Result of null
-   *
-   * <code><pre>
-   * R N
-   * </pre></code>
-   */
-  public void replyNull();
-
-  //
-  // boolean
-  //
-
-  /**
-   * Boolean true
-   *
-   * <code><pre>
-   * T
-   * </pre></code>
-   */
-  public Object replyTrue();
-
-  /**
-   * Boolean false
-   *
-   * <code><pre>
-   * F
-   * </pre></code>
-   */
-  public Object replyFalse();
-
-  //
-  // integers
-  //
-
-  /**
-   * Result of integer 0
-   *
-   * <code><pre>
-   * R x90
-   * </pre></code>
-   */
-  public int replyInt_0();
-
-  /**
-   * Result of integer 1
-   *
-   * <code><pre>
-   * R x91
-   * </pre></code>
-   */
-  public int replyInt_1();
-
-  /**
-   * Result of integer 47
-   *
-   * <code><pre>
-   * R xbf
-   * </pre></code>
-   */
-  public int replyInt_47();
-
-  /**
-   * Result of integer -16
-   *
-   * <code><pre>
-   * R x80
-   * </pre></code>
-   */
-  public int replyInt_m16();
-
-  // two byte integers
-
-  /**
-   * Result of integer 0x30
-   *
-   * <code><pre>
-   * R xc8 x30
-   * </pre></code>
-   */
-  public int replyInt_0x30();
-
-  /**
-   * Result of integer x7ff
-   *
-   * <code><pre>
-   * R xcf xff
-   * </pre></code>
-   */
-  public int replyInt_0x7ff();
-
-  /**
-   * Result of integer -17
-   *
-   * <code><pre>
-   * R xc7 xef
-   * </pre></code>
-   */
-  public int replyInt_m17();
-
-  /**
-   * Result of integer -0x800
-   *
-   * <code><pre>
-   * R xc0 x00
-   * </pre></code>
-   */
-  public int replyInt_m0x800();
-
-  /**
-   * Result of integer 0x800
-   *
-   * <code><pre>
-   * R xd4 x08 x00
-   * </pre></code>
-   */
-  public int replyInt_0x800();
-
-  /**
-   * Result of integer 0x3ffff
-   *
-   * <code><pre>
-   * R xd7 xff xff
-   * </pre></code>
-   */
-  public int replyInt_0x3ffff();
-
-  /**
-   * Result of integer -0x801
-   *
-   * <code><pre>
-   * R xd3 xf8 x00
-   * </pre></code>
-   */
-  public int replyInt_m0x801();
-
-  /**
-   * Result of integer m0x40000
-   *
-   * <code><pre>
-   * R xd0 x00 x00
-   * </pre></code>
-   */
-  public int replyInt_m0x40000();
-
-  // 5 byte integers
-
-  /**
-   * Result of integer 0x40000
-   *
-   * <code><pre>
-   * R I x00 x04 x00 x00
-   * </pre></code>
-   */
-  public int replyInt_0x40000();
-
-  /**
-   * Result of integer 0x7fffffff
-   *
-   * <code><pre>
-   * R I x7f xff xff xff
-   * </pre></code>
-   */
-  public int replyInt_0x7fffffff();
-
-  /**
-   * Result of integer m0x40001
-   *
-   * <code><pre>
-   * R I xff xf3 xff xf
-   * </pre></code>
-   */
-  public int replyInt_m0x40001();
-
-  /**
-   * Result of integer -0x80000000
-   *
-   * <code><pre>
-   * R I x80 x00 x00 x00
-   * </pre></code>
-   */
-  public int replyInt_m0x80000000();
-
-  //
-  // longs
-  //
-
-  /**
-   * Result of long 0
-   *
-   * <code><pre>
-   * R xe0
-   * </pre></code>
-   */
-  public long replyLong_0();
-
-  /**
-   * Result of long 1
-   *
-   * <code><pre>
-   * R xe1
-   * </pre></code>
-   */
-  public long replyLong_1();
-
-  /**
-   * Result of long 15
-   *
-   * <code><pre>
-   * R xef
-   * </pre></code>
-   */
-  public long replyLong_15();
-
-  /**
-   * Result of long -8
-   *
-   * <code><pre>
-   * R xd8
-   * </pre></code>
-   */
-  public long replyLong_m8();
-
-  // two byte longs
-
-  /**
-   * Result of long 0x10
-   *
-   * <code><pre>
-   * R xf8 x10
-   * </pre></code>
-   */
-  public long replyLong_0x10();
-
-  /**
-   * Result of long x7ff
-   *
-   * <code><pre>
-   * R xff xff
-   * </pre></code>
-   */
-  public long replyLong_0x7ff();
-
-  /**
-   * Result of long -9
-   *
-   * <code><pre>
-   * R xf7 xf7
-   * </pre></code>
-   */
-  public long replyLong_m9();
-
-  /**
-   * Result of long -0x800
-   *
-   * <code><pre>
-   * R xf0 x00
-   * </pre></code>
-   */
-  public long replyLong_m0x800();
-
-  /**
-   * Result of long 0x800
-   *
-   * <code><pre>
-   * R x3c x08 x00
-   * </pre></code>
-   */
-  public long replyLong_0x800();
-
-  /**
-   * Result of long 0x3ffff
-   *
-   * <code><pre>
-   * R x3f xff xff
-   * </pre></code>
-   */
-  public long replyLong_0x3ffff();
-
-  /**
-   * Result of long -0x801
-   *
-   * <code><pre>
-   * R x3b xf7 xff
-   * </pre></code>
-   */
-  public long replyLong_m0x801();
-
-  /**
-   * Result of long m0x40000
-   *
-   * <code><pre>
-   * R x38 x00 x00
-   * </pre></code>
-   */
-  public long replyLong_m0x40000();
-
-  // 5 byte longs
-
-  /**
-   * Result of long 0x40000
-   *
-   * <code><pre>
-   * R x59 x00 x04 x00 x00
-   * </pre></code>
-   */
-  public long replyLong_0x40000();
-
-  /**
-   * Result of long 0x7fffffff
-   *
-   * <code><pre>
-   * R x59 x7f xff xff xff
-   * </pre></code>
-   */
-  public long replyLong_0x7fffffff();
-
-  /**
-   * Result of long m0x40001
-   *
-   * <code><pre>
-   * R x59 xff xf3 xff xf
-   * </pre></code>
-   */
-  public long replyLong_m0x40001();
-
-  /**
-   * Result of long -0x80000000
-   *
-   * <code><pre>
-   * R x59 x80 x00 x00 x00
-   * </pre></code>
-   */
-  public long replyLong_m0x80000000();
-
-  /**
-   * Result of long 0x80000000
-   *
-   * <code><pre>
-   * R L x00 x00 x00 x00 x80 x00 x00 x00
-   * </pre></code>
-   */
-  public long replyLong_0x80000000();
-
-  /**
-   * Result of long -0x80000001
-   *
-   * <code><pre>
-   * R L xff xff xff xff x7f xff xff xff
-   * </pre></code>
-   */
-  public long replyLong_m0x80000001();
-
-  //
-  // doubles
-  //
-
-  /**
-   * Result of double 0.0
-   *
-   * <code><pre>
-   * R x5b
-   * </pre></code>
-   */
-  public double replyDouble_0_0();
-
-  /**
-   * Result of double 1.0
-   *
-   * <code><pre>
-   * R x5c
-   * </pre></code>
-   */
-  public double replyDouble_1_0();
-
-  /**
-   * Result of double 2.0
-   *
-   * <code><pre>
-   * R x5d x02
-   * </pre></code>
-   */
-  public double replyDouble_2_0();
-
-  /**
-   * Result of double 127.0
-   *
-   * <code><pre>
-   * R x5d x7f
-   * </pre></code>
-   */
-  public double replyDouble_127_0();
-
-  /**
-   * Result of double -128.0
-   *
-   * <code><pre>
-   * R x5d x80
-   * </pre></code>
-   */
-  public double replyDouble_m128_0();
-
-  /**
-   * Result of double 128.0
-   *
-   * <code><pre>
-   * R x5e x00 x80
-   * </pre></code>
-   */
-  public double replyDouble_128_0();
-
-  /**
-   * Result of double -129.0
-   *
-   * <code><pre>
-   * R x5e xff x7f
-   * </pre></code>
-   */
-  public double replyDouble_m129_0();
-
-  /**
-   * Result of double 32767.0
-   *
-   * <code><pre>
-   * R x5e x7f xff
-   * </pre></code>
-   */
-  public double replyDouble_32767_0();
-
-  /**
-   * Result of double -32768.0
-   *
-   * <code><pre>
-   * R x5e x80 x80
-   * </pre></code>
-   */
-  public double replyDouble_m32768_0();
-
-  /**
-   * Result of double 0.001
-   *
-   * <code><pre>
-   * R x5f x00 x00 x00 x01
-   * </pre></code>
-   */
-  public double replyDouble_0_001();
-
-  /**
-   * Result of double -0.001
-   *
-   * <code><pre>
-   * R x5f xff xff xff xff
-   * </pre></code>
-   */
-  public double replyDouble_m0_001();
-
-  /**
-   * Result of double 65.536
-   *
-   * <code><pre>
-   * R x5f x00 x01 x00 x00
-   * </pre></code>
-   */
-  public double replyDouble_65_536();
-
-  /**
-   * Result of double 3.14159
-   *
-   * <code><pre>
-   * D x40 x09 x21 xf9 xf0 x1b x86 x6e
-   * </pre></code>
-   */
-  public double replyDouble_3_14159();
-
-  //
-  // date
-  //
-
-  /**
-   * date 0 (01-01-1970 00:00 GMT)
-   *
-   * <code><pre>
-   * x4a x00 x00 x00 x00
-   * </pre></code>
-   */
-  public Object replyDate_0();
-
-  /**
-   * Date by millisecond (05-08-1998 07:51:31.000 GMT)
-   *
-   * <code><pre>
-   * x4a x00 x00 x00 xd0 x4b x92 x84 xb8
-   * </pre></code>
-   */
-  public Object replyDate_1();
-
-  /**
-   * Date by minute (05-08-1998 07:51:00.000 GMT)
-   *
-   * <code><pre>
-   * x4b x00 xe3 x83 x8f
-   * </pre></code>
-   */
-  public Object replyDate_2();
-
-  //
-  // string length
-  //
-
-  /**
-   * A zero-length string
-   *
-   * <code><pre>
-   * x00
-   * </pre></code>
-   */
-  public String replyString_0();
-
-  /**
-   * A null string
-   *
-   * <code><pre>
-   * N
-   * </pre></code>
-   */
-  public String replyString_null();
-
-  /**
-   * A one-length string
-   *
-   * <code><pre>
-   * x01 a
-   * </pre></code>
-   */
-  public String replyString_1();
-
-  /**
-   * A 31-length string
-   *
-   * <code><pre>
-   * x0f 0123456789012345678901234567890
-   * </pre></code>
-   */
-  public String replyString_31();
-
-  /**
-   * A 32-length string
-   *
-   * <code><pre>
-   * x30 x02 01234567890123456789012345678901
-   * </pre></code>
-   */
-  public String replyString_32();
-
-  /**
-   * A 1023-length string
-   *
-   * <code><pre>
-   * x33 xff 000 01234567890123456789012345678901...
-   * </pre></code>
-   */
-  public String replyString_1023();
-
-  /**
-   * A 1024-length string
-   *
-   * <code><pre>
-   * S x04 x00 000 01234567890123456789012345678901...
-   * </pre></code>
-   */
-  public String replyString_1024();
-
-  /**
-   * A 65536-length string
-   *
-   * <code><pre>
-   * R x80 x00 000 ...
-   * S x04 x00 000 01234567890123456789012345678901...
-   * </pre></code>
-   */
-  public String replyString_65536();
-
-  //
-  // binary length
-  //
-
-  /**
-   * A zero-length binary
-   *
-   * <code><pre>
-   * x20
-   * </pre></code>
-   */
-  public Object replyBinary_0();
-
-  /**
-   * A null string
-   *
-   * <code><pre>
-   * N
-   * </pre></code>
-   */
-  public Object replyBinary_null();
-
-  /**
-   * A one-length string
-   *
-   * <code><pre>
-   * x01 0
-   * </pre></code>
-   */
-  public Object replyBinary_1();
-
-  /**
-   * A 15-length binary
-   *
-   * <code><pre>
-   * x2f 0123456789012345
-   * </pre></code>
-   */
-  public Object replyBinary_15();
-
-  /**
-   * A 16-length binary
-   *
-   * <code><pre>
-   * x34 x10 01234567890123456789012345678901
-   * </pre></code>
-   */
-  public Object replyBinary_16();
-
-  /**
-   * A 1023-length binary
-   *
-   * <code><pre>
-   * x37 xff 000 01234567890123456789012345678901...
-   * </pre></code>
-   */
-  public Object replyBinary_1023();
-
-  /**
-   * A 1024-length binary
-   *
-   * <code><pre>
-   * B x04 x00 000 01234567890123456789012345678901...
-   * </pre></code>
-   */
-  public Object replyBinary_1024();
-
-  /**
-   * A 65536-length binary
-   *
-   * <code><pre>
-   * A x80 x00 000 ...
-   * B x04 x00 000 01234567890123456789012345678901...
-   * </pre></code>
-   */
-  public Object replyBinary_65536();
-
-  //
-  // lists
-  //
-
-  /**
-   * Zero-length untyped list
-   *
-   * <code><pre>
-   * x78
-   * </pre></code>
-   */
-  public Object replyUntypedFixedList_0();
-
-  /**
-   * 1-length untyped list
-   *
-   * <code><pre>
-   * x79 x01 1
-   * </pre></code>
-   */
-  public Object replyUntypedFixedList_1();
-
-  /**
-   * 7-length untyped list
-   *
-   * <code><pre>
-   * x7f x01 1 x01 2 x01 3 x01 4 x01 5 x01 6 x01 7
-   * </pre></code>
-   */
-  public Object replyUntypedFixedList_7();
-
-  /**
-   * 8-length untyped list
-   *
-   * <code><pre>
-   * X x98 x01 1 x01 2 x01 3 x01 4 x01 5 x01 6 x01 7 x01 8
-   * </pre></code>
-   */
-  public Object replyUntypedFixedList_8();
-
-  /**
-   * Zero-length typed list (String array)
-   *
-   * <code><pre>
-   * x70 x07 [string
-   * </pre></code>
-   */
-  public Object replyTypedFixedList_0();
-
-  /**
-   * 1-length typed list (String array)
-   *
-   * <code><pre>
-   * x71 x07 [string x01 1
-   * </pre></code>
-   */
-  public Object replyTypedFixedList_1();
-
-  /**
-   * 7-length typed list (String array)
-   *
-   * <code><pre>
-   * x77 x07 [string x01 1 x01 2 x01 3 x01 4 x01 5 x01 6 x01 7
-   * </pre></code>
-   */
-  public Object replyTypedFixedList_7();
-
-  /**
-   * 8-length typed list (String array)
-   *
-   * <code><pre>
-   * V x07 [stringx98 x01 1 x01 2 x01 3 x01 4 x01 5 x01 6 x01 7 x01 8
-   * </pre></code>
-   */
-  public Object replyTypedFixedList_8();
-
-  //
-  // untyped maps
-  //
-
-  /**
-   * zero-length untyped map
-   *
-   * <code><pre>
-   * H Z
-   * </pre></code>
-   */
-  public Object replyUntypedMap_0();
-
-  /**
-   * untyped map with string key
-   *
-   * <code><pre>
-   * H x01 a x90 Z
-   * </pre></code>
-   */
-  public Object replyUntypedMap_1();
-
-  /**
-   * untyped map with int key
-   *
-   * <code><pre>
-   * H x90 x01 a x91 x01 b Z
-   * </pre></code>
-   */
-  public Object replyUntypedMap_2();
-
-  /**
-   * untyped map with list key
-   *
-   * <code><pre>
-   * H x71 x01 a x90 Z
-   * </pre></code>
-   */
-  public Object replyUntypedMap_3();
-
-  //
-  // typed maps
-  //
-
-  /**
-   * zero-length typed map
-   *
-   * <code><pre>
-   * M x13 java.lang.Hashtable Z
-   * </pre></code>
-   */
-  public Object replyTypedMap_0();
-
-  /**
-   * untyped map with string key
-   *
-   * <code><pre>
-   * M x13 java.lang.Hashtable x01 a x90 Z
-   * </pre></code>
-   */
-  public Object replyTypedMap_1();
-
-  /**
-   * typed map with int key
-   *
-   * <code><pre>
-   * M x13 java.lang.Hashtable x90 x01 a x91 x01 b Z
-   * </pre></code>
-   */
-  public Object replyTypedMap_2();
-
-  /**
-   * typed map with list key
-   *
-   * <code><pre>
-   * M x13 java.lang.Hashtable x71 x01 a x90 Z
-   * </pre></code>
-   */
-  public Object replyTypedMap_3();
-
-  //
-  // objects
-  //
-
-  /**
-   * Returns a single object
-   *
-   * <code><pre>
-   * C x1a com.caucho.hessian.test.A0 x90 x60
-   * </pre></code>
-   */
-  public Object replyObject_0();
-  
-  /**
-   * Returns 16 object types
-   *
-   * <code><pre>
-   * X xa0
-   *  C x1a com.caucho.hessian.test.A0 x90 x60
-   *  C x1a com.caucho.hessian.test.A1 x90 x61
-   *  C x1a com.caucho.hessian.test.A2 x90 x62
-   *  C x1a com.caucho.hessian.test.A3 x90 x63
-   *  C x1a com.caucho.hessian.test.A4 x90 x64
-   *  C x1a com.caucho.hessian.test.A5 x90 x65
-   *  C x1a com.caucho.hessian.test.A6 x90 x66
-   *  C x1a com.caucho.hessian.test.A7 x90 x67
-   *  C x1a com.caucho.hessian.test.A8 x90 x68
-   *  C x1a com.caucho.hessian.test.A9 x90 x69
-   *  C x1b com.caucho.hessian.test.A10 x90 x6a
-   *  C x1b com.caucho.hessian.test.A11 x90 x6b
-   *  C x1b com.caucho.hessian.test.A12 x90 x6c
-   *  C x1b com.caucho.hessian.test.A13 x90 x6d
-   *  C x1b com.caucho.hessian.test.A14 x90 x6e
-   *  C x1b com.caucho.hessian.test.A15 x90 x6f
-   *  C x1b com.caucho.hessian.test.A16 x90 O xa0
-   */
-  public Object replyObject_16();
-
-  /**
-   * Simple object with one field
-   *
-   * <code><pre>
-   * C x22 com.caucho.hessian.test.TestObject x91 x06 _value x60 x90
-   * </pre></code>
-   */
-  public Object replyObject_1();
-
-  /**
-   * Simple two objects with one field
-   *
-   * <code><pre>
-   * x7a
-   *   C x22 com.caucho.hessian.test.TestObject x91 x06 _value
-   *   x60 x90
-   *   x60 x91
-   * </pre></code>
-   */
-  public Object replyObject_2();
-
-  /**
-   * Simple repeated object
-   *
-   * <code><pre>
-   * x7a
-   *   C x22 com.caucho.hessian.test.TestObject x91 x06 _value
-   *   x60 x90
-   *   Q x91
-   * </pre></code>
-   */
-  public Object replyObject_2a();
-
-  /**
-   * Two object with equals
-   *
-   * <code><pre>
-   * x7a
-   *   C x22 com.caucho.hessian.test.TestObject x91 x06 _value
-   *   x60 x90
-   *   x60 x90
-   * </pre></code>
-   */
-  public Object replyObject_2b();
-
-  /**
-   * Circular object
-   *
-   * <code><pre>
-   * C x20 com.caucho.hessian.test.TestCons x91 x06 _first x05 _rest
-   *   x60 x01 a Q \x90x
-   * </pre></code>
-   */
-  public Object replyObject_3();
-
-  //
-  // arguments
-  //
-
-  /**
-   * Null
-   *
-   * <code><pre>
-   * N
-   * </pre></code>
-   */
-  public Object argNull(Object v);
-
-  //
-  // boolean
-  //
-
-  /**
-   * Boolean true
-   *
-   * <code><pre>
-   * T
-   * </pre></code>
-   */
-  public Object argTrue(Object v);
-
-  /**
-   * Boolean false
-   *
-   * <code><pre>
-   * F
-   * </pre></code>
-   */
-  public Object argFalse(Object v);
-
-  //
-  // integer
-  //
-  
-  /**
-   * Integer 0
-   *
-   * <code><pre>
-   * x90
-   * </pre></code>
-   */
-  public Object argInt_0(Object v);
-
-  /**
-   * Integer 1
-   *
-   * <code><pre>
-   * x91
-   * </pre></code>
-   */
-  public Object argInt_1(Object v);
-
-  /**
-   * integer 47
-   *
-   * <code><pre>
-   * xbf
-   * </pre></code>
-   */
-  public Object argInt_47(Object v);
-
-  /**
-   * Result of integer -16
-   *
-   * <code><pre>
-   * R x80
-   * </pre></code>
-   */
-  public Object argInt_m16(Object v);
-
-  // two byte integers
-
-  /**
-   * Integer 0x30
-   *
-   * <code><pre>
-   * xc8 x30
-   * </pre></code>
-   */
-  public Object argInt_0x30(Object v);
-
-  /**
-   * Result of integer x7ff
-   *
-   * <code><pre>
-   * xcf xff
-   * </pre></code>
-   */
-  public Object argInt_0x7ff(Object v);
-
-  /**
-   * integer -17
-   *
-   * <code><pre>
-   * xc7 xef
-   * </pre></code>
-   */
-  public Object argInt_m17(Object v);
-
-  /**
-   * Integer -0x800
-   *
-   * <code><pre>
-   * xc0 x00
-   * </pre></code>
-   */
-  public Object argInt_m0x800(Object v);
-
-  /**
-   * Integer 0x800
-   *
-   * <code><pre>
-   * xd4 x08 x00
-   * </pre></code>
-   */
-  public Object argInt_0x800(Object v);
-
-  /**
-   * Integer 0x3ffff
-   *
-   * <code><pre>
-   * xd7 xff xff
-   * </pre></code>
-   */
-  public Object argInt_0x3ffff(Object v);
-
-  /**
-   * Integer -0x801
-   *
-   * <code><pre>
-   * xd3 xf8 x00
-   * </pre></code>
-   */
-  public Object argInt_m0x801(Object v);
-
-  /**
-   * Integer m0x40000
-   *
-   * <code><pre>
-   * xd0 x00 x00
-   * </pre></code>
-   */
-  public Object argInt_m0x40000(Object v);
-
-  // 5 byte integers
-
-  /**
-   * integer 0x40000
-   *
-   * <code><pre>
-   * I x00 x04 x00 x00
-   * </pre></code>
-   */
-  public Object argInt_0x40000(Object v);
-
-  /**
-   * Integer 0x7fffffff
-   *
-   * <code><pre>
-   * I x7f xff xff xff
-   * </pre></code>
-   */
-  public Object argInt_0x7fffffff(Object v);
-
-  /**
-   * Integer m0x40001
-   *
-   * <code><pre>
-   * I xff xfb xff xff
-   * </pre></code>
-   */
-  public Object argInt_m0x40001(Object v);
-
-  /**
-   * Result of integer -0x80000000
-   *
-   * <code><pre>
-   * I x80 x00 x00 x00
-   * </pre></code>
-   */
-  public Object argInt_m0x80000000(Object v);
-
-  //
-  // longs
-  //
-
-  /**
-   * long 0
-   *
-   * <code><pre>
-   * xe0
-   * </pre></code>
-   */
-  public Object argLong_0(Object v);
-
-  /**
-   * long 1
-   *
-   * <code><pre>
-   * xe1
-   * </pre></code>
-   */
-  public Object argLong_1(Object v);
-
-  /**
-   * long 15
-   *
-   * <code><pre>
-   * xef
-   * </pre></code>
-   */
-  public Object argLong_15(Object v);
-
-  /**
-   * long -8
-   *
-   * <code><pre>
-   * xd8
-   * </pre></code>
-   */
-  public Object argLong_m8(Object v);
-
-  // two byte longs
-
-  /**
-   * long 0x10
-   *
-   * <code><pre>
-   * xf8 x10
-   * </pre></code>
-   */
-  public Object argLong_0x10(Object v);
-
-  /**
-   * long x7ff
-   *
-   * <code><pre>
-   * xff xff
-   * </pre></code>
-   */
-  public Object argLong_0x7ff(Object v);
-
-  /**
-   * long -9
-   *
-   * <code><pre>
-   * xf7 xf7
-   * </pre></code>
-   */
-  public Object argLong_m9(Object v);
-
-  /**
-   * long -0x800
-   *
-   * <code><pre>
-   * xf0 x00
-   * </pre></code>
-   */
-  public Object argLong_m0x800(Object v);
-
-  /**
-   * long 0x800
-   *
-   * <code><pre>
-   * x3c x08 x00
-   * </pre></code>
-   */
-  public Object argLong_0x800(Object v);
-
-  /**
-   * long 0x3ffff
-   *
-   * <code><pre>
-   * x3f xff xff
-   * </pre></code>
-   */
-  public Object argLong_0x3ffff(Object v);
-
-  /**
-   * long -0x801
-   *
-   * <code><pre>
-   * x3b xf7 xff
-   * </pre></code>
-   */
-  public Object argLong_m0x801(Object v);
-
-  /**
-   * long m0x40000
-   *
-   * <code><pre>
-   * x38 x00 x00
-   * </pre></code>
-   */
-  public Object argLong_m0x40000(Object v);
-
-  // 5 byte longs
-
-  /**
-   * long 0x40000
-   *
-   * <code><pre>
-   * x59 x00 x04 x00 x00
-   * </pre></code>
-   */
-  public Object argLong_0x40000(Object v);
-
-  /**
-   * long 0x7fffffff
-   *
-   * <code><pre>
-   * x59 x7f xff xff xff
-   * </pre></code>
-   */
-  public Object argLong_0x7fffffff(Object v);
-
-  /**
-   * long m0x40001
-   *
-   * <code><pre>
-   * x59 xff xfb xff xf
-   * </pre></code>
-   */
-  public Object argLong_m0x40001(Object v);
-
-  /**
-   * long -0x80000000
-   *
-   * <code><pre>
-   * x59 x80 x00 x00 x00
-   * </pre></code>
-   */
-  public Object argLong_m0x80000000(Object v);
-
-  /**
-   * Result of long 0x80000000
-   *
-   * <code><pre>
-   * L x00 x00 x00 x00 x80 x00 x00 x00
-   * </pre></code>
-   */
-  public Object argLong_0x80000000(Object v);
-
-  /**
-   * Result of long -0x80000001
-   *
-   * <code><pre>
-   * L xff xff xff xff x7f xff xff xff
-   * </pre></code>
-   */
-  public Object argLong_m0x80000001(Object v);
-
-  //
-  // doubles
-  //
-
-  /**
-   * double 0.0
-   *
-   * <code><pre>
-   * x5b
-   * </pre></code>
-   */
-  public Object argDouble_0_0(Object v);
-
-  /**
-   * double 1.0
-   *
-   * <code><pre>
-   * x5c
-   * </pre></code>
-   */
-  public Object argDouble_1_0(Object v);
-
-  /**
-   * double 2.0
-   *
-   * <code><pre>
-   * x5d x02
-   * </pre></code>
-   */
-  public Object argDouble_2_0(Object v);
-
-  /**
-   * double 127.0
-   *
-   * <code><pre>
-   * x5d x7f
-   * </pre></code>
-   */
-  public Object argDouble_127_0(Object v);
-
-  /**
-   * double -128.0
-   *
-   * <code><pre>
-   * x5d x80
-   * </pre></code>
-   */
-  public Object argDouble_m128_0(Object v);
-
-  /**
-   * double 128.0
-   *
-   * <code><pre>
-   * x5e x00 x80
-   * </pre></code>
-   */
-  public Object argDouble_128_0(Object v);
-
-  /**
-   * double -129.0
-   *
-   * <code><pre>
-   * x5e xff x7f
-   * </pre></code>
-   */
-  public Object argDouble_m129_0(Object v);
-
-  /**
-   * double 32767.0
-   *
-   * <code><pre>
-   * x5e x7f xff
-   * </pre></code>
-   */
-  public Object argDouble_32767_0(Object v);
-
-  /**
-   * Double -32768.0
-   *
-   * <code><pre>
-   * x5e x80 x80
-   * </pre></code>
-   */
-  public Object argDouble_m32768_0(Object v);
-
-  /**
-   * double 0.001
-   *
-   * <code><pre>
-   * x5f x00 x00 x00 x01
-   * </pre></code>
-   */
-  public Object argDouble_0_001(Object v);
-
-  /**
-   * double -0.001
-   *
-   * <code><pre>
-   * x5f xff xff xff xff
-   * </pre></code>
-   */
-  public Object argDouble_m0_001(Object v);
-
-  /**
-   * double 65.536
-   *
-   * <code><pre>
-   * x5f x00 x01 x00 x00
-   * </pre></code>
-   */
-  public Object argDouble_65_536(Object v);
-
-  /**
-   * Result of double 3.14159
-   *
-   * <code><pre>
-   * D x40 x09 x21 xf9 xf0 x1b x86 x6e
-   * </pre></code>
-   */
-  public Object argDouble_3_14159(Object v);
-
-  //
-  // date
-  //
-
-  /**
-   * date 0 (01-01-1970 00:00 GMT)
-   *
-   * <code><pre>
-   * x4a x00 x00 x00 x00
-   * </pre></code>
-   */
-  public Object argDate_0(Object v);
-
-  /**
-   * Date by millisecond (05-08-1998 07:51 GMT)
-   *
-   * <code><pre>
-   * x4a x00 x00 x00 xd0 x4b x92 x84 xb8
-   * </pre></code>
-   */
-  public Object argDate_1(Object v);
-
-  /**
-   * Date by minute (05-08-1998 07:51 GMT)
-   *
-   * <code><pre>
-   * x4b x00 xe3 x83 x8f
-   * </pre></code>
-   */
-  public Object argDate_2(Object v);
-
-  //
-  // string length
-  //
-
-  /**
-   * A zero-length string
-   *
-   * <code><pre>
-   * x00
-   * </pre></code>
-   */
-  public Object argString_0(Object v);
-
-  /**
-   * A one-length string
-   *
-   * <code><pre>
-   * x01 a
-   * </pre></code>
-   */
-  public Object argString_1(Object v);
-
-  /**
-   * A 31-length string
-   *
-   * <code><pre>
-   * x0f 0123456789012345678901234567890
-   * </pre></code>
-   */
-  public Object argString_31(Object v);
-
-  /**
-   * A 32-length string
-   *
-   * <code><pre>
-   * x30 x02 01234567890123456789012345678901
-   * </pre></code>
-   */
-  public Object argString_32(Object v);
-
-  /**
-   * A 1023-length string
-   *
-   * <code><pre>
-   * x33 xff 000 01234567890123456789012345678901...
-   * </pre></code>
-   */
-  public Object argString_1023(Object v);
-
-  /**
-   * A 1024-length string
-   *
-   * <code><pre>
-   * S x04 x00 000 01234567890123456789012345678901...
-   * </pre></code>
-   */
-  public Object argString_1024(Object v);
-
-  /**
-   * A 65536-length string
-   *
-   * <code><pre>
-   * R x80 x00 000 ...
-   * S x04 x00 000 01234567890123456789012345678901...
-   * </pre></code>
-   */
-  public Object argString_65536(Object v);
-
-  //
-  // binary length
-  //
-
-  /**
-   * A zero-length binary
-   *
-   * <code><pre>
-   * x20
-   * </pre></code>
-   */
-  public Object argBinary_0(Object v);
-
-  /**
-   * A one-length string
-   *
-   * <code><pre>
-   * x21 0
-   * </pre></code>
-   */
-  public Object argBinary_1(Object v);
-
-  /**
-   * A 15-length binary
-   *
-   * <code><pre>
-   * x2f 0123456789012345
-   * </pre></code>
-   */
-  public Object argBinary_15(Object v);
-
-  /**
-   * A 16-length binary
-   *
-   * <code><pre>
-   * x34 x10 01234567890123456789012345678901
-   * </pre></code>
-   */
-  public Object argBinary_16(Object v);
-
-  /**
-   * A 1023-length binary
-   *
-   * <code><pre>
-   * x37 xff 000 01234567890123456789012345678901...
-   * </pre></code>
-   */
-  public Object argBinary_1023(Object v);
-
-  /**
-   * A 1024-length binary
-   *
-   * <code><pre>
-   * B x04 x00 000 01234567890123456789012345678901...
-   * </pre></code>
-   */
-  public Object argBinary_1024(Object v);
-
-  /**
-   * A 65536-length binary
-   *
-   * <code><pre>
-   * A x80 x00 000 ...
-   * B x04 x00 000 01234567890123456789012345678901...
-   * </pre></code>
-   */
-  public Object argBinary_65536(Object v);
-
-  //
-  // lists
-  //
-
-  /**
-   * Zero-length untyped list
-   *
-   * <code><pre>
-   * x78
-   * </pre></code>
-   */
-  public Object argUntypedFixedList_0(Object v);
-
-  /**
-   * 1-length untyped list
-   *
-   * <code><pre>
-   * x79 x01 1
-   * </pre></code>
-   */
-  public Object argUntypedFixedList_1(Object v);
-
-  /**
-   * 7-length untyped list
-   *
-   * <code><pre>
-   * x7f x01 1 x01 2 x01 3 x01 4 x01 5 x01 6 x01 7
-   * </pre></code>
-   */
-  public Object argUntypedFixedList_7(Object v);
-
-  /**
-   * 8-length untyped list
-   *
-   * <code><pre>
-   * X x98 x01 1 x01 2 x01 3 x01 4 x01 5 x01 6 x01 7 x01 8
-   * </pre></code>
-   */
-  public Object argUntypedFixedList_8(Object v);
-
-  /**
-   * Zero-length typed list (String array)
-   *
-   * <code><pre>
-   * x70 x07 [string
-   * </pre></code>
-   */
-  public Object argTypedFixedList_0(Object v);
-
-  /**
-   * 1-length typed list (String array)
-   *
-   * <code><pre>
-   * x71 x07 [string x01 1
-   * </pre></code>
-   */
-  public Object argTypedFixedList_1(Object v);
-
-  /**
-   * 7-length typed list (String array)
-   *
-   * <code><pre>
-   * x77 x07 [string x01 1 x01 2 x01 3 x01 4 x01 5 x01 6 x01 7
-   * </pre></code>
-   */
-  public Object argTypedFixedList_7(Object v);
-
-  /**
-   * 8-length typed list (String array)
-   *
-   * <code><pre>
-   * V x07 [stringx98 x01 1 x01 2 x01 3 x01 4 x01 5 x01 6 x01 7 x01 8
-   * </pre></code>
-   */
-  public Object argTypedFixedList_8(Object v);
-
-  //
-  // untyped maps
-  //
-
-  /**
-   * zero-length untyped map
-   *
-   * <code><pre>
-   * H Z
-   * </pre></code>
-   */
-  public Object argUntypedMap_0(Object v);
-
-  /**
-   * untyped map with string key
-   *
-   * <code><pre>
-   * H x01 a x90 Z
-   * </pre></code>
-   */
-  public Object argUntypedMap_1(Object v);
-
-  /**
-   * untyped map with int key
-   *
-   * <code><pre>
-   * H x90 x01 a x91 x01 b Z
-   * </pre></code>
-   */
-  public Object argUntypedMap_2(Object v);
-
-  /**
-   * untyped map with list key
-   *
-   * <code><pre>
-   * H x71 x01 a x90 Z
-   * </pre></code>
-   */
-  public Object argUntypedMap_3(Object v);
-
-  //
-  // typed maps
-  //
-
-  /**
-   * zero-length typed map
-   *
-   * <code><pre>
-   * M x13 java.lang.Hashtable Z
-   * </pre></code>
-   */
-  public Object argTypedMap_0(Object v);
-
-  /**
-   * untyped map with string key
-   *
-   * <code><pre>
-   * M x13 java.lang.Hashtable x01 a x90 Z
-   * </pre></code>
-   */
-  public Object argTypedMap_1(Object v);
-
-  /**
-   * typed map with int key
-   *
-   * <code><pre>
-   * M x13 java.lang.Hashtable x90 x01 a x91 x01 b Z
-   * </pre></code>
-   */
-  public Object argTypedMap_2(Object v);
-
-  /**
-   * typed map with list key
-   *
-   * <code><pre>
-   * M x13 java.lang.Hashtable x79 x01 a x90 Z
-   * </pre></code>
-   */
-  public Object argTypedMap_3(Object v);
-
-  //
-  // objects
-  //
-
-  /**
-   * Returns a single object
-   *
-   * <code><pre>
-   * C x1a com.caucho.hessian.test.A0 x90 x60
-   * </pre></code>
-   */
-  public Object argObject_0(Object v);
-  
-  /**
-   * Returns 16 object types
-   *
-   * <code><pre>
-   * X xa0
-   *  C x1a com.caucho.hessian.test.A0 x90 x60
-   *  C x1a com.caucho.hessian.test.A1 x90 x61
-   *  C x1a com.caucho.hessian.test.A2 x90 x62
-   *  C x1a com.caucho.hessian.test.A3 x90 x63
-   *  C x1a com.caucho.hessian.test.A4 x90 x64
-   *  C x1a com.caucho.hessian.test.A5 x90 x65
-   *  C x1a com.caucho.hessian.test.A6 x90 x66
-   *  C x1a com.caucho.hessian.test.A7 x90 x67
-   *  C x1a com.caucho.hessian.test.A8 x90 x68
-   *  C x1a com.caucho.hessian.test.A9 x90 x69
-   *  C x1b com.caucho.hessian.test.A10 x90 x6a
-   *  C x1b com.caucho.hessian.test.A11 x90 x6b
-   *  C x1b com.caucho.hessian.test.A12 x90 x6c
-   *  C x1b com.caucho.hessian.test.A13 x90 x6d
-   *  C x1b com.caucho.hessian.test.A14 x90 x6e
-   *  C x1b com.caucho.hessian.test.A15 x90 x6f
-   *  C x1b com.caucho.hessian.test.A16 x90 O xa0
-   */
-  public Object argObject_16(Object v);
-
-  /**
-   * Simple object with one field
-   *
-   * <code><pre>
-   * C x30 x22 com.caucho.hessian.test.TestObject x91 x06 _value x60 x90
-   * </pre></code>
-   */
-  public Object argObject_1(Object v);
-
-  /**
-   * Simple two objects with one field
-   *
-   * <code><pre>
-   * x7a
-   *   C x30 x22 com.caucho.hessian.test.TestObject x91 x06 _value
-   *   x60 x90
-   *   x60 x91
-   * </pre></code>
-   */
-  public Object argObject_2(Object v);
-
-  /**
-   * Simple repeated object
-   *
-   * <code><pre>
-   * x7a
-   *   C x30 x22 com.caucho.hessian.test.TestObject x91 x06 _value
-   *   x60 x90
-   *   Q x91
-   * </pre></code>
-   */
-  public Object argObject_2a(Object v);
-
-  /**
-   * Two object with equals
-   *
-   * <code><pre>
-   * x7a
-   *   C x22 com.caucho.hessian.test.TestObject x91 x06 _value
-   *   x60 x90
-   *   x60 x90
-   * </pre></code>
-   */
-  public Object argObject_2b(Object v);
-
-  /**
-   * Circular object
-   *
-   * <code><pre>
-   * C x20 com.caucho.hessian.test.TestCons x91 x06 _first x05 _rest
-   *   x60 x01 a Q x90
-   * </pre></code>
-   */
-  public Object argObject_3(Object v);
-}
diff --git a/com/caucho/hessian/test/TestHessian2Servlet.java b/com/caucho/hessian/test/TestHessian2Servlet.java
deleted file mode 100644
index 791ddda..0000000
--- a/com/caucho/hessian/test/TestHessian2Servlet.java
+++ /dev/null
@@ -1,1805 +0,0 @@
-package com.caucho.hessian.test;
-
-import com.caucho.hessian.io.*;
-import com.caucho.hessian.server.HessianServlet;
-import java.io.*;
-import java.util.*;
-
-/**
- * The test service is a Hessian 2.0 protocol test for developers of
- * Hessian 2.0 clients.  For a new client the recommended order is:
- *
- * <ul>
- * <li>methodNull
- * <li>methodHello
- * </ul>
- */
-public class TestHessian2Servlet
-  extends HessianServlet
-  implements TestHessian2
-{
-  private ThreadLocal<CharArrayWriter> _threadWriter
-    = new ThreadLocal<CharArrayWriter>();
-  
-  public void methodNull()
-  {
-  }
-
-  //
-  // reply tests, testing serialization output
-  //
-
-  public void replyNull()
-  {
-  }
-
-  //
-  // boolean
-  //
-
-  public Object replyTrue()
-  {
-    return true;
-  }
-
-  public Object replyFalse()
-  {
-    return false;
-  }
-
-  //
-  // integers
-  //
-  
-  // single byte integers
-
-  public int replyInt_0()
-  {
-    return 0;
-  }
-
-  public int replyInt_1()
-  {
-    return 1;
-  }
-
-  public int replyInt_47()
-  {
-    return 47;
-  }
-
-  public int replyInt_m16()
-  {
-    return -16;
-  }
-
-  // two byte integers
-
-  public int replyInt_0x30()
-  {
-    return 0x30;
-  }
-
-  public int replyInt_0x7ff()
-  {
-    return 0x7ff;
-  }
-
-  public int replyInt_m17()
-  {
-    return -17;
-  }
-
-  public int replyInt_m0x800()
-  {
-    return -0x800;
-  }
-
-  // three byte integers
-
-  public int replyInt_0x800()
-  {
-    return 0x800;
-  }
-
-  public int replyInt_0x3ffff()
-  {
-    return 0x3ffff;
-  }
-
-  public int replyInt_m0x801()
-  {
-    return -0x801;
-  }
-  
-  public int replyInt_m0x40000()
-  {
-    return - 0x40000;
-  }
-
-  // 5 byte integers
-
-  public int replyInt_0x40000()
-  {
-    return 0x40000;
-  }
-
-  public int replyInt_0x7fffffff()
-  {
-    return 0x7fffffff;
-  }
-
-  public int replyInt_m0x40001()
-  {
-    return - 0x40001;
-  }
-
-  public int replyInt_m0x80000000()
-  {
-    return - 0x80000000;
-  }
-
-  //
-  // longs
-  //
-  
-  // single byte longs
-
-  public long replyLong_0()
-  {
-    return 0;
-  }
-
-  public long replyLong_1()
-  {
-    return 1;
-  }
-
-  public long replyLong_15()
-  {
-    return 15;
-  }
-
-  public long replyLong_m8()
-  {
-    return -8;
-  }
-
-  // two byte longs
-
-  public long replyLong_0x10()
-  {
-    return 0x10;
-  }
-
-  public long replyLong_0x7ff()
-  {
-    return 0x7ff;
-  }
-
-  public long replyLong_m9()
-  {
-    return -9;
-  }
-
-  public long replyLong_m0x800()
-  {
-    return -0x800;
-  }
-
-  // three byte longs
-
-  public long replyLong_0x800()
-  {
-    return 0x800;
-  }
-
-  public long replyLong_0x3ffff()
-  {
-    return 0x3ffff;
-  }
-
-  public long replyLong_m0x801()
-  {
-    return -0x801;
-  }
-  
-  public long replyLong_m0x40000()
-  {
-    return - 0x40000;
-  }
-
-  // 5 byte longs
-
-  public long replyLong_0x40000()
-  {
-    return 0x40000;
-  }
-
-  public long replyLong_0x7fffffff()
-  {
-    return 0x7fffffff;
-  }
-
-  public long replyLong_m0x40001()
-  {
-    return - 0x40001;
-  }
-
-  public long replyLong_m0x80000000()
-  {
-    return - 0x80000000;
-  }
-
-  public long replyLong_0x80000000()
-  {
-    return 0x80000000L;
-  }
-
-  public long replyLong_m0x80000001()
-  {
-    return - 0x80000001L;
-  }
-
-  //
-  // doubles
-  //
-
-  public double replyDouble_0_0()
-  {
-    return 0;
-  }
-
-  public double replyDouble_1_0()
-  {
-    return 1;
-  }
-
-  public double replyDouble_2_0()
-  {
-    return 2;
-  }
-  
-  public double replyDouble_127_0()
-  {
-    return 127;
-  }
-
-  public double replyDouble_m128_0()
-  {
-    return -128;
-  }
-
-  public double replyDouble_128_0()
-  {
-    return 128;
-  }
-
-  public double replyDouble_m129_0()
-  {
-    return -129;
-  }
-
-  public double replyDouble_32767_0()
-  {
-    return 32767;
-  }
-
-  public double replyDouble_m32768_0()
-  {
-    return -32768;
-  }
-
-  public double replyDouble_0_001()
-  {
-    return 0.001;
-  }
-
-  public double replyDouble_m0_001()
-  {
-    return - 0.001;
-  }
-
-  public double replyDouble_65_536()
-  {
-    return 65.536;
-  }
-
-  public double replyDouble_3_14159()
-  {
-    return 3.14159;
-  }
-
-  // date
-
-  public Object replyDate_0()
-  {
-    return new Date(0);
-  }
-
-  public Object replyDate_1()
-  {
-    long time = 894621091000L;
-
-    return new Date(time);
-  }
-
-  public Object replyDate_2()
-  {
-    long time = 894621091000L;
-
-    time -= time % 60000L;
-    
-    return new Date(time);
-  }
-
-  // strings by length
-
-  public String replyString_0()
-  {
-    return "";
-  }
-
-  public String replyString_null()
-  {
-    return null;
-  }
-
-  public String replyString_1()
-  {
-    return "0";
-  }
-
-  public String replyString_31()
-  {
-    return "0123456789012345678901234567890";
-  }
-
-  public String replyString_32()
-  {
-    return "01234567890123456789012345678901";
-  }
-  
-  public String replyString_1023()
-  {
-    StringBuilder sb = new StringBuilder();
-
-    for (int i = 0; i < 16; i++) {
-      sb.append("" + (i / 10) + (i % 10) + " 456789012345678901234567890123456789012345678901234567890123\n");
-    }
-
-    sb.setLength(1023);
-
-    return sb.toString();
-  }
-  
-  public String replyString_1024()
-  {
-    StringBuilder sb = new StringBuilder();
-
-    for (int i = 0; i < 16; i++) {
-      sb.append("" + (i / 10) + (i % 10) + " 456789012345678901234567890123456789012345678901234567890123\n");
-    }
-
-    sb.setLength(1024);
-
-    return sb.toString();
-  }
-  
-  public String replyString_65536()
-  {
-    StringBuilder sb = new StringBuilder();
-
-    for (int i = 0; i < 64 * 16; i++) {
-      sb.append("" + (i / 100) + (i / 10 % 10) + (i % 10) + " 56789012345678901234567890123456789012345678901234567890123\n");
-    }
-
-    sb.setLength(65536);
-
-    return sb.toString();
-  }
-
-  // binarys by length
-
-  public Object replyBinary_0()
-  {
-    return new byte[0];
-  }
-
-  public Object replyBinary_null()
-  {
-    return null;
-  }
-
-  public Object replyBinary_1()
-  {
-    return toBinary("0");
-  }
-
-  public Object replyBinary_15()
-  {
-    return toBinary("012345678901234");
-  }
-
-  public Object replyBinary_16()
-  {
-    return toBinary("0123456789012345");
-  }
-  
-  public Object replyBinary_1023()
-  {
-    StringBuilder sb = new StringBuilder();
-
-    for (int i = 0; i < 16; i++) {
-      sb.append("" + (i / 10) + (i % 10) + " 456789012345678901234567890123456789012345678901234567890123\n");
-    }
-
-    sb.setLength(1023);
-
-    return toBinary(sb.toString());
-  }
-  
-  public Object replyBinary_1024()
-  {
-    StringBuilder sb = new StringBuilder();
-
-    for (int i = 0; i < 16; i++) {
-      sb.append("" + (i / 10) + (i % 10) + " 456789012345678901234567890123456789012345678901234567890123\n");
-    }
-
-    sb.setLength(1024);
-
-    return toBinary(sb.toString());
-  }
-  
-  public Object replyBinary_65536()
-  {
-    StringBuilder sb = new StringBuilder();
-
-    for (int i = 0; i < 64 * 16; i++) {
-      sb.append("" + (i / 100) + (i / 10 % 10) + (i % 10) + " 56789012345678901234567890123456789012345678901234567890123\n");
-    }
-
-    sb.setLength(65536);
-
-    return toBinary(sb.toString());
-  }
-
-  private byte []toBinary(String s)
-  {
-    byte []buffer = new byte[s.length()];
-
-    for (int i = 0; i < s.length(); i++)
-      buffer[i] = (byte) s.charAt(i);
-
-    return buffer;
-  }
-
-  //
-  // lists
-  //
-
-  public Object replyUntypedFixedList_0()
-  {
-    ArrayList list = new ArrayList();
-
-    return list;
-  }
-
-  public Object replyUntypedFixedList_1()
-  {
-    ArrayList list = new ArrayList();
-
-    list.add("1");
-
-    return list;
-  }
-
-  public Object replyUntypedFixedList_7()
-  {
-    ArrayList list = new ArrayList();
-
-    list.add("1");
-    list.add("2");
-    list.add("3");
-    list.add("4");
-    list.add("5");
-    list.add("6");
-    list.add("7");
-
-    return list;
-  }
-
-  public Object replyUntypedFixedList_8()
-  {
-    ArrayList list = new ArrayList();
-
-    list.add("1");
-    list.add("2");
-    list.add("3");
-    list.add("4");
-    list.add("5");
-    list.add("6");
-    list.add("7");
-    list.add("8");
-
-    return list;
-  }
-
-  public Object replyTypedFixedList_0()
-  {
-    return new String[] {};
-  }
-
-  public Object replyTypedFixedList_1()
-  {
-    return new String[] { "1" };
-  }
-
-  public Object replyTypedFixedList_7()
-  {
-    return new String[] { "1", "2", "3", "4", "5", "6", "7" };
-  }
-
-  public Object replyTypedFixedList_8()
-  {
-    return new String[] { "1", "2", "3", "4", "5", "6", "7", "8" };
-  }
-
-  // untyped map
-
-  public Object replyUntypedMap_0()
-  {
-    return new HashMap();
-  }
-
-  public Object replyUntypedMap_1()
-  {
-    HashMap map = new HashMap();
-    map.put("a", 0);
-
-    return map;
-  }
-
-  public Object replyUntypedMap_2()
-  {
-    HashMap map = new HashMap();
-    
-    map.put(0, "a");
-    map.put(1, "b");
-
-    return map;
-  }
-
-  public Object replyUntypedMap_3()
-  {
-    HashMap map = new HashMap();
-
-    ArrayList list = new ArrayList();
-    list.add("a");
-    
-    map.put(list, 0);
-
-    return map;
-  }
-
-  // typed map
-
-  public Object replyTypedMap_0()
-  {
-    Hashtable map = new Hashtable();
-    
-    return map;
-  }
-
-  public Object replyTypedMap_1()
-  {
-    Map map = new Hashtable();
-    
-    map.put("a", 0);
-
-    return map;
-  }
-
-  public Object replyTypedMap_2()
-  {
-    Map map = new Hashtable();
-    
-    map.put(0, "a");
-    map.put(1, "b");
-
-    return map;
-  }
-
-  public Object replyTypedMap_3()
-  {
-    Map map = new Hashtable();
-
-    ArrayList list = new ArrayList();
-    list.add("a");
-    
-    map.put(list, 0);
-
-    return map;
-  }
-
-  //
-  // objects
-  //
-  
-  public Object replyObject_0()
-  {
-    return new A0();
-  }
-  
-  public Object replyObject_16()
-  {
-    ArrayList list = new ArrayList();
-    
-    list.add(new A0());
-    list.add(new A1());
-    list.add(new A2());
-    list.add(new A3());
-    list.add(new A4());
-    list.add(new A5());
-    list.add(new A6());
-    list.add(new A7());
-    list.add(new A8());
-    list.add(new A9());
-    list.add(new A10());
-    list.add(new A11());
-    list.add(new A12());
-    list.add(new A13());
-    list.add(new A14());
-    list.add(new A15());
-    list.add(new A16());
-    
-    return list;
-  }
-  
-  public Object replyObject_1()
-  {
-    return new TestObject(0);
-  }
-  
-  public Object replyObject_2()
-  {
-    ArrayList list = new ArrayList();
-
-    list.add(new TestObject(0));
-    list.add(new TestObject(1));
-    
-    return list;
-  }
-  
-  public Object replyObject_2a()
-  {
-    ArrayList list = new ArrayList();
-
-    TestObject obj = new TestObject(0);
-    
-    list.add(obj);
-    list.add(obj);
-    
-    return list;
-  }
-  
-  public Object replyObject_2b()
-  {
-    ArrayList list = new ArrayList();
-
-    list.add(new TestObject(0));
-    list.add(new TestObject(0));
-    
-    return list;
-  }
-  
-  public Object replyObject_3()
-  {
-    TestCons cons = new TestCons();
-
-    cons.setFirst("a");
-    cons.setRest(cons);
-    
-    return cons;
-  }
-
-  //
-  // arguments
-  //
-  
-  public Object argNull(Object v)
-  {
-    if (v == null)
-      return true;
-    
-    return getInputDebug();
-  }
-  
-  public Object argTrue(Object v)
-  {
-    if (Boolean.TRUE.equals(v))
-      return true;
-    
-    return getInputDebug();
-  }
-  
-  public Object argFalse(Object v)
-  {
-    if (Boolean.FALSE.equals(v))
-      return true;
-    
-    return getInputDebug();
-  }
-
-  // integers
-  
-  public Object argInt_0(Object v)
-  {
-    if (v instanceof Integer) {
-      Integer value = (Integer) v;
-
-      if (value == 0)
-	return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argInt_1(Object v)
-  {
-    if (v instanceof Integer) {
-      Integer value = (Integer) v;
-
-      if (value == 1)
-	return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argInt_47(Object v)
-  {
-    if (v instanceof Integer) {
-      Integer value = (Integer) v;
-
-      if (value == 47)
-	return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argInt_m16(Object v)
-  {
-    if (v instanceof Integer) {
-      Integer value = (Integer) v;
-
-      if (value == -16)
-	return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  // two byte integers
-
-  public Object argInt_0x30(Object v)
-  {
-    if (v instanceof Integer) {
-      Integer value = (Integer) v;
-
-      if (value == 0x30)
-	return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argInt_0x7ff(Object v)
-  {
-    if (v instanceof Integer) {
-      Integer value = (Integer) v;
-
-      if (value == 0x7ff)
-	return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argInt_m17(Object v)
-  {
-    if (v instanceof Integer) {
-      Integer value = (Integer) v;
-
-      if (value == -17)
-	return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argInt_m0x800(Object v)
-  {
-    if (v instanceof Integer) {
-      Integer value = (Integer) v;
-
-      if (value == -0x800)
-	return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argInt_0x800(Object v)
-  {
-    if (v instanceof Integer) {
-      Integer value = (Integer) v;
-
-      if (value == 0x800)
-	return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argInt_0x3ffff(Object v)
-  {
-    if (v instanceof Integer) {
-      Integer value = (Integer) v;
-
-      if (value == 0x3ffff)
-	return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argInt_m0x801(Object v)
-  {
-    if (v instanceof Integer) {
-      Integer value = (Integer) v;
-
-      if (value == -0x801)
-	return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argInt_m0x40000(Object v)
-  {
-    if (v instanceof Integer) {
-      Integer value = (Integer) v;
-
-      if (value == -0x40000)
-	return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  // 5 byte integers
-
-  public Object argInt_0x40000(Object v)
-  {
-    if (v instanceof Integer) {
-      Integer value = (Integer) v;
-
-      if (value == 0x40000)
-	return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argInt_0x7fffffff(Object v)
-  {
-    if (v instanceof Integer) {
-      Integer value = (Integer) v;
-
-      if (value == 0x7fffffff)
-	return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argInt_m0x40001(Object v)
-  {
-    if (v instanceof Integer) {
-      Integer value = (Integer) v;
-
-      if (value == -0x40001)
-	return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argInt_m0x80000000(Object v)
-  {
-    if (v instanceof Integer) {
-      Integer value = (Integer) v;
-
-      if (value == -0x80000000)
-	return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  //
-  // longs
-  //
-
-  public Object argLong_0(Object v)
-  {
-    if (v.equals(replyLong_0()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  public Object argLong_1(Object v)
-  {
-    if (v.equals(replyLong_1()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  public Object argLong_15(Object v)
-  {
-    if (v.equals(replyLong_15()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  public Object argLong_m8(Object v)
-  {
-    if (v.equals(replyLong_m8()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  // two byte longs
-
-  public Object argLong_0x10(Object v)
-  {
-    if (v.equals(replyLong_0x10()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  public Object argLong_0x7ff(Object v)
-  {
-    if (v.equals(replyLong_0x7ff()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  public Object argLong_m9(Object v)
-  {
-    if (v.equals(replyLong_m9()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  public Object argLong_m0x800(Object v)
-  {
-    if (v.equals(replyLong_m0x800()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  public Object argLong_0x800(Object v)
-  {
-    if (v.equals(replyLong_0x800()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  public Object argLong_0x3ffff(Object v)
-  {
-    if (v.equals(replyLong_0x3ffff()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  public Object argLong_m0x801(Object v)
-  {
-    if (v.equals(replyLong_m0x801()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  public Object argLong_m0x40000(Object v)
-  {
-    if (v.equals(replyLong_m0x40000()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  // 5 byte longs
-
-  public Object argLong_0x40000(Object v)
-  {
-    if (v.equals(replyLong_0x40000()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  public Object argLong_0x7fffffff(Object v)
-  {
-    if (v.equals(replyLong_0x7fffffff()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  public Object argLong_m0x40001(Object v)
-  {
-    if (v.equals(replyLong_m0x40001()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  public Object argLong_m0x80000000(Object v)
-  {
-    if (v.equals(replyLong_m0x80000000()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  public Object argLong_0x80000000(Object v)
-  {
-    if (v.equals(replyLong_0x80000000()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  public Object argLong_m0x80000001(Object v)
-  {
-    if (v.equals(replyLong_m0x80000001()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  //
-  // doubles
-  //
-
-  /**
-   * double 0.0
-   *
-   * <code><pre>
-   * x5b
-   * </pre></code>
-   */
-  public Object argDouble_0_0(Object v)
-  {
-    if (v.equals(replyDouble_0_0()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  /**
-   * double 1.0
-   *
-   * <code><pre>
-   * x5c
-   * </pre></code>
-   */
-  public Object argDouble_1_0(Object v)
-  {
-    if (v.equals(replyDouble_1_0()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  /**
-   * double 2.0
-   *
-   * <code><pre>
-   * x5d x02
-   * </pre></code>
-   */
-  public Object argDouble_2_0(Object v)
-  {
-    if (v.equals(replyDouble_2_0()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  /**
-   * double 127.0
-   *
-   * <code><pre>
-   * x5d x7f
-   * </pre></code>
-   */
-  public Object argDouble_127_0(Object v)
-  {
-    if (v.equals(replyDouble_127_0()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  /**
-   * double -128.0
-   *
-   * <code><pre>
-   * x5d x80
-   * </pre></code>
-   */
-  public Object argDouble_m128_0(Object v)
-  {
-    if (v.equals(replyDouble_m128_0()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  /**
-   * double 128.0
-   *
-   * <code><pre>
-   * x5e x00 x80
-   * </pre></code>
-   */
-  public Object argDouble_128_0(Object v)
-  {
-    if (v.equals(replyDouble_128_0()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  /**
-   * double -129.0
-   *
-   * <code><pre>
-   * x5e xff x7f
-   * </pre></code>
-   */
-  public Object argDouble_m129_0(Object v)
-  {
-    if (v.equals(replyDouble_m129_0()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  /**
-   * double 32767.0
-   *
-   * <code><pre>
-   * x5e x7f xff
-   * </pre></code>
-   */
-  public Object argDouble_32767_0(Object v)
-  {
-    if (v.equals(replyDouble_32767_0()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  /**
-   * Double -32768.0
-   *
-   * <code><pre>
-   * x5e x80 x80
-   * </pre></code>
-   */
-  public Object argDouble_m32768_0(Object v)
-  {
-    if (v.equals(replyDouble_m32768_0()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  /**
-   * double 0.001
-   *
-   * <code><pre>
-   * x5f x00 x00 x00 x01
-   * </pre></code>
-   */
-  public Object argDouble_0_001(Object v)
-  {
-    if (v.equals(replyDouble_0_001()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  /**
-   * double -0.001
-   *
-   * <code><pre>
-   * x5f xff xff xff xff
-   * </pre></code>
-   */
-  public Object argDouble_m0_001(Object v)
-  {
-    if (v.equals(replyDouble_m0_001()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  /**
-   * double 65.536
-   *
-   * <code><pre>
-   * x5f x00 x01 x00 x00
-   * </pre></code>
-   */
-  public Object argDouble_65_536(Object v)
-  {
-    if (v.equals(replyDouble_65_536()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  /**
-   * Result of double 3.14159
-   *
-   * <code><pre>
-   * D x00 x01 x00 x00 x00 x00 x00 x00
-   * </pre></code>
-   */
-  public Object argDouble_3_14159(Object v)
-  {
-    if (v.equals(replyDouble_3_14159()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  //
-  // date
-  //
-
-  public Object argDate_0(Object v)
-  {
-    if (v.equals(replyDate_0()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  public Object argDate_1(Object v)
-  {
-    if (v.equals(replyDate_1()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  public Object argDate_2(Object v)
-  {
-    if (v.equals(replyDate_2()))
-      return true;
-
-    return getInputDebug();
-  }
-
-  //
-  // string length
-  //
-
-  public Object argString_0(Object v)
-  {
-    String expect = "";
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argString_1(Object v)
-  {
-    String expect = "0";
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argString_31(Object v)
-  {
-    String expect = "0123456789012345678901234567890";
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argString_32(Object v)
-  {
-    String expect = "01234567890123456789012345678901";
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argString_1023(Object v)
-  {
-    String expect = replyString_1023();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-    
-  public Object argString_1024(Object v)
-  {
-    String expect = replyString_1024();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-    
-  public Object argString_65536(Object v)
-  {
-    String expect = replyString_65536();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  //
-  // binary length
-  //
-
-  public Object argBinary_0(Object v)
-  {
-    byte []expect = (byte []) replyBinary_0();
-    
-    if (equals(expect, v))
-      return true;
-    
-    return getInputDebug();
-  }
-
-  public Object argBinary_1(Object v)
-  {
-    byte []expect = (byte []) replyBinary_1();
-    
-    if (equals(expect, v))
-      return true;
-    
-    return getInputDebug();
-  }
-
-  public Object argBinary_15(Object v)
-  {
-    byte []expect = (byte []) replyBinary_15();
-    
-    if (equals(expect, v))
-      return true;
-    
-    return getInputDebug();
-  }
-
-  public Object argBinary_16(Object v)
-  {
-    byte []expect = (byte []) replyBinary_16();
-    
-    if (equals(expect, v))
-      return true;
-    
-    return getInputDebug();
-  }
-
-  public Object argBinary_1023(Object v)
-  {
-    byte []expect = (byte []) replyBinary_1023();
-    
-    if (equals(expect, v))
-      return true;
-    
-    return getInputDebug();
-  }
-
-  public Object argBinary_1024(Object v)
-  {
-    byte []expect = (byte []) replyBinary_1024();
-    
-    if (equals(expect, v))
-      return true;
-    
-    return getInputDebug();
-  }
-
-  public Object argBinary_65536(Object v)
-  {
-    byte []expect = (byte []) replyBinary_65536();
-    
-    if (equals(expect, v))
-      return true;
-    
-    return getInputDebug();
-  }
-
-  //
-  // lists
-  //
-
-  public Object argUntypedFixedList_0(Object v)
-  {
-    Object expect = replyUntypedFixedList_0();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argUntypedFixedList_1(Object v)
-  {
-    Object expect = replyUntypedFixedList_1();
-
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argUntypedFixedList_7(Object v)
-  {
-    Object expect = replyUntypedFixedList_7();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argUntypedFixedList_8(Object v)
-  {
-    Object expect = replyUntypedFixedList_8();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argTypedFixedList_0(Object v)
-  {
-    String []expect = (String []) replyTypedFixedList_0();
-    
-    if (v instanceof String[] && equals(expect, (String []) v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argTypedFixedList_1(Object v)
-  {
-    String []expect = (String []) replyTypedFixedList_1();
-    
-    if (v instanceof String[] && equals(expect, (String []) v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argTypedFixedList_7(Object v)
-  {
-    String []expect = (String []) replyTypedFixedList_7();
-    
-    if (v instanceof String[] && equals(expect, (String []) v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argTypedFixedList_8(Object v)
-  {
-    String []expect = (String []) replyTypedFixedList_8();
-    
-    if (v instanceof String[] && equals(expect, (String []) v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  //
-  // untyped maps
-  //
-
-  public Object argUntypedMap_0(Object v)
-  {
-    Object expect = replyUntypedMap_0();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argUntypedMap_1(Object v)
-  {
-    Object expect = replyUntypedMap_1();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argUntypedMap_2(Object v)
-  {
-    Object expect = replyUntypedMap_2();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argUntypedMap_3(Object v)
-  {
-    Object expect = replyUntypedMap_3();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  //
-  // typed maps
-  //
-
-  public Object argTypedMap_0(Object v)
-  {
-    Object expect = replyTypedMap_0();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argTypedMap_1(Object v)
-  {
-    Object expect = replyTypedMap_1();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argTypedMap_2(Object v)
-  {
-    Object expect = replyTypedMap_2();
-
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argTypedMap_3(Object v)
-  {
-    Object expect = replyTypedMap_3();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  //
-  // objects
-  //
-
-  public Object argObject_0(Object v)
-  {
-    Object expect = replyObject_0();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-  
-  public Object argObject_16(Object v)
-  {
-    Object expect = replyObject_16();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argObject_1(Object v)
-  {
-    Object expect = replyObject_1();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argObject_2(Object v)
-  {
-    Object expect = replyObject_2();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argObject_2a(Object v)
-  {
-    Object expect = replyObject_2a();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argObject_2b(Object v)
-  {
-    Object expect = replyObject_2b();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  public Object argObject_3(Object v)
-  {
-    Object expect = replyObject_3();
-    
-    if (expect.equals(v)) {
-      return true;
-    }
-    
-    return getInputDebug();
-  }
-
-  private boolean equals(String []a, String []b)
-  {
-    if (a == null || b == null)
-      return false;
-
-    if (a.length != b.length)
-      return false;
-
-    for (int i = 0; i < a.length; i++) {
-      if (! a[i].equals(b[i]))
-	return false;
-    }
-
-    return true;
-  }
-
-  private boolean equals(byte []a, Object obj)
-  {
-    if (! (obj instanceof byte[]))
-      return false;
-
-    byte []b = (byte []) obj;
-    
-    if (a == null || b == null)
-      return false;
-
-    if (a.length != b.length)
-      return false;
-
-    for (int i = 0; i < a.length; i++) {
-      if (a[i] != b[i]) {
-	return false;
-      }
-    }
-
-    return true;
-  }
-
-  protected String getInputDebug()
-  {
-    CharArrayWriter writer = _threadWriter.get();
-    if (writer != null)
-      return writer.toString();
-    else
-      return null;
-  }
-
-  /**
-   * Invoke the object with the request from the input stream.
-   *
-   * @param in the Hessian input stream
-   * @param out the Hessian output stream
-   */
-  @Override
-  public void invoke(InputStream is, OutputStream os, String objectId,
-                     SerializerFactory serializerFactory)
-    throws Exception
-  {
-    CharArrayWriter writer = new CharArrayWriter();
-
-    _threadWriter.set(writer);
-
-    PrintWriter dbg = new PrintWriter(writer);
-
-    HessianDebugInputStream debug = new HessianDebugInputStream(is, dbg);
-    debug.startTop2();
-    
-    super.invoke(debug, os, objectId, serializerFactory);
-  }
-}
diff --git a/com/caucho/hessian/test/TestHessianServlet.java b/com/caucho/hessian/test/TestHessianServlet.java
deleted file mode 100644
index 91e36b7..0000000
--- a/com/caucho/hessian/test/TestHessianServlet.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.caucho.hessian.test;
-
-import com.caucho.hessian.io.*;
-import com.caucho.hessian.server.HessianServlet;
-import java.io.*;
-import java.util.*;
-
-/**
- * The test service is a Hessian 2.0 protocol test for developers of
- * Hessian 2.0 clients.  For a new client the recommended order is:
- *
- * <ul>
- * <li>methodNull
- * <li>methodHello
- * </ul>
- */
-public class TestHessianServlet
-  extends HessianServlet
-  implements Test
-{
-  private ThreadLocal<CharArrayWriter> _threadWriter
-    = new ThreadLocal<CharArrayWriter>();
-  
-  /**
-   * Does nothing.
-   */
-  public void nullCall()
-  {
-  }
-  
-  /**
-   * Hello, World.
-   */
-  public String hello()
-  {
-    return "Hello, World";
-  }
-  
-  /**
-   * Subtraction
-   */
-  public int subtract(int a, int b)
-  {
-    return a - b;
-  }
-  
-  /**
-   * Echos the object to the server.
-   * <pre>
-   */
-  public Object echo(Object value)
-  {
-    return value;
-  }
-  
-  /**
-   * Throws an application fault.
-   */
-  public void fault()
-    throws IOException
-  {
-    throw new NullPointerException("sample exception");
-  }
-}
diff --git a/com/caucho/hessian/test/TestObject.java b/com/caucho/hessian/test/TestObject.java
deleted file mode 100644
index 07f624e..0000000
--- a/com/caucho/hessian/test/TestObject.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.caucho.hessian.test;
-
-import java.io.IOException;
-
-/**
- * Empty object for short-encoding testing
- */
-public class TestObject implements java.io.Serializable {
-  private Object _value;
-
-  public TestObject()
-  {
-  }
-
-  public TestObject(Object value)
-  {
-    _value = value;
-  }
-
-  public Object getValue()
-  {
-    return _value;
-  }
-
-  public int hashCode()
-  {
-    if (_value != null)
-      return _value.hashCode();
-    else
-      return 0;
-  }
-
-  public boolean equals(Object o)
-  {
-    if (! (o instanceof TestObject))
-      return false;
-
-    TestObject obj = (TestObject) o;
-
-    if (_value != null)
-      return _value.equals(obj._value);
-    else
-      return _value == obj._value;
-  }
-  
-  public String toString()
-  {
-    return getClass().getName() + "[" + _value + "]";
-  }
-}
diff --git a/com/caucho/hessian/util/HessianFreeList.java b/com/caucho/hessian/util/HessianFreeList.java
index d0eaa90..1d40628 100644
--- a/com/caucho/hessian/util/HessianFreeList.java
+++ b/com/caucho/hessian/util/HessianFreeList.java
@@ -137,7 +137,7 @@ public final class HessianFreeList<T> {
 
     for (int i = top - 1; i >= 0; i--) {
       if (_freeStack.get(i) == obj)
-	return true;
+        return true;
     }
 
     return false;
diff --git a/com/caucho/hessian/util/IdentityIntMap.java b/com/caucho/hessian/util/IdentityIntMap.java
index 42f4273..c14b5d5 100644
--- a/com/caucho/hessian/util/IdentityIntMap.java
+++ b/com/caucho/hessian/util/IdentityIntMap.java
@@ -132,7 +132,7 @@ public class IdentityIntMap {
   public final int put(Object key, int value, boolean isReplace)
   {
     int prime = _prime;
-    int hash = System.identityHashCode(key) % prime;
+    int hash = Math.abs(System.identityHashCode(key) % prime);
     // int hash = key.hashCode() % prime;
 
     Object []keys = _keys;
@@ -174,7 +174,7 @@ public class IdentityIntMap {
    */
   public final void remove(Object key)
   {
-    if (put(key, -1, true) != -1) {
+    if (put(key, NULL, true) != NULL) {
       _size--;
     }
   }
@@ -195,9 +195,10 @@ public class IdentityIntMap {
 
     for (int i = keys.length - 1; i >= 0; i--) {
       Object key = keys[i];
+      int value = values[i];
 
-      if (key != null) {
-        put(key, values[i], true);
+      if (key != null && value != NULL) {
+        put(key, value, true);
       }
     }
   }
diff --git a/com/caucho/services/server/AbstractSkeleton.java b/com/caucho/services/server/AbstractSkeleton.java
index 47dc67e..ab8d6d5 100644
--- a/com/caucho/services/server/AbstractSkeleton.java
+++ b/com/caucho/services/server/AbstractSkeleton.java
@@ -177,31 +177,31 @@ abstract public class AbstractSkeleton {
     if (name.equals("boolean") || name.equals("java.lang.Boolean"))
       return "boolean";
     else if (name.equals("int") || name.equals("java.lang.Integer")
-	     || name.equals("short") || name.equals("java.lang.Short")
-	     || name.equals("byte") || name.equals("java.lang.Byte"))
+             || name.equals("short") || name.equals("java.lang.Short")
+             || name.equals("byte") || name.equals("java.lang.Byte"))
       return "int";
     else if (name.equals("long") || name.equals("java.lang.Long"))
       return "long";
     else if (name.equals("float") || name.equals("java.lang.Float")
-	     || name.equals("double") || name.equals("java.lang.Double"))
+             || name.equals("double") || name.equals("java.lang.Double"))
       return "double";
     else if (name.equals("java.lang.String")
-	     || name.equals("com.caucho.util.CharBuffer")
-	     || name.equals("char") || name.equals("java.lang.Character")
-	     || name.equals("java.io.Reader"))
+             || name.equals("com.caucho.util.CharBuffer")
+             || name.equals("char") || name.equals("java.lang.Character")
+             || name.equals("java.io.Reader"))
       return "string";
     else if (name.equals("java.util.Date")
-	     || name.equals("com.caucho.util.QDate"))
+             || name.equals("com.caucho.util.QDate"))
       return "date";
     else if (InputStream.class.isAssignableFrom(cl)
-	     || name.equals("[B"))
+             || name.equals("[B"))
       return "binary";
     else if (cl.isArray()) {
       return "[" + mangleClass(cl.getComponentType(), isFull);
     }
     else if (name.equals("org.w3c.dom.Node")
-	     || name.equals("org.w3c.dom.Element")
-	     || name.equals("org.w3c.dom.Document"))
+             || name.equals("org.w3c.dom.Element")
+             || name.equals("org.w3c.dom.Document"))
       return "xml";
     else if (isFull)
       return name;
diff --git a/com/caucho/services/server/ServiceContext.java b/com/caucho/services/server/ServiceContext.java
index 6bc2bbc..13bf42a 100644
--- a/com/caucho/services/server/ServiceContext.java
+++ b/com/caucho/services/server/ServiceContext.java
@@ -50,15 +50,19 @@ package com.caucho.services.server;
 
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
 import java.util.HashMap;
 
 /**
  * Context for a service, to handle request-specific information.
  */
 public class ServiceContext {
-  private static final ThreadLocal _localContext = new ThreadLocal();
+  private static final ThreadLocal<ServiceContext> _localContext
+    = new ThreadLocal<ServiceContext>();
 
   private ServletRequest _request;
+  private ServletResponse _response;
   private String _serviceName;
   private String _objectId;
   private int _count;
@@ -76,8 +80,9 @@ public class ServiceContext {
    * @param objectId the object identifier
    */
   public static void begin(ServletRequest request,
-			   String serviceName,
-			   String objectId)
+                           ServletResponse response,
+                           String serviceName,
+                           String objectId)
     throws ServletException
   {
     ServiceContext context = (ServiceContext) _localContext.get();
@@ -88,6 +93,7 @@ public class ServiceContext {
     }
 
     context._request = request;
+    context._response = response;
     context._serviceName = serviceName;
     context._objectId = objectId;
     context._count++;
@@ -144,6 +150,19 @@ public class ServiceContext {
   }
 
   /**
+   * Returns the service request.
+   */
+  public static ServletResponse getContextResponse()
+  {
+    ServiceContext context = (ServiceContext) _localContext.get();
+
+    if (context != null)
+      return context._response;
+    else
+      return null;
+  }
+
+  /**
    * Returns the service id, corresponding to the pathInfo of the URL.
    */
   public static String getContextServiceName()
@@ -178,8 +197,11 @@ public class ServiceContext {
 
     if (context != null && --context._count == 0) {
       context._request = null;
+      context._response = null;
 
       context._headers.clear();
+      
+      _localContext.set(null);
     }
   }
 
diff --git a/debian/changelog b/debian/changelog
index fc3cd89..ded0c1c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,17 @@
+hessian (4.0.35-1) experimental; urgency=low
+
+  * Team upload.
+  * New upstream release
+  * Removed the test classes from the generated jar
+  * debian/watch: Updated to find the latest versions of Hessian
+  * debian/control: Updated the dependency on the Servlet API (2.5 -> 3.0)
+  * debian/control: Bumped Standards-Version to 3.9.4 (no changes)
+  * debian/copyright: Updated to comply with the Machine-readable format 1.0
+  * debian/copyright: Replaced the generic Apache License 1.1 with the variant
+    actually used upstream
+
+ -- Emmanuel Bourg <ebourg at apache.org>  Sun, 14 Apr 2013 01:32:01 +0200
+
 hessian (4.0.6-1) unstable; urgency=low
 
   * Initial release. (Closes: #581769).
diff --git a/debian/control b/debian/control
index f3ad6ad..1934c3f 100644
--- a/debian/control
+++ b/debian/control
@@ -1,18 +1,18 @@
 Source: hessian
 Maintainer: Debian Java Maintainers <pkg-java-maintainers at lists.alioth.debian.org>
-Uploaders: Miguel Landaeta <miguel at miguel.cc>
+Uploaders: Miguel Landaeta <miguel at miguel.cc>, Emmanuel Bourg <ebourg at apache.org>
 Section: java
 Priority: optional
 Build-Depends: debhelper (>= 7.0.50), default-jdk, javahelper,
- libservlet2.5-java
-Standards-Version: 3.8.4
+ libservlet3.0-java
+Standards-Version: 3.9.4
 Homepage: http://hessian.caucho.com/
 Vcs-Git: git://git.debian.org/git/pkg-java/hessian.git
 Vcs-Browser: http://git.debian.org/?p=pkg-java/hessian.git
 
 Package: libhessian-java
 Architecture: all
-Depends: libservlet2.5-java, ${misc:Depends}
+Depends: libservlet3.0-java, ${misc:Depends}
 Suggests: libhessian-java-doc (= ${binary:Version})
 Description: Java implementation of a binary protocol for web services
  Hessian provides compact binary and XML protocols for applications
diff --git a/debian/copyright b/debian/copyright
index 0bd8c45..4e7957e 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -1,63 +1,53 @@
-The sources were downloaded from http://caucho.com/download/hessian-4.0.6-src.jar.
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: Hessian
+Upstream-Contact: Scott Ferguson <ferg at caucho.com>
+Source: http://hessian.caucho.com/
 
 Files: *
 Copyright: © 2001-2010 Caucho Technology, Inc.
 License: Apache-1.1
  The Apache Software License, Version 1.1
-
- Copyright (c) 2000 The Apache Software Foundation.  All rights
- reserved.
-
+ .
  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions
  are met:
-
+ .
  1. Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.
-
+ .
  2. Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
     distribution.
-
- 3. The end-user documentation included with the redistribution,
-    if any, must include the following acknowledgment:
+ .
+ 3. The end-user documentation included with the redistribution, if
+    any, must include the following acknowlegement:
        "This product includes software developed by the
-        Apache Software Foundation (http://www.apache.org/)."
-    Alternately, this acknowledgment may appear in the software itself,
-    if and wherever such third-party acknowledgments normally appear.
-
- 4. The names "Apache" and "Apache Software Foundation" must
-    not be used to endorse or promote products derived from this
-    software without prior written permission. For written
-    permission, please contact apache at apache.org.
-
- 5. Products derived from this software may not be called "Apache",
-    nor may "Apache" appear in their name, without prior written
-    permission of the Apache Software Foundation.
-
+        Caucho Technology (http://www.caucho.com/)."
+    Alternately, this acknowlegement may appear in the software itself,
+    if and wherever such third-party acknowlegements normally appear.
+ .
+ 4. The names "Hessian", "Resin", and "Caucho" must not be used to
+    endorse or promote products derived from this software without prior
+    written permission. For written permission, please contact
+    info at caucho.com.
+ .
+ 5. Products derived from this software may not be called "Resin"
+    nor may "Resin" appear in their names without prior written
+    permission of Caucho Technology.
+ .
  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- SUCH DAMAGE.
- ====================================================================
-
- This software consists of voluntary contributions made by many
- individuals on behalf of the Apache Software Foundation.  For more
- information on the Apache Software Foundation, please see
- <http://www.apache.org/>.
+ DISCLAIMED.  IN NO EVENT SHALL CAUCHO TECHNOLOGY OR ITS CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
- Portions of this software are based upon public domain software
- originally written at the National Center for Supercomputing Applications,
- University of Illinois, Urbana-Champaign.
 
 Files: debian/*
 Copyright: © 2010 Miguel Landaeta <miguel at miguel.cc>
diff --git a/debian/orig-tar.sh b/debian/orig-tar.sh
index a47bf33..9e4bd8c 100755
--- a/debian/orig-tar.sh
+++ b/debian/orig-tar.sh
@@ -7,12 +7,12 @@ echo "version $2"
 package=`dpkg-parsechangelog | sed -n 's/^Source: //p'`
 version=$2
 tarball=$3
-TAR=${package}_${version}.orig.tar.gz
+TAR=../${package}_${version}.orig.tar.gz
 DIR=${package}-${version}.orig
 
 unzip $tarball -d $DIR
 
 GZIP=--best tar --numeric --group 0 --owner 0 -c -v -z -f $TAR \
-    --exclude 'META-INF' $DIR
+    --exclude 'META-INF' --exclude **/test/** --exclude **/test  $DIR
 
 rm -rf $tarball $DIR
diff --git a/debian/rules b/debian/rules
index f1eb67b..a751a1f 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,7 +1,7 @@
 #!/usr/bin/make -f
 
 export JAVA_HOME=/usr/lib/jvm/default-java
-export CLASSPATH=/usr/share/java/servlet-api-2.5.jar
+export CLASSPATH=/usr/share/java/servlet-api-3.0.jar
 
 %:
 	dh --with javahelper $@
diff --git a/debian/watch b/debian/watch
index 14414cb..907ee63 100644
--- a/debian/watch
+++ b/debian/watch
@@ -1,3 +1,3 @@
 version=3
-http://hessian.caucho.com/ \
-http://caucho.com/download/hessian-(.*)-src.jar debian debian/orig-tar.sh
+opts=downloadurlmangle=s/resin/hessian/;s/\.zip/-src\.jar/ \
+    http://www.caucho.com/download/resin-([\d\.]+).zip debian debian/orig-tar.sh

-- 
Hessian: simple binary protocol for connecting web services



More information about the pkg-java-commits mailing list