You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commons-dev@ws.apache.org by sc...@apache.org on 2008/01/17 15:11:56 UTC

svn commit: r612822 - in /webservices/commons/trunk/modules/axiom/modules: axiom-api/src/main/java/org/apache/axiom/attachments/ axiom-api/src/main/java/org/apache/axiom/attachments/impl/ axiom-api/src/main/java/org/apache/axiom/attachments/utils/ axio...

Author: scheu
Date: Thu Jan 17 06:10:54 2008
New Revision: 612822

URL: http://svn.apache.org/viewvc?rev=612822&view=rev
Log:
WSCOMMONS-292
Contributor:Rich Scheuerle
Additional speedup to the Attachment processing.  This patch introduces the BAAInputStream and BAAOutputStream utility classes.  These classes are like the ByteArray*Stream classes except that they use an array of 4K byte[] to store the data.  The use of non-contiguous byte[] to store the attachment data will reduce the copying/resizing/gc overhead.

Added:
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemoryEnhanced.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/utils/BAAInputStream.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/utils/BAAOutputStream.java
    webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/attachments/BAATest.java
Modified:
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/BoundaryPushbackInputStream.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartFactory.java
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemory.java

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java?rev=612822&r1=612821&r2=612822&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/Attachments.java Thu Jan 17 06:10:54 2008
@@ -61,7 +61,7 @@
      * has the ability to "push back" or "unread" one byte.
      */
     PushbackInputStream pushbackInStream;
-    int PUSHBACK_SIZE = 1000;
+    int PUSHBACK_SIZE = 4 * 1024;
 
     /**
      * <code>attachmentsMap</code> stores the Data Handlers of the already parsed Mime Body Parts.

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/BoundaryPushbackInputStream.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/BoundaryPushbackInputStream.java?rev=612822&r1=612821&r2=612822&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/BoundaryPushbackInputStream.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/BoundaryPushbackInputStream.java Thu Jan 17 06:10:54 2008
@@ -60,6 +60,9 @@
     
     // Skip search array
     private short[] skip = null;
+    
+    // Working byte for read()
+    private byte[] read_byte = new  byte[1];
 
     /**
      * @param inStream
@@ -71,7 +74,11 @@
         this.is = inStream;
         this.boundary = boundary;
         this.rnBoundaryLen = boundary.length + 2;
-        this.bufferSize = Math.max(rnBoundaryLen * 2, pushBackSize);
+        
+        // The buffer must accomodate twice the boundary length and
+        // the maximum that we will ever push back (which is the entire buffer except for 
+        // the boundary)
+        this.bufferSize = Math.max(rnBoundaryLen * 2, pushBackSize + boundary.length);
     }
     
     /**
@@ -137,15 +144,24 @@
      *
      * @throws java.io.IOException
      */
+    
     public int read() throws java.io.IOException {
-
-        byte[] b = new byte[1];    
-        int read = read(b);
+  
+        // Short cut to avoid buffer copying
+        if (buffer != null && index > 0) {
+            if ((bIndex > 0 && (index+1) < bIndex) ||
+                 bIndex < 0 && index < (numBytes - rnBoundaryLen)) {
+                index++;
+                return (buffer[index-1]);
+            }
+        }
+  
+        int read = read(read_byte);
 
         if (read < 0) {
             return -1;
         } else {
-            return b[0];
+            return read_byte[0];
         }
     }
 
