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 ve...@apache.org on 2010/05/24 10:42:37 UTC
svn commit: r947564 - in
/webservices/commons/trunk/modules/axiom/modules/axiom-api/src:
main/java/org/apache/axiom/util/blob/ test/java/org/apache/axiom/util/blob/
Author: veithen
Date: Mon May 24 08:42:37 2010
New Revision: 947564
URL: http://svn.apache.org/viewvc?rev=947564&view=rev
Log:
Some cleanup of the org.apache.axiom.util.blob API to give it a chance to remain stable in the next releases.
Added:
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/package.html
Removed:
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/Slice.java
Modified:
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/Blob.java
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/MemoryBlob.java
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/OverflowBlob.java
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/WritableBlob.java
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/WritableBlobTestBase.java
Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/Blob.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/Blob.java?rev=947564&r1=947563&r2=947564&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/Blob.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/Blob.java Mon May 24 08:42:37 2010
@@ -23,6 +23,15 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import org.apache.axiom.ext.io.StreamCopyException;
+
+/**
+ * Stores binary data.
+ * <p>
+ * Not that blobs are not thread safe. While they support requesting multiple concurrent input
+ * streams, these streams must be used in the same thread, unless appropriate synchronization or
+ * locking is done.
+ */
public interface Blob {
/**
* Get an input stream to read the data in the blob.
@@ -35,11 +44,14 @@ public interface Blob {
/**
* Write the data to a given output stream.
*
- * @param out The output stream to write the data to. This method will
- * not close the stream.
- * @throws IOException
+ * @param out
+ * The output stream to write the data to. This method will not close the stream.
+ * @throws StreamCopyException
+ * Thrown if there is an I/O when reading the data from the blob or when writing it
+ * to the stream. {@link StreamCopyException#getOperation()} can be used to
+ * determine whether the failed operation was a read or a write.
*/
- void writeTo(OutputStream out) throws IOException;
+ void writeTo(OutputStream out) throws StreamCopyException;
/**
* Get the length of the data in the blob, i.e. the number of bytes.
Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/MemoryBlob.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/MemoryBlob.java?rev=947564&r1=947563&r2=947564&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/MemoryBlob.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/MemoryBlob.java Mon May 24 08:42:37 2010
@@ -67,7 +67,6 @@ public class MemoryBlob implements Writa
}
class InputStreamImpl extends InputStream {
- private final int size;
private int i;
private int currIndex;
private int totalIndex;
@@ -76,8 +75,6 @@ public class MemoryBlob implements Writa
private byte[] read_byte = new byte[1];
public InputStreamImpl() {
- size = (int)getLength();
- currBuffer = (byte[]) data.get(0);
}
public int read() throws IOException {
@@ -91,7 +88,7 @@ public class MemoryBlob implements Writa
}
public int available() throws IOException {
- return size - totalIndex;
+ return (int)getLength() - totalIndex;
}
@@ -104,11 +101,15 @@ public class MemoryBlob implements Writa
}
public int read(byte[] b, int off, int len) throws IOException {
+ int size = (int)getLength();
int total = 0;
if (totalIndex >= size) {
return -1;
}
while (total < len && totalIndex < size) {
+ if (currBuffer == null) {
+ currBuffer = (byte[]) data.get(i);
+ }
int copy = Math.min(len - total, BUFFER_SIZE - currIndex);
copy = Math.min(copy, size - totalIndex);
System.arraycopy(currBuffer, currIndex, b, off, copy);
@@ -118,13 +119,12 @@ public class MemoryBlob implements Writa
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;
}
+ currBuffer = null;
}
}
return total;
@@ -159,8 +159,16 @@ public class MemoryBlob implements Writa
index = 0;
}
+ public boolean isSupportingReadUncommitted() {
+ return true;
+ }
+
public long getLength() {
- return (BUFFER_SIZE * (data.size()-1)) + index;
+ if (data == null) {
+ return 0;
+ } else {
+ return (BUFFER_SIZE * (data.size()-1)) + index;
+ }
}
public BlobOutputStream getOutputStream() {
@@ -220,24 +228,28 @@ public class MemoryBlob implements Writa
}
public InputStream getInputStream() throws IOException {
- if (!committed) {
- throw new IllegalStateException();
- } else {
- return new InputStreamImpl();
- }
+ return new InputStreamImpl();
}
- public void writeTo(OutputStream os) throws IOException {
+ public void writeTo(OutputStream os) throws StreamCopyException {
int size = (int)getLength();
if (data != null) {
- int numBuffers = data.size();
- for (int j = 0; j < numBuffers-1; j ++) {
- os.write( (byte[]) data.get(j), 0, BUFFER_SIZE);
- }
- if (numBuffers > 0) {
- int writeLimit = size - ((numBuffers-1) * BUFFER_SIZE);
- os.write( (byte[]) data.get(numBuffers-1), 0, writeLimit);
+ try {
+ int numBuffers = data.size();
+ for (int j = 0; j < numBuffers-1; j ++) {
+ os.write( (byte[]) data.get(j), 0, BUFFER_SIZE);
+ }
+ if (numBuffers > 0) {
+ int writeLimit = size - ((numBuffers-1) * BUFFER_SIZE);
+ os.write( (byte[]) data.get(numBuffers-1), 0, writeLimit);
+ }
+ } catch (IOException ex) {
+ throw new StreamCopyException(StreamCopyException.WRITE, ex);
}
}
}
+
+ public void release() {
+ // no-op
+ }
}
Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/OverflowBlob.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/OverflowBlob.java?rev=947564&r1=947563&r2=947564&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/OverflowBlob.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/OverflowBlob.java Mon May 24 08:42:37 2010
@@ -256,6 +256,11 @@ public class OverflowBlob implements Wri
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.
*
@@ -388,28 +393,53 @@ public class OverflowBlob implements Wri
}
}
- public void writeTo(OutputStream out) throws IOException {
+ public void writeTo(OutputStream out) throws StreamCopyException {
if (temporaryFile != null) {
- FileInputStream in = new FileInputStream(temporaryFile);
+ 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];
- int c;
- while ((c = in.read(buf)) != -1) {
- out.write(buf, 0, c);
+ 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 {
- in.close();
+ try {
+ in.close();
+ } catch (IOException ex) {
+ throw new StreamCopyException(StreamCopyException.READ, ex);
+ }
}
} else {
- for (int i=0; i<chunkIndex; i++) {
- out.write(chunks[i]);
- }
- if (chunkOffset > 0) {
- out.write(chunks[chunkIndex], 0, chunkOffset);
+ try {
+ for (int i=0; i<chunkIndex; i++) {
+ out.write(chunks[i]);
+ }
+ if (chunkOffset > 0) {
+ out.write(chunks[chunkIndex], 0, chunkOffset);
+ }
+ } catch (IOException ex) {
+ throw new StreamCopyException(StreamCopyException.WRITE, ex);
}
}
}
Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/WritableBlob.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/WritableBlob.java?rev=947564&r1=947563&r2=947564&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/WritableBlob.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/WritableBlob.java Mon May 24 08:42:37 2010
@@ -40,9 +40,29 @@ import org.apache.axiom.ext.io.StreamCop
* </dl>
* If 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}.
+ * <p>
+ * Blobs are not 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.
@@ -140,4 +160,9 @@ public interface WritableBlob extends Bl
* @throws IllegalStateException if the blob is in state COMMITTED
*/
long readFrom(InputStream in, long length) throws StreamCopyException;
+
+ /**
+ * Release all resources held by this blob.
+ */
+ void release();
}
Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/package.html
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/package.html?rev=947564&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/package.html (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/package.html Mon May 24 08:42:37 2010
@@ -0,0 +1,10 @@
+<html>
+<body>
+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/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/WritableBlobTestBase.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/WritableBlobTestBase.java?rev=947564&r1=947563&r2=947564&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/WritableBlobTestBase.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/WritableBlobTestBase.java Mon May 24 08:42:37 2010
@@ -177,10 +177,31 @@ public abstract class WritableBlobTestBa
public void testGetInputStreamNew() throws Exception {
WritableBlob blob = createBlob();
try {
- blob.getInputStream();
- fail("Expected IllegalStateException");
- } catch (IllegalStateException ex) {
- // Expected
+ if (blob.isSupportingReadUncommitted()) {
+ // 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();
+ assertEquals(-1, in.read());
+ // 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);
+ assertTrue(Arrays.equals(data, IOUtils.toByteArray(in)));
+ random.nextBytes(data);
+ out.write(data);
+ assertTrue(Arrays.equals(data, IOUtils.toByteArray(in)));
+ } else {
+ try {
+ blob.getInputStream();
+ fail("Expected IllegalStateException");
+ } catch (IllegalStateException ex) {
+ // Expected
+ }
+ }
} finally {
releaseBlob(blob);
}
@@ -191,10 +212,24 @@ public abstract class WritableBlobTestBa
try {
OutputStream out = blob.getOutputStream();
try {
- blob.getInputStream();
- fail("Expected IllegalStateException");
- } catch (IllegalStateException ex) {
- // Expected
+ byte[] data = new byte[1000];
+ random.nextBytes(data);
+ out.write(data);
+ if (blob.isSupportingReadUncommitted()) {
+ InputStream in = blob.getInputStream();
+ try {
+ assertTrue(Arrays.equals(data, IOUtils.toByteArray(in)));
+ } finally {
+ in.close();
+ }
+ } else {
+ try {
+ blob.getInputStream();
+ fail("Expected IllegalStateException");
+ } catch (IllegalStateException ex) {
+ // Expected
+ }
+ }
} finally {
out.close();
}