You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by ve...@apache.org on 2015/05/16 01:56:51 UTC

svn commit: r1679662 [2/3] - in /webservices/axiom/trunk: modules/axiom-api/src/main/java/org/apache/axiom/attachments/ modules/axiom-api/src/main/java/org/apache/axiom/blob/ modules/axiom-api/src/main/java/org/apache/axiom/util/stax/ modules/axiom-api...

Copied: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/OverflowableBlobImpl.java (from r1678555, webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/OverflowBlob.java)
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/OverflowableBlobImpl.java?p2=webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/OverflowableBlobImpl.java&p1=webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/OverflowBlob.java&r1=1678555&r2=1679662&rev=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/OverflowBlob.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/OverflowableBlobImpl.java Fri May 15 23:56:49 2015
@@ -19,51 +19,31 @@
 
 package org.apache.axiom.blob;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 
 import org.apache.axiom.ext.io.ReadFromSupport;
 import org.apache.axiom.ext.io.StreamCopyException;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 
-/**
- * Blob implementation that stores data in a temporary file if the size exceeds a configurable
- * threshold. The data is first stored into a fixed size buffer. Once this buffer overflows, it is
- * transferred to a temporary file. The buffer is divided into a given number of fixed size chunks
- * that are allocated on demand. Since a temporary file may be created it is mandatory to call
- * {@link #release()} to discard the blob.
- */
-public final class OverflowBlob implements WritableBlob {
-    private static final Log log = LogFactory.getLog(OverflowBlob.class);
-    
-    static final int STATE_NEW = 0;
-    static final int STATE_UNCOMMITTED = 1;
-    static final int STATE_COMMITTED = 2;
-    
-    class OutputStreamImpl extends BlobOutputStream {
+final class OverflowableBlobImpl implements OverflowableBlob {
+    class OutputStreamImpl extends OutputStream implements ReadFromSupport {
         
-        private FileOutputStream fileOutputStream;
+        private OutputStream overflowOutputStream;
         
-        public WritableBlob getBlob() {
-            return OverflowBlob.this;
-        }
-
         public void write(byte[] b, int off, int len) throws IOException {
-
-            if (fileOutputStream != null) {
-                fileOutputStream.write(b, off, len);
+            if (state != State.UNCOMMITTED) {
+                throw new IllegalStateException();
+            }
+            if (overflowOutputStream != null) {
+                overflowOutputStream.write(b, off, len);
             } else if (len > (chunks.length-chunkIndex)*chunkSize - chunkOffset) {
 
                 // The buffer will overflow. Switch to a temporary file.
-                fileOutputStream = switchToTempFile();
+                overflowOutputStream = switchToOverflowBlob();
                 
                 // Write the new data to the temporary file.
-                fileOutputStream.write(b, off, len);
+                overflowOutputStream.write(b, off, len);
 
             } else {
 
@@ -97,17 +77,15 @@ public final class OverflowBlob implemen
             write(new byte[] { (byte)b }, 0, 1);
         }
 
-        public void flush() throws IOException {
-            if (fileOutputStream != null) {
-                fileOutputStream.flush();
+        public void close() throws IOException {
+            if (overflowOutputStream != null) {
+                overflowOutputStream.close();
             }
+            state = State.COMMITTED;
         }
 
-        public void close() throws IOException {
-            if (fileOutputStream != null) {
-                fileOutputStream.close();
-            }
-            state = STATE_COMMITTED;
+        public long readFrom(InputStream in, long length) throws StreamCopyException {
+            return OverflowableBlobImpl.this.readFrom(in, length, false);
         }
     }
     
@@ -205,15 +183,7 @@ public final class OverflowBlob implemen
      */
     final int chunkSize;
     
-    /**
-     * The prefix to be used in generating the name of the temporary file.
-     */
-    final String tempPrefix;
-    
-    /**
-     * The suffix to be used in generating the name of the temporary file.
-     */
-    final String tempSuffix;
+    final WritableBlobFactory overflowBlobFactory;
     
     /**
      * Array of <code>byte[]</code> representing the chunks of the buffer.
@@ -234,28 +204,22 @@ public final class OverflowBlob implemen
     int chunkOffset;
     
     /**
-     * The handle of the temporary file. This is only set when the memory buffer
-     * overflows and is written out to a temporary file.
+     * The overflow blob. This is only set when the memory buffer overflows and is written to a
+     * different blob.
      */
-    File temporaryFile;
+    WritableBlob overflowBlob;
     
     /**
      * The state of the blob.
      */
-    int state = STATE_NEW;
+    State state = State.NEW;
     
-    public OverflowBlob(int numberOfChunks, int chunkSize, String tempPrefix, String tempSuffix) {
+    OverflowableBlobImpl(int numberOfChunks, int chunkSize, WritableBlobFactory overflowBlobFactory) {
         this.chunkSize = chunkSize;
-        this.tempPrefix = tempPrefix;
-        this.tempSuffix = tempSuffix;
+        this.overflowBlobFactory = overflowBlobFactory;
         chunks = new byte[numberOfChunks][];
     }
     
-    public boolean isSupportingReadUncommitted() {
-        // This is actually a limitation of the implementation, not an intrinsic limitation
-        return false;
-    }
-
     /**
      * Get the current chunk to write to, allocating it if necessary.
      * 
@@ -279,46 +243,42 @@ public final class OverflowBlob implemen
      * @return an open FileOutputStream to the temporary file
      * @throws IOException
      */
-    FileOutputStream switchToTempFile() throws IOException {
-        temporaryFile = File.createTempFile(tempPrefix, tempSuffix);
-        if (log.isDebugEnabled()) {
-            log.debug("Using temporary file " + temporaryFile);
-        }
-        temporaryFile.deleteOnExit();
+    OutputStream switchToOverflowBlob() throws IOException {
+        overflowBlob = overflowBlobFactory.createBlob();
 
-        FileOutputStream fileOutputStream = new FileOutputStream(temporaryFile);
+        OutputStream outputStream = overflowBlob.getOutputStream();
         // Write the buffer to the temporary file.
         for (int i=0; i<chunkIndex; i++) {
-            fileOutputStream.write(chunks[i]);
+            outputStream.write(chunks[i]);
         }
 
         if (chunkOffset > 0) {
-            fileOutputStream.write(chunks[chunkIndex], 0, chunkOffset);
+            outputStream.write(chunks[chunkIndex], 0, chunkOffset);
         }
 
         // Release references to the buffer so that it can be garbage collected.
         chunks = null;
         
-        return fileOutputStream;
+        return outputStream;
     }
     
-    public BlobOutputStream getOutputStream() {
-        if (state != STATE_NEW) {
+    public OutputStream getOutputStream() {
+        if (state != State.NEW) {
             throw new IllegalStateException();
         } else {
-            state = STATE_UNCOMMITTED;
+            state = State.UNCOMMITTED;
             return new OutputStreamImpl();
         }
     }
     
-    public long readFrom(InputStream in, long length, boolean commit) throws StreamCopyException {
-        if (state == STATE_COMMITTED) {
+    long readFrom(InputStream in, long length, boolean commit) throws StreamCopyException {
+        if (state == State.COMMITTED) {
             throw new IllegalStateException();
         }
         // TODO: this will not work if the blob is in state UNCOMMITTED and we have already switched to a temporary file
         long read = 0;
         long toRead = length == -1 ? Long.MAX_VALUE : length;
-        while (true) {
+        while (toRead > 0) {
             int c;
             try {
                 int len = chunkSize-chunkOffset;
@@ -339,33 +299,15 @@ public final class OverflowBlob implemen
                 chunkIndex++;
                 chunkOffset = 0;
                 if (chunkIndex == chunks.length) {
-                    FileOutputStream fileOutputStream;
+                    OutputStream out;
                     try {
-                        fileOutputStream = switchToTempFile();
+                        out = switchToOverflowBlob();
                     } catch (IOException ex) {
                         throw new StreamCopyException(StreamCopyException.WRITE, ex);
                     }
-                    byte[] buf = new byte[4096];
-                    while (true) {
-                        int c2;
-                        try {
-                            c2 = in.read(buf, 0, (int)Math.min(toRead, 4096));
-                        } catch (IOException ex) {
-                            throw new StreamCopyException(StreamCopyException.READ, ex);
-                        }
-                        if (c2 == -1) {
-                            break;
-                        }
-                        try {
-                            fileOutputStream.write(buf, 0, c2);
-                        } catch (IOException ex) {
-                            throw new StreamCopyException(StreamCopyException.WRITE, ex);
-                        }
-                        read += c2;
-                        toRead -= c2;
-                    }
+                    read += IOUtil.copy(in, out, toRead);
                     try {
-                        fileOutputStream.close();
+                        out.close();
                     } catch (IOException ex) {
                         throw new StreamCopyException(StreamCopyException.WRITE, ex);
                     }
@@ -373,61 +315,33 @@ public final class OverflowBlob implemen
                 }
             }
         }
-        state = commit ? STATE_COMMITTED : STATE_UNCOMMITTED;
+        state = commit ? State.COMMITTED : State.UNCOMMITTED;
         return read;
     }
     
-    public long readFrom(InputStream in, long length) throws StreamCopyException {
-        return readFrom(in, length, state == STATE_NEW);
+    public long readFrom(InputStream in) throws StreamCopyException {
+        if (state != State.NEW) {
+            throw new IllegalStateException();
+        }
+        return readFrom(in, -1, true);
     }
 
     public InputStream getInputStream() throws IOException {
-        if (state != STATE_COMMITTED) {
+        if (state != State.COMMITTED) {
             throw new IllegalStateException();
-        } else if (temporaryFile != null) {
-            return new FileInputStream(temporaryFile);
+        } else if (overflowBlob != null) {
+            return overflowBlob.getInputStream();
         } else {
             return new InputStreamImpl();
         }
     }
     
     public void writeTo(OutputStream out) throws StreamCopyException {
-        if (temporaryFile != null) {
-            FileInputStream in;
-            try {
-                in = new FileInputStream(temporaryFile);
-            } catch (IOException ex) {
-                throw new StreamCopyException(StreamCopyException.READ, ex);
-            }
-            try {
-                if (out instanceof ReadFromSupport) {
-                    ((ReadFromSupport)out).readFrom(in, -1);
-                } else {
-                    byte[] buf = new byte[4096];
-                    while (true) {
-                        int c;
-                        try {
-                            c = in.read(buf);
-                        } catch (IOException ex) {
-                            throw new StreamCopyException(StreamCopyException.READ, ex);
-                        }
-                        if (c == -1) {
-                            break;
-                        }
-                        try {
-                            out.write(buf, 0, c);
-                        } catch (IOException ex) {
-                            throw new StreamCopyException(StreamCopyException.WRITE, ex);
-                        }
-                    }
-                }
-            } finally {
-                try {
-                    in.close();
-                } catch (IOException ex) {
-                    throw new StreamCopyException(StreamCopyException.READ, ex);
-                }
-            }
+        if (state != State.COMMITTED) {
+            throw new IllegalStateException();
+        }
+        if (overflowBlob != null) {
+            overflowBlob.writeTo(out);
         } else {
             try {
                 for (int i=0; i<chunkIndex; i++) {
@@ -442,27 +356,26 @@ public final class OverflowBlob implemen
         }
     }
     
-    public long getLength() {
-        if (temporaryFile != null) {
-            return temporaryFile.length();
+    public long getSize() {
+        if (state != State.COMMITTED) {
+            throw new IllegalStateException();
+        }
+        if (overflowBlob != null) {
+            return overflowBlob.getSize();
         } else {
             return chunkIndex*chunkSize + chunkOffset;
         }
     }
     
-    public void release() {
-        if (temporaryFile != null) {
-            if (log.isDebugEnabled()) {
-                log.debug("Deleting temporary file " + temporaryFile);
-            }
-            temporaryFile.delete();
+    public void release() throws IOException {
+        if (overflowBlob != null) {
+            overflowBlob.release();
+            overflowBlob = null;
         }
+        state = State.RELEASED;
     }
 
-    protected void finalize() throws Throwable {
-        if (temporaryFile != null) {
-            log.warn("Cleaning up unreleased temporary file " + temporaryFile);
-            temporaryFile.delete();
-        }
+    public WritableBlob getOverflowBlob() {
+        return overflowBlob;
     }
 }

Added: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/State.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/State.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/State.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/State.java Fri May 15 23:56:49 2015
@@ -0,0 +1,26 @@
+/*
+ * 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.blob;
+
+enum State {
+    NEW,
+    UNCOMMITTED,
+    COMMITTED,
+    RELEASED
+}

Propchange: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/State.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/TempFileBlobFactory.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/TempFileBlobFactory.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/TempFileBlobFactory.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/TempFileBlobFactory.java Fri May 15 23:56:49 2015
@@ -0,0 +1,42 @@
+/*
+ * 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.blob;
+
+import java.io.File;
+import java.io.IOException;
+
+final class TempFileBlobFactory implements WritableBlobFactory {
+    private final String tempPrefix;
+    private final String tempSuffix;
+    private final File tempDirectory;
+
+    TempFileBlobFactory(String tempPrefix, String tempSuffix, File tempDirectory) {
+        this.tempPrefix = tempPrefix;
+        this.tempSuffix = tempSuffix;
+        this.tempDirectory = tempDirectory;
+    }
+
+    public WritableBlob createBlob() {
+        return new TempFileBlobImpl(this);
+    }
+    
+    File createTempFile() throws IOException {
+        return File.createTempFile(tempPrefix, tempSuffix, tempDirectory);
+    }
+}

Propchange: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/TempFileBlobFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/TempFileBlobImpl.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/TempFileBlobImpl.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/TempFileBlobImpl.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/TempFileBlobImpl.java Fri May 15 23:56:49 2015
@@ -0,0 +1,97 @@
+/*
+ * 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.blob;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+final class TempFileBlobImpl extends AbstractWritableBlob {
+    private static final Log log = LogFactory.getLog(TempFileBlobImpl.class);
+    
+    private final TempFileBlobFactory factory;
+    private File file;
+    private State state = State.NEW;
+
+    TempFileBlobImpl(TempFileBlobFactory factory) {
+        this.factory = factory;
+    }
+
+    public OutputStream getOutputStream() throws IOException {
+        if (state != State.NEW) {
+            throw new IllegalStateException();
+        }
+        file = factory.createTempFile();
+        if (log.isDebugEnabled()) {
+            log.debug("Using temporary file " + file);
+        }
+        file.deleteOnExit();
+        OutputStream out = new FileOutputStream(file) {
+            @Override
+            public void close() throws IOException {
+                super.close();
+                state = State.COMMITTED;
+            }
+        };
+        state = State.UNCOMMITTED;
+        return out;
+    }
+
+    public InputStream getInputStream() throws IOException {
+        if (state != State.COMMITTED) {
+            throw new IllegalStateException();
+        }
+        // We know that we are accessing a regular file and since we don't leak the
+        // location of the file, nobody else should be modifying it. Therefore we can
+        // return an input stream that supports mark/reset.
+        return new TempFileInputStream(file);
+    }
+
+    public long getSize() {
+        if (state != State.COMMITTED) {
+            throw new IllegalStateException();
+        }
+        return file.length();
+    }
+
+    public void release() throws IOException {
+        if (file != null) {
+            if (log.isDebugEnabled()) {
+                log.debug("Deleting temporary file " + file);
+            }
+            if (!file.delete()) {
+                throw new IOException("Failed to delete " + file);
+            }
+            file = null;
+            state = State.RELEASED;
+        }
+    }
+
+    protected void finalize() throws Throwable {
+        if (file != null) {
+            log.warn("Cleaning up unreleased temporary file " + file);
+            file.delete();
+        }
+    }
+}

Propchange: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/TempFileBlobImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/TempFileInputStream.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/TempFileInputStream.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/TempFileInputStream.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/TempFileInputStream.java Fri May 15 23:56:49 2015
@@ -0,0 +1,51 @@
+/*
+ * 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.blob;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+final class TempFileInputStream extends FileInputStream {
+    private long markPosition;
+    
+    TempFileInputStream(File file) throws FileNotFoundException {
+        super(file);
+    }
+
+    @Override
+    public boolean markSupported() {
+        return true;
+    }
+
+    @Override
+    public synchronized void mark(int readlimit) {
+        try {
+            markPosition = getChannel().position();
+        } catch (IOException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    @Override
+    public synchronized void reset() throws IOException {
+        getChannel().position(markPosition);
+    }
+}

Propchange: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/TempFileInputStream.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/WritableBlob.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/WritableBlob.java?rev=1679662&r1=1679661&r2=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/WritableBlob.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/WritableBlob.java Fri May 15 23:56:49 2015
@@ -16,19 +16,19 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-
 package org.apache.axiom.blob;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 
+import org.apache.axiom.ext.io.ReadFromSupport;
 import org.apache.axiom.ext.io.StreamCopyException;
 
 /**
  * A writable blob.
  * <p>
- * The behavior of the methods defined by this interface is described in terms of three logical
+ * The behavior of the methods defined by this interface is described in terms of four logical
  * states the blob can be in:
  * <dl>
  *   <dt>NEW
@@ -37,40 +37,21 @@ import org.apache.axiom.ext.io.StreamCop
  *   <dd>Data is being written to the blob.
  *   <dt>COMMITTED
  *   <dd>All data has been written to the blob and the blob will no longer accept any new data.
+ *   <dt>RELEASED
+ *   <dd>The blob has been released, i.e. its data has been discarded.
  * </dl>
- * Whether or not reading data from the blob if is in state NEW or UNCOMMITTED depends on the
- * return value of {@link #isSupportingReadUncommitted()}.
+ * Reading data from a blob in state NEW or UNCOMMITTED is not supported: methods defined by the
+ * {@link Blob} interface will throw {@link IllegalStateException} if the blob is not in state
+ * COMMITTED.
  * <p>
- * Blobs are not thread safe.
+ * {@link WritableBlob} instances are generally not thread safe. However, for a blob in state
+ * COMMITTED, all methods defined by the {@link Blob} interface are thread safe.
  */
 public interface WritableBlob extends Blob {
     /**
-     * Determine whether the blob supports reading in state NEW or UNCOMMITTED. If this method
-     * returns <code>false</code> and the blob is in state NEW or UNCOMMITTED, any call to a method
-     * defined by the {@link Blob} superinterface will result in an {@link IllegalStateException}.
-     * If this method returns <code>true</code>, then any data written to the blob will be
-     * immediately available for reading. This is also true for an input stream obtained from
-     * {@link Blob#getInputStream()} before the data is written. This implies that it is possible
-     * for the input stream to first report the end of the stream and later allow reading additional
-     * data. Therefore, a pair of streams obtained from {@link #getOutputStream()} and
-     * {@link Blob#getInputStream()} behaves differently than a {@link java.io.PipedOutputStream}
-     * and {@link java.io.PipedInputStream} pair, because in this situation
-     * {@link java.io.PipedInputStream} would block.
-     * 
-     * @return <code>true</code> if the blob allows reading the data in state NEW or UNCOMMITTED;
-     *         <code>false</code> if the blob allows read operations only in state COMMITTED
-     */
-    boolean isSupportingReadUncommitted();
-    
-    /**
-     * Create an output stream to write data to the blob.
-     * <p>
-     * <em>Precondition:</em> The blob is in state NEW.
-     * <p>
-     * <em>Postcondition:</em> The blob is in state UNCOMMITTED.
-     * <p>
-     * Note that the pre- and postconditions imply that this method may be called at most once for
-     * a given blob instance.
+     * Create an output stream to write data to the blob. The blob must be in state NEW when this
+     * method is called. It will be in state UNCOMMITTED after this method completes successfully.
+     * Note that this implies that this method may be called at most once for a given blob instance.
      * <p>
      * Calls to methods of the returned output stream will modify the state of the blob
      * according to the following rules:
@@ -80,89 +61,44 @@ public interface WritableBlob extends Bl
      *       an {@link IOException} if the state is COMMITTED, i.e. if the stream has already been
      *       closed.
      * </ul>
+     * <p>
+     * The returned stream may implement {@link ReadFromSupport}, especially if the blob stores its
+     * data in memory (in which case {@link ReadFromSupport#readFrom(InputStream, long)} would read
+     * data directly into the buffers managed by the blob).
      * 
      * @return an output stream that can be used to write data to the blob
      * 
      * @throws IllegalStateException if the blob is not in state NEW
+     * @throws IOException if an I/O error occurred
      */
-    BlobOutputStream getOutputStream();
+    OutputStream getOutputStream() throws IOException;
 
     /**
      * Read data from the given input stream and write it to the blob.
      * <p>
      * A call to this method has the same effect as requesting an output stream using
      * {@link #getOutputStream()} and copying the data from the input stream to that
-     * output stream, but the implementation will achieve this result in a more efficient way.
-     * <p>
-     * <em>Precondition:</em> The blob is in state NEW or UNCOMMITTED.
-     * <p>
-     * <em>Postcondition:</em> The blob is in state UNCOMMITTED if <code>commit</code> is
-     * <code>false</code>. It is in state COMMITTED if <code>commit</code> is <code>true</code>.
-     * <p>
-     * The precondition implies that this method may be used after a call to
-     * {@link #getOutputStream()}. In that case it is illegal to set <code>commit</code> to
-     * <code>true</code> (because this would invalidate the state of the output stream).
-     * <p>
-     * The method transfers data from the input stream to the blob until one of the following
-     * conditions is met:
-     * <ul>
-     *   <li>The end of the input stream is reached.
-     *   <li>The value of the <code>length</code> argument is different from <code>-1</code>
-     *       and the number of bytes transferred is equal to <code>length</code>.
-     * </ul>
-     * 
-     * @param in An input stream to read data from. This method will not
-     *           close the stream.
-     * @param length the number of bytes to transfer, or <code>-1</code> if the method should
-     *               transfer data until the end of the input stream is reached
-     * @param commit indicates whether the blob should be in state COMMITTED after the operation
-     * @return the number of bytes transferred
-     * @throws StreamCopyException
-     * @throws IllegalStateException if the blob is in state COMMITTED or if
-     *         {@link #getOutputStream()} has been called before and <code>commit</code> is
-     *         <code>true</code>
-     */
-    long readFrom(InputStream in, long length, boolean commit) throws StreamCopyException;
-
-    /**
-     * Read data from the given input stream and write it to the blob.
-     * <p>
-     * This method is similar to {@link #readFrom(InputStream, long, boolean)}, except that the state
-     * of the blob after the invocation (i.e. the <code>commit</code> argument) is determined
-     * automatically:
+     * output stream, but the implementation may achieve this result in a more efficient way.
      * <p>
-     * <table border="2" rules="all" cellpadding="4" cellspacing="0">
-     *   <thead>
-     *     <tr><th>Precondition (state)</th><th>Postcondition (state)</th></tr>
-     *   </thead>
-     *   <tbody>
-     *     <tr><td>NEW</td><td>COMMITTED</td></tr>
-     *     <tr><td>UNCOMMITTED</td><td>UNCOMMITTED</td></tr>
-     *     <tr><td>COMMITTED</td><td><em>illegal</em></td></tr>
-     *   </tbody>
-     * </table>
+     * The blob must be in state NEW when this method is called. It will be in state UNCOMMITTED
+     * after this method completes successfully.
      * <p>
-     * There are thus two usage patterns for this method:
-     * <ol>
-     *   <li>The method is used to fill the blob with the data from an input stream, but no other
-     *       data is written to the blob.
-     *   <li>The method is used in parallel with the output stream returned by
-     *       {@link #getOutputStream()}: some data is written using the output stream and some
-     *       data is written using this method (for efficiency reasons).
-     * </ol>
+     * The method transfers data from the input stream to the blob until the end of the input
+     * stream is reached.
      * 
      * @param in An input stream to read data from. This method will not
      *           close the stream.
-     * @param length the number of bytes to transfer, or <code>-1</code> if the method should
-     *               transfer data until the end of the input stream is reached
      * @return the number of bytes transferred
      * @throws StreamCopyException
-     * @throws IllegalStateException if the blob is in state COMMITTED
+     * @throws IllegalStateException if the blob is not in state NEW
      */
-    long readFrom(InputStream in, long length) throws StreamCopyException;
+    long readFrom(InputStream in) throws StreamCopyException;
     
     /**
-     * Release all resources held by this blob.
+     * Release all resources held by this blob. This method will put the blob into the RELEASED
+     * state and the content will no longer be accessible.
+     *
+     * @throws IOException if the cleanup could not be completed because an I/O error occurred
      */
-    void release();
+    void release() throws IOException;
 }

Copied: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/WritableBlobFactory.java (from r1678555, webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/WritableBlobFactory.java)
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/WritableBlobFactory.java?p2=webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/WritableBlobFactory.java&p1=webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/WritableBlobFactory.java&r1=1678555&r2=1679662&rev=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/WritableBlobFactory.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/WritableBlobFactory.java Fri May 15 23:56:49 2015
@@ -20,6 +20,14 @@ package org.apache.axiom.blob;
 
 import org.apache.axiom.blob.WritableBlob;
 
+/**
+ * A factory for {@link WritableBlob} instances.
+ */
 public interface WritableBlobFactory {
+    /**
+     * Create a new {@link WritableBlob} instance.
+     * 
+     * @return the newly created instance
+     */
     WritableBlob createBlob();
 }

Modified: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/package.html
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/package.html?rev=1679662&r1=1679661&r2=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/package.html (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/blob/package.html Fri May 15 23:56:49 2015
@@ -21,8 +21,5 @@
 Contains utility classes to work with binary data. They are typically used to store
 data temporarily and often provide a better alternative than using
 {@link java.io.ByteArrayOutputStream} and {@link java.io.ByteArrayInputStream}.
-<p>
-Note that the API in this package is new in 1.2.9 and may undergo some changes in
-subsequent releases. Please use with care!
 </body>
 </html>
\ No newline at end of file

Modified: webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/XMLStreamReaderUtils.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/XMLStreamReaderUtils.java?rev=1679662&r1=1679661&r2=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/XMLStreamReaderUtils.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/XMLStreamReaderUtils.java Fri May 15 23:56:49 2015
@@ -29,8 +29,8 @@ import javax.xml.stream.XMLStreamExcepti
 import javax.xml.stream.XMLStreamReader;
 
 import org.apache.axiom.blob.BlobDataSource;
+import org.apache.axiom.blob.Blobs;
 import org.apache.axiom.blob.MemoryBlob;
-import org.apache.axiom.blob.WritableBlob;
 import org.apache.axiom.ext.stax.CharacterDataReader;
 import org.apache.axiom.ext.stax.DelegatingXMLStreamReader;
 import org.apache.axiom.ext.stax.datahandler.DataHandlerProvider;
@@ -231,7 +231,7 @@ public class XMLStreamReaderUtils {
             reader.next();
             return dh;
         } else {
-            WritableBlob blob = new MemoryBlob();
+            MemoryBlob blob = Blobs.createMemoryBlob();
             Writer out = new Base64DecodingOutputStreamWriter(blob.getOutputStream());
             try {
                 writeTextTo(reader, out);

Modified: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/attachments/PartOnFileTest.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/attachments/PartOnFileTest.java?rev=1679662&r1=1679661&r2=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/attachments/PartOnFileTest.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/attachments/PartOnFileTest.java Fri May 15 23:56:49 2015
@@ -19,12 +19,14 @@
 
 package org.apache.axiom.attachments;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import org.apache.axiom.om.AbstractTestCase;
 import org.apache.axiom.om.TestConstants;
 
 import javax.activation.DataHandler;
 import javax.activation.DataSource;
-import javax.activation.FileDataSource;
+
 import java.io.File;
 import java.io.InputStream;
 
@@ -60,9 +62,9 @@ public class PartOnFileTest extends Abst
 
         DataSource ds = dh.getDataSource();
         assertNotNull(ds);
-        if (!(ds instanceof FileDataSource)) {
-            fail("Expected FileDataSource, but got " + ds.getClass().getName());
-        }
+        // The attachment cleanup code in Axis2 relies on the assumption that attachments written
+        // to disk produce CachedFileDataSource instances.
+        assertThat(ds).isInstanceOf(CachedFileDataSource.class);
 
         assertEquals("image/jpeg", dh.getContentType());
     }

Modified: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/MemoryBlobTest.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/MemoryBlobTest.java?rev=1679662&r1=1679661&r2=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/MemoryBlobTest.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/MemoryBlobTest.java Fri May 15 23:56:49 2015
@@ -18,8 +18,7 @@
  */
 package org.apache.axiom.blob;
 
-import org.apache.axiom.blob.MemoryBlob;
-import org.apache.axiom.blob.WritableBlob;
+import org.apache.axiom.blob.suite.WritableBlobTestSuiteBuilder;
 
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
@@ -28,8 +27,8 @@ public class MemoryBlobTest extends Test
     public static TestSuite suite() {
         return new WritableBlobTestSuiteBuilder(new WritableBlobFactory() {
             public WritableBlob createBlob() {
-                return new MemoryBlob();
+                return Blobs.createMemoryBlob();
             }
-        }).build();
+        }, new int[] { 10000 }, true, false).build();
     }
 }

Copied: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/OverflowableBlobTest.java (from r1678555, webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/OverflowBlobTest.java)
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/OverflowableBlobTest.java?p2=webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/OverflowableBlobTest.java&p1=webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/OverflowBlobTest.java&r1=1678555&r2=1679662&rev=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/OverflowBlobTest.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/OverflowableBlobTest.java Fri May 15 23:56:49 2015
@@ -18,18 +18,17 @@
  */
 package org.apache.axiom.blob;
 
-import org.apache.axiom.blob.OverflowBlob;
-import org.apache.axiom.blob.WritableBlob;
+import org.apache.axiom.blob.suite.WritableBlobTestSuiteBuilder;
 
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
 
-public class OverflowBlobTest extends TestCase {
+public class OverflowableBlobTest extends TestCase {
     public static TestSuite suite() {
         return new WritableBlobTestSuiteBuilder(new WritableBlobFactory() {
             public WritableBlob createBlob() {
-                return new OverflowBlob(16, 1024, "test", ".dat");
+                return Blobs.createOverflowableBlob(16*1024, "test", ".dat", null);
             }
-        }).build();
+        }, new int[] { 10000, 16*1024, 100000 }, true, false).build();
     }
 }

Added: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TempFileBlobTest.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TempFileBlobTest.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TempFileBlobTest.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TempFileBlobTest.java Fri May 15 23:56:49 2015
@@ -0,0 +1,33 @@
+/*
+ * 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.blob;
+
+import org.apache.axiom.blob.suite.WritableBlobTestSuiteBuilder;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class TempFileBlobTest extends TestCase {
+    public static TestSuite suite() {
+        return new WritableBlobTestSuiteBuilder(
+                new TempFileBlobFactory("test", ".dat", null),
+                new int[] { 10000 },
+                false, true).build();
+    }
+}

Propchange: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TempFileBlobTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/ByteArrayOutputStreamWithReadFromSupport.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/ByteArrayOutputStreamWithReadFromSupport.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/ByteArrayOutputStreamWithReadFromSupport.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/ByteArrayOutputStreamWithReadFromSupport.java Fri May 15 23:56:49 2015
@@ -0,0 +1,74 @@
+/*
+ * 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.blob.suite;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.axiom.ext.io.ReadFromSupport;
+import org.apache.axiom.ext.io.StreamCopyException;
+
+public class ByteArrayOutputStreamWithReadFromSupport extends OutputStream implements ReadFromSupport {
+    private byte[] buffer = new byte[4096];
+    private int size;
+    private boolean readFromCalled;
+
+    @Override
+    public void write(int b) throws IOException {
+        if (buffer.length == size) {
+            byte[] newBuffer = new byte[size*2];
+            System.arraycopy(buffer, 0, newBuffer, 0, size);
+            buffer = newBuffer;
+        }
+        buffer[size++] = (byte)b;
+    }
+    
+    public long readFrom(InputStream inputStream, long length) throws StreamCopyException {
+        readFromCalled = true;
+        long read = 0;
+        while (length < 0 || read < length) {
+            int b;
+            try {
+                b = inputStream.read();
+            } catch (IOException ex) {
+                throw new StreamCopyException(StreamCopyException.READ, ex);
+            }
+            if (b == -1) {
+                break;
+            }
+            try {
+                write(b);
+            } catch (IOException ex) {
+                throw new StreamCopyException(StreamCopyException.WRITE, ex);
+            }
+        }
+        return read;
+    }
+
+    public byte[] toByteArray() {
+        byte[] result = new byte[size];
+        System.arraycopy(buffer, 0, result, 0, size);
+        return result;
+    }
+
+    public boolean isReadFromCalled() {
+        return readFromCalled;
+    }
+}

Propchange: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/ByteArrayOutputStreamWithReadFromSupport.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/CleanupCallback.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/CleanupCallback.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/CleanupCallback.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/CleanupCallback.java Fri May 15 23:56:49 2015
@@ -0,0 +1,25 @@
+/*
+ * 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.blob.suite;
+
+import java.io.IOException;
+
+public interface CleanupCallback {
+    void cleanup() throws IOException;
+}

Propchange: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/CleanupCallback.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/SizeSensitiveWritableBlobTestCase.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/SizeSensitiveWritableBlobTestCase.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/SizeSensitiveWritableBlobTestCase.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/SizeSensitiveWritableBlobTestCase.java Fri May 15 23:56:49 2015
@@ -0,0 +1,31 @@
+/*
+ * 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.blob.suite;
+
+import org.apache.axiom.blob.WritableBlobFactory;
+
+public abstract class SizeSensitiveWritableBlobTestCase extends WritableBlobTestCase {
+    protected final int size;
+    
+    public SizeSensitiveWritableBlobTestCase(WritableBlobFactory factory, State initialState, int size) {
+        super(factory, initialState);
+        this.size = size;
+        addTestParameter("size", size);
+    }
+}

Propchange: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/SizeSensitiveWritableBlobTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/State.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/State.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/State.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/State.java Fri May 15 23:56:49 2015
@@ -0,0 +1,81 @@
+/*
+ * 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.blob.suite;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.axiom.blob.WritableBlob;
+import org.apache.axiom.testutils.suite.Dimension;
+import org.apache.axiom.testutils.suite.MatrixTestCase;
+
+public abstract class State implements Dimension {
+    public static final State NEW = new State("NEW") {
+        @Override
+        public CleanupCallback transition(WritableBlob blob) throws IOException {
+            return null;
+        }
+    };
+
+    public static final State UNCOMMITTED = new State("UNCOMMITTED") {
+        @Override
+        public CleanupCallback transition(final WritableBlob blob) throws IOException {
+            final OutputStream out = blob.getOutputStream();
+            return new CleanupCallback() {
+                public void cleanup() throws IOException {
+                    out.close();
+                    blob.release();
+                }
+            };
+        }
+    };
+
+    public static final State COMMITTED = new State("COMMITTED") {
+        @Override
+        public CleanupCallback transition(final WritableBlob blob) throws IOException {
+            blob.getOutputStream().close();
+            return new CleanupCallback() {
+                public void cleanup() throws IOException {
+                    blob.release();
+                }
+            };
+        }
+    };
+
+    public static final State RELEASED = new State("RELEASED") {
+        @Override
+        public CleanupCallback transition(WritableBlob blob) throws IOException {
+            blob.getOutputStream().close();
+            blob.release();
+            return null;
+        }
+    };
+
+    private final String name;
+
+    private State(String name) {
+        this.name = name;
+    }
+
+    public final void addTestParameters(MatrixTestCase testCase) {
+        testCase.addTestParameter("state", name);
+    }
+    
+    public abstract CleanupCallback transition(WritableBlob blob) throws IOException;
+}

Propchange: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/State.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestAvailable.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestAvailable.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestAvailable.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestAvailable.java Fri May 15 23:56:49 2015
@@ -0,0 +1,46 @@
+/*
+ * 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.blob.suite;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import java.io.InputStream;
+
+import org.apache.axiom.blob.WritableBlob;
+import org.apache.axiom.blob.WritableBlobFactory;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.NullInputStream;
+
+public class TestAvailable extends WritableBlobTestCase {
+    public TestAvailable(WritableBlobFactory factory) {
+        super(factory, State.NEW);
+    }
+
+    @Override
+    protected void runTest(WritableBlob blob) throws Throwable {
+        blob.readFrom(new NullInputStream(1000));
+        InputStream in = blob.getInputStream();
+        try {
+            IOUtils.toByteArray(in, 200);
+            assertThat(in.available()).isEqualTo(800);
+        } finally {
+            in.close();
+        }
+    }
+}

Propchange: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestAvailable.java
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestGetInputStreamIllegalState.java (from r1678555, webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestGetInputStreamNew.java)
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestGetInputStreamIllegalState.java?p2=webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestGetInputStreamIllegalState.java&p1=webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestGetInputStreamNew.java&r1=1678555&r2=1679662&rev=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestGetInputStreamNew.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestGetInputStreamIllegalState.java Fri May 15 23:56:49 2015
@@ -16,49 +16,24 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.axiom.blob;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Random;
+package org.apache.axiom.blob.suite;
 
 import org.apache.axiom.blob.WritableBlob;
-import org.apache.commons.io.IOUtils;
+import org.apache.axiom.blob.WritableBlobFactory;
 
-public class TestGetInputStreamNew extends WritableBlobTestCase {
-    public TestGetInputStreamNew(WritableBlobFactory factory) {
-        super(factory);
+public class TestGetInputStreamIllegalState extends WritableBlobTestCase {
+    public TestGetInputStreamIllegalState(WritableBlobFactory factory, State state) {
+        super(factory, state);
+        state.addTestParameters(this);
     }
 
     @Override
     protected void runTest(WritableBlob blob) throws Throwable {
-        if (blob.isSupportingReadUncommitted()) {
-            Random random = new Random();
-            // The order of instructions is important here: we first get
-            // the input stream (when the blob is still in state NEW) and
-            // only then we request the output stream (which will put the
-            // stream in state UNCOMMITTED).
-            InputStream in = blob.getInputStream();
-            OutputStream out = blob.getOutputStream();
-            assertThat(in.read()).isEqualTo(-1);
-            // Check that any data written to the output stream immediately becomes available
-            // on the input stream.
-            byte[] data = new byte[1000];
-            random.nextBytes(data);
-            out.write(data);
-            assertThat(IOUtils.toByteArray(in)).isEqualTo(data);
-            random.nextBytes(data);
-            out.write(data);
-            assertThat(IOUtils.toByteArray(in)).isEqualTo(data);
-        } else {
-            try {
-                blob.getInputStream();
-                fail("Expected IllegalStateException");
-            } catch (IllegalStateException ex) {
-                // Expected
-            }
+        try {
+            blob.getInputStream();
+            fail("Expected IllegalStateException");
+        } catch (IllegalStateException ex) {
+            // Expected
         }
     }
 }

Copied: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestGetOutputStreamIllegalState.java (from r1678555, webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestGetOutputStreamCommitted.java)
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestGetOutputStreamIllegalState.java?p2=webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestGetOutputStreamIllegalState.java&p1=webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestGetOutputStreamCommitted.java&r1=1678555&r2=1679662&rev=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestGetOutputStreamCommitted.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestGetOutputStreamIllegalState.java Fri May 15 23:56:49 2015
@@ -16,21 +16,19 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.axiom.blob;
-
-import java.io.OutputStream;
+package org.apache.axiom.blob.suite;
 
 import org.apache.axiom.blob.WritableBlob;
+import org.apache.axiom.blob.WritableBlobFactory;
 
-public class TestGetOutputStreamCommitted extends WritableBlobTestCase {
-    public TestGetOutputStreamCommitted(WritableBlobFactory factory) {
-        super(factory);
+public class TestGetOutputStreamIllegalState extends WritableBlobTestCase {
+    public TestGetOutputStreamIllegalState(WritableBlobFactory factory, State state) {
+        super(factory, state);
+        state.addTestParameters(this);
     }
 
     @Override
     protected void runTest(WritableBlob blob) throws Throwable {
-        OutputStream out = blob.getOutputStream();
-        out.close();
         try {
             blob.getOutputStream();
             fail("Expected IllegalStateException");

Added: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestGetSizeIllegalState.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestGetSizeIllegalState.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestGetSizeIllegalState.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestGetSizeIllegalState.java Fri May 15 23:56:49 2015
@@ -0,0 +1,39 @@
+/*
+ * 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.blob.suite;
+
+import org.apache.axiom.blob.WritableBlob;
+import org.apache.axiom.blob.WritableBlobFactory;
+
+public class TestGetSizeIllegalState extends WritableBlobTestCase {
+    public TestGetSizeIllegalState(WritableBlobFactory factory, State state) {
+        super(factory, state);
+        state.addTestParameters(this);
+    }
+
+    @Override
+    protected void runTest(WritableBlob blob) throws Throwable {
+        try {
+            blob.getSize();
+            fail("Expected IllegalStateException");
+        } catch (IllegalStateException ex) {
+            // Expected
+        }
+    }
+}

Propchange: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestGetSizeIllegalState.java
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestMarkReset.java (from r1678555, webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestMarkReset.java)
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestMarkReset.java?p2=webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestMarkReset.java&p1=webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestMarkReset.java&r1=1678555&r2=1679662&rev=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestMarkReset.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestMarkReset.java Fri May 15 23:56:49 2015
@@ -16,40 +16,43 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.axiom.blob;
+package org.apache.axiom.blob.suite;
 
 import static com.google.common.truth.Truth.assertThat;
 
-import java.io.DataInputStream;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.Random;
 
 import org.apache.axiom.blob.WritableBlob;
+import org.apache.axiom.blob.WritableBlobFactory;
+import org.apache.commons.io.IOUtils;
 
-public class TestMarkReset extends WritableBlobTestCase {
-    public TestMarkReset(WritableBlobFactory factory) {
-        super(factory);
+public class TestMarkReset extends SizeSensitiveWritableBlobTestCase {
+    public TestMarkReset(WritableBlobFactory factory, int size) {
+        super(factory, State.NEW, size);
     }
 
     @Override
     protected void runTest(WritableBlob blob) throws Throwable {
         Random random = new Random();
-        byte[] sourceData1 = new byte[2000];
-        byte[] sourceData2 = new byte[2000];
+        byte[] sourceData1 = new byte[size/2];
+        byte[] sourceData2 = new byte[size/2];
         random.nextBytes(sourceData1);
         random.nextBytes(sourceData2);
         OutputStream out = blob.getOutputStream();
         out.write(sourceData1);
         out.write(sourceData2);
         out.close();
-        DataInputStream in = new DataInputStream(blob.getInputStream());
+        InputStream in = blob.getInputStream();
+        assertThat(in.markSupported()).isTrue();
         byte[] data1 = new byte[sourceData1.length];
         byte[] data2 = new byte[sourceData2.length];
-        in.readFully(data1);
+        IOUtils.readFully(in, data1);
         in.mark(sourceData2.length);
-        in.readFully(data2);
+        IOUtils.readFully(in, data2);
         in.reset();
-        in.readFully(data2);
+        IOUtils.readFully(in, data2);
         assertThat(data1).isEqualTo(sourceData1);
         assertThat(data2).isEqualTo(sourceData2);
     }

Copied: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestRandomReadWrite.java (from r1678555, webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestRandomReadWrite.java)
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestRandomReadWrite.java?p2=webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestRandomReadWrite.java&p1=webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestRandomReadWrite.java&r1=1678555&r2=1679662&rev=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestRandomReadWrite.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestRandomReadWrite.java Fri May 15 23:56:49 2015
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.axiom.blob;
+package org.apache.axiom.blob.suite;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -25,14 +25,13 @@ import java.io.OutputStream;
 import java.util.Random;
 
 import org.apache.axiom.blob.WritableBlob;
+import org.apache.axiom.blob.WritableBlobFactory;
 
-public class TestRandomReadWrite extends WritableBlobTestCase {
-    private final int size;
-    
+import com.google.common.collect.Range;
+
+public class TestRandomReadWrite extends SizeSensitiveWritableBlobTestCase {
     public TestRandomReadWrite(WritableBlobFactory factory, int size) {
-        super(factory);
-        this.size = size;
-        addTestParameter("size", size);
+        super(factory, State.NEW, size);
     }
 
     @Override
@@ -44,28 +43,41 @@ public class TestRandomReadWrite extends
         // Write the test data in chunks with random size
         int offset = 0;
         while (offset < data.length) {
-            int c = Math.min(512 + random.nextInt(1024), data.length - offset);
-            out.write(data, offset, c);
-            offset += c;
+            if (random.nextBoolean()) {
+                out.write(data[offset++]);
+            } else {
+                int c = Math.min(512 + random.nextInt(1024), data.length - offset);
+                out.write(data, offset, c);
+                offset += c;
+            }
         }
         out.close();
-        assertThat(blob.getLength()).isEqualTo(size);
+        assertThat(blob.getSize()).isEqualTo(size);
         // Reread the test data, again in chunks with random size
         InputStream in = blob.getInputStream();
         offset = 0;
         byte[] data2 = new byte[data.length];
         byte[] buffer = new byte[2048];
         while (true) {
-            int bufferOffset = random.nextInt(512);
-            int c = 512 + random.nextInt(1024);
-            int read = in.read(buffer, bufferOffset, c);
-            if (read == -1) {
-                break;
+            if (random.nextBoolean()) {
+                int b = in.read();
+                if (b == -1) {
+                    break;
+                }
+                assertThat(b).isIn(Range.closedOpen(0, 256));
+                data2[offset++] = (byte)b;
+            } else {
+                int bufferOffset = random.nextInt(512);
+                int c = 512 + random.nextInt(1024);
+                int read = in.read(buffer, bufferOffset, c);
+                if (read == -1) {
+                    break;
+                }
+                int newOffset = offset + read;
+                assertThat(newOffset).isAtMost(data2.length);
+                System.arraycopy(buffer, bufferOffset, data2, offset, read);
+                offset = newOffset;
             }
-            int newOffset = offset + read;
-            assertThat(newOffset).isAtMost(data2.length);
-            System.arraycopy(buffer, bufferOffset, data2, offset, read);
-            offset = newOffset;
         }
         assertThat(offset).isEqualTo(data2.length);
         in.close();

Added: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadEOF.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadEOF.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadEOF.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadEOF.java Fri May 15 23:56:49 2015
@@ -0,0 +1,47 @@
+/*
+ * 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.blob.suite;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import java.io.InputStream;
+
+import org.apache.axiom.blob.WritableBlob;
+import org.apache.axiom.blob.WritableBlobFactory;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.NullInputStream;
+
+public class TestReadEOF extends WritableBlobTestCase {
+    public TestReadEOF(WritableBlobFactory factory) {
+        super(factory, State.NEW);
+    }
+
+    @Override
+    protected void runTest(WritableBlob blob) throws Throwable {
+        blob.readFrom(new NullInputStream(100));
+        InputStream in = blob.getInputStream();
+        try {
+            IOUtils.toByteArray(in, 100);
+            assertThat(in.read()).isEqualTo(-1);
+            assertThat(in.read(new byte[10])).isEqualTo(-1);
+        } finally {
+            in.close();
+        }
+    }
+}

Propchange: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadEOF.java
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFrom.java (from r1678555, webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestReadFrom.java)
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFrom.java?p2=webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFrom.java&p1=webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestReadFrom.java&r1=1678555&r2=1679662&rev=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestReadFrom.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFrom.java Fri May 15 23:56:49 2015
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.axiom.blob;
+package org.apache.axiom.blob.suite;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -25,15 +25,13 @@ import java.io.InputStream;
 import java.util.Random;
 
 import org.apache.axiom.blob.WritableBlob;
+import org.apache.axiom.blob.WritableBlobFactory;
+import org.apache.axiom.testutils.io.CloseSensorInputStream;
 import org.apache.commons.io.IOUtils;
 
-public class TestReadFrom extends WritableBlobTestCase {
-    private final int size;
-    
+public class TestReadFrom extends SizeSensitiveWritableBlobTestCase {
     public TestReadFrom(WritableBlobFactory factory, int size) {
-        super(factory);
-        this.size = size;
-        addTestParameter("size", size);
+        super(factory, State.NEW, size);
     }
 
     @Override
@@ -41,13 +39,15 @@ public class TestReadFrom extends Writab
         Random random = new Random();
         byte[] data = new byte[size];
         random.nextBytes(data);
-        blob.readFrom(new ByteArrayInputStream(data), -1);
-        InputStream in = blob.getInputStream();
+        CloseSensorInputStream in = new CloseSensorInputStream(new ByteArrayInputStream(data));
+        assertThat(blob.readFrom(in)).isEqualTo(size);
+        assertThat(in.isClosed()).isFalse();
+        InputStream in2 = blob.getInputStream();
         try {
-            assertThat(IOUtils.toByteArray(in)).isEqualTo(data);
+            assertThat(IOUtils.toByteArray(in2)).isEqualTo(data);
         }
         finally {
-            in.close();
+            in2.close();
         }
     }
 }

Copied: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFromIllegalState.java (from r1678555, webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestReadFromCommitted.java)
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFromIllegalState.java?p2=webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFromIllegalState.java&p1=webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestReadFromCommitted.java&r1=1678555&r2=1679662&rev=1679662&view=diff
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/TestReadFromCommitted.java (original)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFromIllegalState.java Fri May 15 23:56:49 2015
@@ -16,29 +16,22 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.axiom.blob;
+package org.apache.axiom.blob.suite;
 
 import org.apache.axiom.blob.WritableBlob;
+import org.apache.axiom.blob.WritableBlobFactory;
 import org.apache.commons.io.input.NullInputStream;
 
-public class TestReadFromCommitted extends WritableBlobTestCase {
-    private final Boolean commit;
-    
-    public TestReadFromCommitted(WritableBlobFactory factory, Boolean commit) {
-        super(factory);
-        this.commit = commit;
-        addTestParameter("commit", String.valueOf(commit));
+public class TestReadFromIllegalState extends WritableBlobTestCase {
+    public TestReadFromIllegalState(WritableBlobFactory factory, State state) {
+        super(factory, state);
+        state.addTestParameters(this);
     }
 
     @Override
     protected void runTest(WritableBlob blob) throws Throwable {
-        blob.getOutputStream().close();
         try {
-            if (commit == null) {
-                blob.readFrom(new NullInputStream(0), -1);
-            } else {
-                blob.readFrom(new NullInputStream(0), -1, commit);
-            }
+            blob.readFrom(new NullInputStream(0));
             fail("Expected IllegalStateException");
         } catch (IllegalStateException ex) {
             // Expected

Added: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFromSupport.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFromSupport.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFromSupport.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFromSupport.java Fri May 15 23:56:49 2015
@@ -0,0 +1,56 @@
+/*
+ * 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.blob.suite;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.axiom.blob.WritableBlob;
+import org.apache.axiom.blob.WritableBlobFactory;
+import org.apache.axiom.ext.io.ReadFromSupport;
+import org.apache.commons.io.IOUtils;
+
+public class TestReadFromSupport extends WritableBlobTestCase {
+    public TestReadFromSupport(WritableBlobFactory factory) {
+        super(factory, State.NEW);
+    }
+
+    @Override
+    protected void runTest(WritableBlob blob) throws Throwable {
+        OutputStream out = blob.getOutputStream();
+        try {
+            out.write(new byte[] { 50, 60 });
+            ((ReadFromSupport)out).readFrom(new ByteArrayInputStream(new byte[] { 1, 2, 3, 4 }), -1);
+            ((ReadFromSupport)out).readFrom(new ByteArrayInputStream(new byte[] { 5, 6, 7, 8 }), 2);
+            out.write(new byte[] { 70, 80 });
+        } finally {
+            out.close();
+        }
+        InputStream in = blob.getInputStream();
+        try {
+            assertThat(IOUtils.toByteArray(in)).isEqualTo(
+                    new byte[] { 50, 60, 1, 2, 3, 4, 5, 6, 70, 80 });
+        } finally {
+            in.close();
+        }
+    }
+}

Propchange: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFromSupport.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFromWithError.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFromWithError.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFromWithError.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFromWithError.java Fri May 15 23:56:49 2015
@@ -0,0 +1,45 @@
+/*
+ * 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.blob.suite;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.apache.axiom.blob.WritableBlob;
+import org.apache.axiom.blob.WritableBlobFactory;
+import org.apache.axiom.ext.io.StreamCopyException;
+import org.apache.axiom.testutils.io.ExceptionInputStream;
+import org.apache.commons.io.input.NullInputStream;
+
+public class TestReadFromWithError extends WritableBlobTestCase {
+    public TestReadFromWithError(WritableBlobFactory factory) {
+        super(factory, State.NEW);
+    }
+
+    @Override
+    protected void runTest(WritableBlob blob) throws Throwable {
+        ExceptionInputStream in = new ExceptionInputStream(new NullInputStream(1000), 500);
+        try {
+            blob.readFrom(in);
+            fail("Expected StreamCopyException");
+        } catch (StreamCopyException ex) {
+            assertThat(ex.getOperation()).isEqualTo(StreamCopyException.READ);
+            assertThat(ex.getCause()).isSameAs(in.getException());
+        }
+    }
+}

Propchange: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadFromWithError.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadZeroLength.java
URL: http://svn.apache.org/viewvc/webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadZeroLength.java?rev=1679662&view=auto
==============================================================================
--- webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadZeroLength.java (added)
+++ webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadZeroLength.java Fri May 15 23:56:49 2015
@@ -0,0 +1,46 @@
+/*
+ * 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.blob.suite;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import java.io.InputStream;
+
+import org.apache.axiom.blob.WritableBlob;
+import org.apache.axiom.blob.WritableBlobFactory;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.NullInputStream;
+
+public class TestReadZeroLength extends WritableBlobTestCase {
+    public TestReadZeroLength(WritableBlobFactory factory) {
+        super(factory, State.NEW);
+    }
+
+    @Override
+    protected void runTest(WritableBlob blob) throws Throwable {
+        blob.readFrom(new NullInputStream(100));
+        InputStream in = blob.getInputStream();
+        try {
+            IOUtils.toByteArray(in, 50);
+            assertThat(in.read(new byte[0])).isEqualTo(0);
+        } finally {
+            in.close();
+        }
+    }
+}

Propchange: webservices/axiom/trunk/modules/axiom-api/src/test/java/org/apache/axiom/blob/suite/TestReadZeroLength.java
------------------------------------------------------------------------------
    svn:eol-style = native