@@ -190,7 +206,7 @@
         
         do {
             
-            // Never read to the of the buffer because
+            // Never read to the end of the buffer because
             // the boundary may span buffers.
             int bcopy = Math.min((numBytes - rnBoundaryLen) - index,
                     len - bwritten);

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.java?rev=612822&r1=612821&r2=612822&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/BufferUtils.java Thu Jan 17 06:10:54 2008
@@ -29,7 +29,7 @@
  */
 public class BufferUtils {
     
-    public static final int BUFFER_LEN = 16 * 1024;
+    public static final int BUFFER_LEN = 4 * 1024;
     
     /**
      * Private utility to write the InputStream contents to the OutputStream.
@@ -48,7 +48,9 @@
         // Continue reading until no bytes are read and no
         // bytes are now available.
         while (bytesRead > 0 || is.available() > 0) {
-            os.write(buffer, 0, bytesRead);
+            if (bytesRead > 0) {
+                os.write(buffer, 0, bytesRead);
+            }
             bytesRead = is.read(buffer);
         }
         

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartFactory.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartFactory.java?rev=612822&r1=612821&r2=612822&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartFactory.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartFactory.java Thu Jan 17 06:10:54 2008
@@ -20,6 +20,8 @@
 
 import org.apache.axiom.attachments.MIMEBodyPartInputStream;
 import org.apache.axiom.attachments.Part;
+import org.apache.axiom.attachments.utils.BAAInputStream;
+import org.apache.axiom.attachments.utils.BAAOutputStream;
 import org.apache.axiom.om.OMException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -75,8 +77,10 @@
         
         try {
             // Read enough of the InputStream to build the headers 
+            // The readHeaders returns some extra bits that were read, but are part
+            // of the data section.
             Hashtable headers = new Hashtable();
-            readHeaders(in, headers);
+            InputStream dross = readHeaders(in, headers);
             
             
             if (isSOAPPart ||
@@ -88,24 +92,29 @@
                 // If this is a SOAPPart, keep it in memory.
                 
                 // Get the bytes of the data without a lot 
-                // of resizing and GC.  For now I will write to a
-                // private BAOS and get the byte buffer from it.
-                BAOS baos = new BAOS();
-                BufferUtils.inputStream2OutputStream(in, baos);
-                return new PartOnMemory(headers, baos.toByteArray(), baos.size());
+                // of resizing and GC.  The BAAOutputStream 
+                // keeps the data in non-contiguous byte buffers.
+                BAAOutputStream baaos = new BAAOutputStream();
+                BufferUtils.inputStream2OutputStream(dross, baaos);
+                BufferUtils.inputStream2OutputStream(in, baaos);
+                return new PartOnMemoryEnhanced(headers, baaos.buffers(), baaos.length());
             } else {
                 // We need to read the input stream to determine whether
                 // the size is bigger or smaller than the threshhold.
-                BAOS baos = new BAOS();
-                int total = BufferUtils.inputStream2OutputStream(in, baos, threshholdSize);
+                BAAOutputStream baaos = new BAAOutputStream();
+                int t1 = BufferUtils.inputStream2OutputStream(dross, baaos, threshholdSize);
+                int t2 =  BufferUtils.inputStream2OutputStream(in, baaos, threshholdSize - t1);
+                int total = t1 + t2;
+                
                 if (total < threshholdSize) {
-                    return new PartOnMemory(headers, baos.toByteArray(), baos.size());
+                    return new PartOnMemoryEnhanced(headers, baaos.buffers(), baaos.length());
                 } else {
-                    ByteArrayInputStream bais = 
-                        new ByteArrayInputStream(baos.toByteArray(), 0, baos.size());
+                    // A BAAInputStream is an input stream over a list of non-contiguous 4K buffers.
+                    BAAInputStream baais = 
+                        new BAAInputStream(baaos.buffers(), baaos.length());
                     
                     return new PartOnFile(headers, 
-                                          bais,
+                                          baais,
                                           in, 
                                           attachmentDir);
                 }
@@ -123,26 +132,66 @@
      * @param is
      * @param headers
      */
-    private static void readHeaders(InputStream in, Map headers) throws IOException {
-        int ch;
+    private static InputStream readHeaders(InputStream in, Map headers) throws IOException {
         if(log.isDebugEnabled()){
             log.debug("initHeaders");
         }
         boolean done = false;
         
-        // Read the characters into a StringBuffer and
-        // add each header to the map
+        
+        final int BUF_SIZE = 1024;
+        byte[] headerBytes = new byte[BUF_SIZE];
+        
+        int size = in.read(headerBytes);
+        int index = 0;
         StringBuffer sb = new StringBuffer(50);
-        while (!done && (ch = in.read()) != -1) {
+        
+        while (!done && index < size) {
+            
+            // Get the next byte
+            int ch = headerBytes[index];
+            index++;
+            if (index == size) {
+                size = in.read(headerBytes);
+                index =0;
+            }
+                
             if (ch == 13) {
-                if ((ch = in.read()) == 10) {
-                    if ((ch = in.read()) == 13) {
-                        if ((ch = in.read()) == 10) {
+                
+                // Get the next byte
+                ch = headerBytes[index];
+                index++;
+                if (index == size) {
+                    size = in.read(headerBytes);
+                    index =0;
+                }
+                
+                if (ch == 10) {
+                    // 13, 10 indicates we are starting a new line...thus a new header
+                    // Get the next byte
+                    ch = headerBytes[index];
+                    index++;
+                    if (index == size) {
+                        size = in.read(headerBytes);
+                        index =0;
+                    }
+                    
+                    if (ch == 13) {
+                        
+                        // Get the next byte
+                        ch = headerBytes[index];
+                        index++;
+                        if (index == size) {
+                            size = in.read(headerBytes);
+                            index =0;
+                        }
+                        
+                        if (ch == 10) {
                             // Blank line indicates we are done.
                             readHeader(sb, headers);
                             sb.delete(0, sb.length()); // Clear the buffer for reuse
                             done = true;
-                        }
+                        } 
                     } else {
                         // now parse and add the header String
                         readHeader(sb, headers);
@@ -160,8 +209,15 @@
         if(log.isDebugEnabled()){
             log.debug("End initHeaders");
         }
-        return;
+        
+        // Return an input stream containing the dross bits
+        if (index >= size) {
+            index = size;
+        }
+        ByteArrayInputStream dross = new ByteArrayInputStream(headerBytes, index, size-index);
+        return dross;
     }
+    
     
     /**
      * Parse the header into a name and value pair.

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemory.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemory.java?rev=612822&r1=612821&r2=612822&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemory.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemory.java Thu Jan 17 06:10:54 2008
@@ -34,7 +34,7 @@
 import java.util.Hashtable;
 
 /**
- * PartOnMemory stores that attachment in memory (in byte arrays)
+ * PartOnMemory stores the attachment in memory (in a byte[])
  * This implementation is used for smaller attachments to enhance 
  * performance.
  * 

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemoryEnhanced.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemoryEnhanced.java?rev=612822&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemoryEnhanced.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/impl/PartOnMemoryEnhanced.java Thu Jan 17 06:10:54 2008
@@ -0,0 +1,141 @@
+/*
+ * 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.axiom.attachments.impl;
+
+import org.apache.axiom.attachments.utils.BAAInputStream;
+import org.apache.axiom.om.OMException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.activation.DataHandler;
+import javax.activation.DataSource;
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeUtility;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Hashtable;
+
+/**
+ * PartOnMemoryEnhanced stores the attachment in memory (in non-contigous byte arrays)
+ * This implementation is used for smaller attachments to enhance 
+ * performance.
+ * 
+ * The PartOnMemoryEnhanced object is created by the PartFactory
+ * @see org.apache.axiom.attachments.impl.PartFactory.
+ */
+public class PartOnMemoryEnhanced extends AbstractPart {
+
+    private static Log log = LogFactory.getLog(PartOnMemoryEnhanced.class);
+    ArrayList data;  // Arrays of 4K buffers
+    int length;      // total length of data
+    
+    /**
+     * Construct a PartOnMemory
+     * @param headers
+     * @param data array list of 4K byte[]
+     * @param length (length of data in bytes)
+     */
+    PartOnMemoryEnhanced(Hashtable headers, ArrayList data, int length) {
+        super(headers);
+        this.data =  data;
+        this.length = length;
+    }
+
+    public DataHandler getDataHandler() throws MessagingException {
+        DataSource ds = new MyByteArrayDataSource();
+        return new DataHandler(ds);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.axiom.attachments.impl.AbstractPart#getFileName()
+     */
+    public String getFileName() throws MessagingException {
+        // There is no file name
+        return null;
+    }
+
+    public InputStream getInputStream() throws IOException, MessagingException {
+        return new BAAInputStream(data, length);
+    }
+    
+    public int getSize() throws MessagingException {
+        return length;
+    }
+    
+    
+    /**
+     * A DataSource that is backed by the byte[] and 
+     * headers map.
+     */
+    class MyByteArrayDataSource implements DataSource {
+
+        /* (non-Javadoc)
+         * @see javax.activation.DataSource#getContentType()
+         */
+        public String getContentType() {
+            String ct = getHeader("content-type");
+            return (ct == null) ?
+                    "application/octet-stream" :
+                    ct;
+        }
+
+        /* (non-Javadoc)
+         * @see javax.activation.DataSource#getInputStream()
+         */
+        public InputStream getInputStream() throws IOException {
+            InputStream is  = new BAAInputStream(data, length);
+            String cte = null;
+            try {
+                cte = getContentTransferEncoding();
+                if(cte != null){
+                    if(log.isDebugEnabled()){
+                        log.debug("Start Decoding stream");
+                    }
+                    return MimeUtility.decode(is, cte);
+
+                }
+            } catch (MessagingException e) {
+                if(log.isDebugEnabled()){
+                    log.debug("Stream Failed decoding");
+                }
+                throw new OMException(e);
+            }
+            return is;
+        }
+
+        /* (non-Javadoc)
+         * @see javax.activation.DataSource#getName()
+         */
+        public String getName() {
+            return "MyByteArrayDataSource";
+        }
+
+        /* (non-Javadoc)
+         * @see javax.activation.DataSource#getOutputStream()
+         */
+        public OutputStream getOutputStream() throws IOException {
+            throw new IOException("Not Supported");
+        }
+        
+    }
+
+}

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/utils/BAAInputStream.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/utils/BAAInputStream.java?rev=612822&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/utils/BAAInputStream.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/utils/BAAInputStream.java Thu Jan 17 06:10:54 2008
@@ -0,0 +1,96 @@
+package org.apache.axiom.attachments.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+
+/**
+ * BAAInputStream is like a ByteArrayInputStream.
+ * A ByteArrayInputStream stores the backing data in a byte[].
+ * BAAInputStream stores the backing data in a Array of 
+ * 4K byte[].  Using several non-contiguous chunks reduces 
+ * memory copy and resizing.
+ */
+public class BAAInputStream extends InputStream {
+
+    ArrayList data = new ArrayList();
+    int BUFFER_SIZE = 4 * 1024;
+    int i;
+    int size;
+    int currIndex;
+    int totalIndex;
+    int mark = 0;
+    byte[] currBuffer = null;
+    byte[] read_byte = new byte[1];
+    
+    public BAAInputStream(ArrayList data, int size) {
+        this.data = data;
+        this.size = size;
+        i = 0;
+        currIndex = 0;
+        totalIndex = 0;
+        currBuffer = (byte[]) data.get(0);
+    }
+
+    public int read() throws IOException {
+        int read = read(read_byte);
+
+        if (read < 0) {
+            return -1;
+        } else {
+            return read_byte[0];
+        }
+    }
+
+    public int available() throws IOException {
+        return size - totalIndex;
+    }
+
+
+    public synchronized void mark(int readlimit) {
+        mark = totalIndex;
+    }
+
+    public boolean markSupported() {
+        return true;
+    }
+
+    public int read(byte[] b, int off, int len) throws IOException {
+        int total = 0;
+        if (totalIndex >= size) {
+            return -1;
+        }
+        while (total < len && totalIndex < size) {
+            int copy = Math.min(len - total, BUFFER_SIZE - currIndex);
+            copy = Math.min(copy, size - totalIndex);
+            System.arraycopy(currBuffer, currIndex, b, off, copy);
+            total += copy;
+            currIndex += copy;
+            totalIndex += copy;
+            off += copy;
+            if (currIndex >= BUFFER_SIZE) {
+                if (i+1 < data.size()) {
+                    currBuffer = (byte[]) data.get(i+1);
+                    i++;
+                    currIndex = 0;
+                } else {
+                    currBuffer = null;
+                    currIndex = BUFFER_SIZE;
+                } 
+            }
+        }
+        return total;
+    }
+
+    public int read(byte[] b) throws IOException {
+        return this.read(b, 0, b.length);
+    }
+
+    public synchronized void reset() throws IOException {
+        i = mark / BUFFER_SIZE;
+        currIndex = mark - (i * BUFFER_SIZE);
+        currBuffer = (byte[]) data.get(i);
+        totalIndex = mark;
+    }
+
+}

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/utils/BAAOutputStream.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/utils/BAAOutputStream.java?rev=612822&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/utils/BAAOutputStream.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/attachments/utils/BAAOutputStream.java Thu Jan 17 06:10:54 2008
@@ -0,0 +1,63 @@
+package org.apache.axiom.attachments.utils;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+
+/**
+ * BAAOutputStream is like a ByteArrayOutputStream.
+ * A ByteArrayOutputStream stores the backing data in a byte[].
+ * BAAOutputStream stores the backing data in a Array of 
+ * 4K byte[].  Using several non-contiguous chunks reduces 
+ * memory copy and resizing.
+ */
+public class BAAOutputStream extends OutputStream {
+
+    ArrayList data = new ArrayList();
+    int BUFFER_SIZE = 4 * 1024;
+    int index = 0;
+    byte[] currBuffer = null;
+    public BAAOutputStream() {
+        super();
+        addBuffer();
+    }
+
+    private void addBuffer() {
+        currBuffer = new byte[BUFFER_SIZE];
+        data.add(currBuffer);
+        index = 0;
+    }
+    
+    public void write(byte[] b, int off, int len) throws IOException {
+       int total = 0;
+       while (total < len) {
+           int copy = Math.min(len-total, BUFFER_SIZE-index);
+           System.arraycopy(b, off, currBuffer, index, copy);
+           total += copy;
+           index += copy;
+           off += copy;
+           if (index >= BUFFER_SIZE) {
+               addBuffer();
+           }
+       }
+    }
+
+    public void write(byte[] b) throws IOException {
+        this.write(b, 0, b.length);
+    }
+
+    
+    byte[] writeByte = new byte[1];
+    public void write(int b) throws IOException {
+        writeByte[0] = (byte) b;
+        this.write(writeByte, 0, 1);
+    }
+
+    public ArrayList buffers() {
+        return data;
+    }
+    
+    public int length() {
+        return (BUFFER_SIZE * (data.size()-1)) + index;
+    }
+}

Added: webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/attachments/BAATest.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/attachments/BAATest.java?rev=612822&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/attachments/BAATest.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-tests/src/test/java/org/apache/axiom/attachments/BAATest.java Thu Jan 17 06:10:54 2008
@@ -0,0 +1,93 @@
+package org.apache.axiom.attachments;
+
+import org.apache.axiom.attachments.impl.BufferUtils;
+import org.apache.axiom.attachments.utils.BAAInputStream;
+import org.apache.axiom.attachments.utils.BAAOutputStream;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import junit.framework.TestCase;
+
+/**
+ * UnitTest for the BAAInputStream and BAAOutputStream classes.
+ */
+public class BAATest extends TestCase {
+
+    static final int  INPUT_SIZE = 100 * 1024;
+    static final int ITERATIONS = 10;
+    static final int PRIME = ITERATIONS/10;
+    static final int BAOS_SIZE = 4 * 1024;
+    byte[] input;
+    ByteArrayInputStream inputBAIS;
+    
+    public BAATest(String arg0) {
+        super(arg0);
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        input = new byte[INPUT_SIZE];
+        for (int i=0; i < INPUT_SIZE; i++) {
+            input[i] = 25;
+        }
+        inputBAIS = new ByteArrayInputStream(input);
+    }
+
+    public void test() throws Exception {
+        for (int i=0; i<5; i++) {
+            normal();
+            enhanced();
+        }
+    }
+    
+    public void normal() throws Exception {
+        long time = System.currentTimeMillis();
+        for (int i=0; i<ITERATIONS+PRIME; i++) {
+            if (i == PRIME) {
+                time = System.currentTimeMillis();
+            }
+            inputBAIS.reset();
+            ByteArrayOutputStream baos = new ByteArrayOutputStream(BAOS_SIZE);
+            BufferUtils.inputStream2OutputStream(inputBAIS, baos);
+            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+            baos = new ByteArrayOutputStream(BAOS_SIZE);
+            BufferUtils.inputStream2OutputStream(bais, baos);
+            bais = new ByteArrayInputStream(baos.toByteArray());
+            baos = new ByteArrayOutputStream(BAOS_SIZE);
+            for (int j= 1; j < 1000; j++) {
+                baos.write(bais.read());
+            }
+            BufferUtils.inputStream2OutputStream(bais, baos);
+            assertTrue(baos.toByteArray().length == INPUT_SIZE);
+        }
+        // Uncomment the follow
+        //System.out.println("Normal time = " + (System.currentTimeMillis()-time));
+    }
+    
+    public void enhanced() throws Exception {
+        long time = System.currentTimeMillis();
+        for (int i=0; i<ITERATIONS+PRIME; i++) {
+            if (i == PRIME) {
+                time = System.currentTimeMillis();
+            }
+            inputBAIS.reset();
+            BAAOutputStream baaos = new BAAOutputStream();
+            BufferUtils.inputStream2OutputStream(inputBAIS, baaos);
+            assertTrue("1: " + baaos.length() + " " + INPUT_SIZE, baaos.length() == INPUT_SIZE);
+
+            BAAInputStream baais = new BAAInputStream(baaos.buffers(), baaos.length());
+            baaos = new BAAOutputStream();
+            BufferUtils.inputStream2OutputStream(baais, baaos);
+            baais = new BAAInputStream(baaos.buffers(), baaos.length());
+            baaos = new BAAOutputStream();
+            for (int j= 1; j < 1000; j++) {
+                baaos.write(baais.read());
+            }
+            BufferUtils.inputStream2OutputStream(baais, baaos);
+            assertTrue("" + baaos.length() + " " + INPUT_SIZE, baaos.length() == INPUT_SIZE);
+        }
+        //System.out.println("Enhanced time = " + (System.currentTimeMillis()-time));
+    }
+    
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: commons-dev-help@ws.apache.org