MYFACES-3477 refactored and applied some optimizations to non-state-saving related parts of MyFaces
diff --git a/impl/src/main/java/org/apache/myfaces/application/viewstate/StateUtils.java b/impl/src/main/java/org/apache/myfaces/application/viewstate/StateUtils.java
index 2703664..cd9d3ef 100644
--- a/impl/src/main/java/org/apache/myfaces/application/viewstate/StateUtils.java
+++ b/impl/src/main/java/org/apache/myfaces/application/viewstate/StateUtils.java
@@ -267,23 +267,22 @@
     
     public static final byte[] getAsByteArray(Object object, ExternalContext ctx)
     {
-        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-        
         // get the Factory that was instantiated @ startup
         SerialFactory serialFactory = (SerialFactory) ctx.getApplicationMap().get(SERIAL_FACTORY);
-        
         Assert.notNull(serialFactory, "serialFactory");
         
         try
         {
-            ObjectOutputStream writer = serialFactory.getObjectOutputStream(outputStream);
-            writer.writeObject(object);
-            byte[] bytes = outputStream.toByteArray();
-            writer.close();
-            outputStream.close();
-            writer = null;
-            outputStream = null;
-            return bytes;
+            try (ByteArrayOutputStream baos = new ByteArrayOutputStream())
+            {
+                try (ObjectOutputStream oos = serialFactory.getObjectOutputStream(baos))
+                {
+                    oos.writeObject(object);
+                    oos.flush();
+
+                    return baos.toByteArray();
+                }
+            }
         }
         catch (IOException e)
         {
@@ -342,18 +341,20 @@
 
     public static final byte[] compress(byte[] bytes)
     {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        
         try
         {
-            GZIPOutputStream gzip = new GZIPOutputStream(baos);
-            gzip.write(bytes, 0, bytes.length);
-            gzip.finish();
-            byte[] fewerBytes = baos.toByteArray();
-            gzip.close();
-            baos.close();
-            gzip = null;
-            baos = null;
-            return fewerBytes;
+            try (ByteArrayOutputStream baos = new ByteArrayOutputStream())
+            {
+                try (GZIPOutputStream gzip = new GZIPOutputStream(baos))
+                {
+                    gzip.write(bytes, 0, bytes.length);
+                    gzip.finish();
+                    gzip.flush();
+
+                    return baos.toByteArray();
+                }
+            }
         }
         catch (IOException e)
         {
@@ -409,28 +410,26 @@
     public static final byte[] decompress(byte[] bytes)
     {
         Assert.notNull(bytes, "bytes");
-        
-        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        byte[] buffer = new byte[bytes.length];
-        int length;
 
         try
         {
-            GZIPInputStream gis = new GZIPInputStream(bais);
-            while ((length = gis.read(buffer)) != -1)
+            try (ByteArrayOutputStream baos = new ByteArrayOutputStream())
             {
-                baos.write(buffer, 0, length);
-            }
+                try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes))
+                {
+                    try (GZIPInputStream gis = new GZIPInputStream(bais))
+                    {
+                        byte[] buffer = new byte[bytes.length];
+                        int length;
+                        while ((length = gis.read(buffer)) != -1)
+                        {
+                            baos.write(buffer, 0, length);
+                        }
+                    }
+                }
 
-            byte[] moreBytes = baos.toByteArray();
-            baos.close();
-            bais.close();
-            gis.close();
-            baos = null;
-            bais = null;
-            gis = null;
-            return moreBytes;
+                return baos.toByteArray();
+            }
         }
         catch (IOException e)
         {
diff --git a/impl/src/main/java/org/apache/myfaces/component/validate/WholeBeanValidator.java b/impl/src/main/java/org/apache/myfaces/component/validate/WholeBeanValidator.java
index d55f115..2132a45 100644
--- a/impl/src/main/java/org/apache/myfaces/component/validate/WholeBeanValidator.java
+++ b/impl/src/main/java/org/apache/myfaces/component/validate/WholeBeanValidator.java
@@ -21,9 +21,8 @@
 

 import org.apache.myfaces.el.ELContextDecorator;

 import org.apache.myfaces.el.ValueReferenceResolver;

-import java.io.ByteArrayInputStream;

-import java.io.ByteArrayOutputStream;

 import java.io.IOException;

+import java.io.ObjectInputStream;

 import java.io.ObjectOutputStream;

 import java.io.Serializable;

 import java.lang.reflect.Constructor;

@@ -64,6 +63,7 @@
 import org.apache.myfaces.util.MessageUtils;

 import org.apache.myfaces.util.MyFacesObjectInputStream;

 import org.apache.myfaces.util.ExternalSpecifications;

+import org.apache.myfaces.util.lang.FastByteArrayOutputStream;

 

 /**

  *

@@ -214,20 +214,19 @@
     

     private Object copySerializableObject(Object base)

     {

-        Object copy = null;

         try 

         {

-            ByteArrayOutputStream baos = new ByteArrayOutputStream();

-            ObjectOutputStream oos = new ObjectOutputStream(baos);

-            oos.writeObject(base);

-            oos.flush();

-            oos.close();

-            baos.close();

-            byte[] byteData = baos.toByteArray();

-            ByteArrayInputStream bais = new ByteArrayInputStream(byteData);

+            FastByteArrayOutputStream baos = new FastByteArrayOutputStream();

+            try (ObjectOutputStream oos = new ObjectOutputStream(baos))

+            {

+                oos.writeObject(base);

+                oos.flush();

+            }

+

+            ObjectInputStream ois = new MyFacesObjectInputStream(baos.getInputStream());

             try 

             {

-                copy = new MyFacesObjectInputStream(bais).readObject();

+                return ois.readObject();

             }

             catch (ClassNotFoundException e)

             {

@@ -238,7 +237,8 @@
         {

             //e.printStackTrace();

         }

-        return copy;

+

+        return null;

     }    

     

     private javax.validation.Validator createValidator(final ValidatorFactory validatorFactory, 

diff --git a/impl/src/main/java/org/apache/myfaces/renderkit/html/util/HTMLEncoder.java b/impl/src/main/java/org/apache/myfaces/renderkit/html/util/HTMLEncoder.java
index 27154f1..36e49be 100644
--- a/impl/src/main/java/org/apache/myfaces/renderkit/html/util/HTMLEncoder.java
+++ b/impl/src/main/java/org/apache/myfaces/renderkit/html/util/HTMLEncoder.java
@@ -18,10 +18,10 @@
  */
 package org.apache.myfaces.renderkit.html.util;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStreamWriter;
 import java.io.Writer;
+import org.apache.myfaces.util.lang.FastByteArrayOutputStream;
 
 /**
  * Converts Strings so that they can be used within HTML-Code.
@@ -688,28 +688,30 @@
     
     private static String percentEncodeNonUsAsciiCharacter(char c, String characterEncoding)
     {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream(10);
-        StringBuilder builder = new StringBuilder();
+        FastByteArrayOutputStream baos = new FastByteArrayOutputStream(10);
         try
         {
-            OutputStreamWriter writer = new OutputStreamWriter(baos,characterEncoding);
-            writer.write(c);
-            writer.flush();
+            try (OutputStreamWriter writer = new OutputStreamWriter(baos, characterEncoding))
+            {
+                writer.write(c);
+                writer.flush();
+            }
         }
-        catch(IOException e)
+        catch (IOException e)
         {
-            baos.reset();
             return null;
         }
-        
-        byte [] byteArray =  baos.toByteArray();
-        for (int i=0; i < byteArray.length; i++)
+
+        StringBuilder builder = new StringBuilder();
+
+        byte[] byteArray = baos.getByteArray();
+        for (int i = 0; i < baos.getSize(); i++)
         {
             builder.append('%');
             builder.append(HEX_CHARSET.charAt( (( ((short) byteArray[i] & 0xFF ) >> 0x4) % 0x10)) );
             builder.append(HEX_CHARSET.charAt( ((short) byteArray[i] & 0xFF ) % 0x10));
         }
-        
+
         return builder.toString();
     }
 
@@ -1100,22 +1102,23 @@
     private static void percentEncodeNonUsAsciiCharacter(Writer currentWriter, char c, String characterEncoding) 
         throws IOException
     {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream(10);
+        FastByteArrayOutputStream baos = new FastByteArrayOutputStream(10);
 
         try
         {
-            OutputStreamWriter writer = new OutputStreamWriter(baos,characterEncoding);
-            writer.write(c);
-            writer.flush();
+            try (OutputStreamWriter writer = new OutputStreamWriter(baos,characterEncoding))
+            {
+                writer.write(c);
+                writer.flush();
+            }
         }
-        catch(IOException e)
+        catch (IOException e)
         {
-            baos.reset();
             return;
         }
-        
-        byte [] byteArray =  baos.toByteArray();
-        for (int i=0; i < byteArray.length; i++)
+
+        byte[] byteArray = baos.getByteArray();
+        for (int i = 0; i < baos.getSize(); i++)
         {
             currentWriter.write('%');
             currentWriter.write(HEX_CHARSET.charAt( (( ((short) byteArray[i] & 0xFF ) >> 0x4) % 0x10)) );
diff --git a/impl/src/main/java/org/apache/myfaces/util/lang/FastByteArrayInputStream.java b/impl/src/main/java/org/apache/myfaces/util/lang/FastByteArrayInputStream.java
new file mode 100644
index 0000000..7e15dca
--- /dev/null
+++ b/impl/src/main/java/org/apache/myfaces/util/lang/FastByteArrayInputStream.java
@@ -0,0 +1,94 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.myfaces.util.lang;

+

+import java.io.InputStream;

+

+/**

+ * ByteArrayInputStream implementation that does not synchronize methods.

+ */

+public class FastByteArrayInputStream extends InputStream

+{

+    /**

+     * Our byte buffer

+     */

+    protected byte[] buf = null;

+

+    /**

+     * Number of bytes that we can read from the buffer

+     */

+    protected int count = 0;

+

+    /**

+     * Number of bytes that have been read from the buffer

+     */

+    protected int pos = 0;

+

+    public FastByteArrayInputStream(byte[] buf, int count)

+    {

+        this.buf = buf;

+        this.count = count;

+    }

+

+    @Override

+    public final int available()

+    {

+        return count - pos;

+    }

+

+    @Override

+    public final int read()

+    {

+        return pos < count ? (buf[pos++] & 0xff) : -1;

+    }

+

+    @Override

+    public final int read(byte[] b, int off, int len)

+    {

+        if (pos >= count)

+        {

+            return -1;

+        }

+

+        if ((pos + len) > count)

+        {

+            len = count - pos;

+        }

+

+        System.arraycopy(buf, pos, b, off, len);

+        pos += len;

+        return len;

+    }

+

+    @Override

+    public final long skip(long n)

+    {

+        if ((pos + n) > count)

+        {

+            n = count - pos;

+        }

+        if (n < 0)

+        {

+            return 0;

+        }

+

+        pos += n;

+        return n;

+    }

+}
\ No newline at end of file
diff --git a/impl/src/main/java/org/apache/myfaces/util/lang/FastByteArrayOutputStream.java b/impl/src/main/java/org/apache/myfaces/util/lang/FastByteArrayOutputStream.java
new file mode 100644
index 0000000..12ba8a8
--- /dev/null
+++ b/impl/src/main/java/org/apache/myfaces/util/lang/FastByteArrayOutputStream.java
@@ -0,0 +1,110 @@
+/*

+ * Licensed to the Apache Software Foundation (ASF) under one

+ * or more contributor license agreements.  See the NOTICE file

+ * distributed with this work for additional information

+ * regarding copyright ownership.  The ASF licenses this file

+ * to you under the Apache License, Version 2.0 (the

+ * "License"); you may not use this file except in compliance

+ * with the License.  You may obtain a copy of the License at

+ *

+ *   http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing,

+ * software distributed under the License is distributed on an

+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

+ * KIND, either express or implied.  See the License for the

+ * specific language governing permissions and limitations

+ * under the License.

+ */

+package org.apache.myfaces.util.lang;

+

+import java.io.InputStream;

+import java.io.OutputStream;

+

+/**

+ * ByteArrayOutputStream implementation that doesn't synchronize methods

+ * and doesn't copy the data on toByteArray().

+ */

+public class FastByteArrayOutputStream extends OutputStream

+{

+    protected byte[] buf = null;

+    protected int size = 0;

+

+    public FastByteArrayOutputStream()

+    {

+        this(1024);

+    }

+

+    public FastByteArrayOutputStream(int size)

+    {

+        this.size = 0;

+        this.buf = new byte[size];

+    }

+

+    /**

+     * Ensures that we have a large enough buffer for the given size.

+     */

+    private void verifyBufferSize(int sz)

+    {

+        if (sz > buf.length)

+        {

+            byte[] old = buf;

+            buf = new byte[Math.max(sz, 2 * buf.length)];

+            System.arraycopy(old, 0, buf, 0, old.length);

+            old = null;

+        }

+    }

+

+    public int getSize()

+    {

+        return size;

+    }

+

+    /**

+     * Returns the byte array containing the written data. Note that this

+     * array will almost always be larger than the amount of data actually

+     * written.

+     */

+    public byte[] getByteArray()

+    {

+        return buf;

+    }

+

+    @Override

+    public final void write(byte b[])

+    {

+        verifyBufferSize(size + b.length);

+        System.arraycopy(b, 0, buf, size, b.length);

+        size += b.length;

+    }

+

+    @Override

+    public final void write(byte b[], int off, int len)

+    {

+        verifyBufferSize(size + len);

+        System.arraycopy(b, off, buf, size, len);

+        size += len;

+    }

+

+    @Override

+    public final void write(int b)

+    {

+        verifyBufferSize(size + 1);

+        buf[size++] = (byte) b;

+    }

+

+    public void reset()

+    {

+        size = 0;

+    }

+

+    /**

+     * Returns a ByteArrayInputStream for reading back the written data

+     */

+    public InputStream getInputStream()

+    {

+        return new FastByteArrayInputStream(buf, size);

+    }

+}

+

+

diff --git a/impl/src/main/java/org/apache/myfaces/view/ServletViewResponseWrapper.java b/impl/src/main/java/org/apache/myfaces/view/ServletViewResponseWrapper.java
index f501314..549df4c 100644
--- a/impl/src/main/java/org/apache/myfaces/view/ServletViewResponseWrapper.java
+++ b/impl/src/main/java/org/apache/myfaces/view/ServletViewResponseWrapper.java
@@ -105,7 +105,7 @@
             }
             catch (IllegalStateException e)
             {
-            getResponse().getOutputStream().write(_byteArrayWriter.toByteArray());
+                getResponse().getOutputStream().write(_byteArrayWriter.toByteArray());
             }
             _byteArrayWriter.reset();
             _byteArrayWriter.flush();
@@ -180,23 +180,22 @@
 
     static class WrappedServletOutputStream extends ServletOutputStream
     {
-        private WrappedByteArrayOutputStream _byteArrayOutputStream;
-
+        private WrappedByteArrayOutputStream baos;
 
         public WrappedServletOutputStream()
         {
-            _byteArrayOutputStream = new WrappedByteArrayOutputStream(1024);
+            baos = new WrappedByteArrayOutputStream(1024);
         }
 
         @Override
         public void write(int i) throws IOException
         {
-            _byteArrayOutputStream.write(i);
+            baos.write(i);
         }
 
         public byte[] toByteArray()
         {
-            return _byteArrayOutputStream.toByteArray();
+            return baos.toByteArray();
         }
         
         /**
@@ -209,14 +208,14 @@
          */
         private void writeTo(Writer out, String encoding) throws IOException
         {
-            //Get the charset based on the encoding or return the default if 
-            //encoding == null
-            Charset charset = (encoding == null) ? 
-                    Charset.defaultCharset() : Charset.forName(encoding);
+            //Get the charset based on the encoding or return the default if encoding == null
+            Charset charset = encoding == null
+                    ? Charset.defaultCharset()
+                    : Charset.forName(encoding);
+
             CharsetDecoder decoder = charset.newDecoder();
             CharBuffer decodedBuffer = decoder.decode(
-                    ByteBuffer.wrap(_byteArrayOutputStream.getInnerArray(),
-                            0,_byteArrayOutputStream.getInnerCount()));
+                    ByteBuffer.wrap(baos.getInnerArray(), 0, baos.getInnerCount()));
             if (decodedBuffer.hasArray())
             {
                 out.write(decodedBuffer.array());
@@ -225,7 +224,7 @@
 
         public void reset()
         {
-            _byteArrayOutputStream.reset();
+            baos.reset();
         }
 
         @Override
@@ -248,7 +247,6 @@
          */
         static class WrappedByteArrayOutputStream extends ByteArrayOutputStream
         {
-            
             public WrappedByteArrayOutputStream()
             {
                 super();