Author: veithen Date: Wed Jul 15 20:48:47 2009 New Revision: 794410 URL: http://svn.apache.org/viewvc?rev=794410&view=rev Log: Created a MemoryBlob class based on the code of BAAOutputStream/BAAInputStream. This class implements the same interface as OverflowBlob (Synapse's TemporaryData). This will make it easy to switch between in-memory storage and file based storage of binary data. It also provides a nicer API than BAA(Input|Output)Stream.
Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/MemoryBlob.java (with props) webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/Slice.java (with props) webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/WritableBlob.java (with props) webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/MemoryBlobTest.java (with props) webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/WritableBlobTestBase.java - copied, changed from r793414, webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/OverflowBlobTest.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/OverflowBlob.java webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/OverflowBlobTest.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=794410&r1=794409&r2=794410&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 Wed Jul 15 20:48:47 2009 @@ -24,26 +24,12 @@ import java.io.OutputStream; public interface Blob { - OutputStream getOutputStream(); - /** - * Fill this object with data read from a given InputStream. - * <p> - * A call <code>tmp.readFrom(in)</code> has the same effect as the - * following code: - * <pre> - * OutputStream out = tmp.getOutputStream(); - * IOUtils.copy(in, out); - * out.close(); - * </pre> - * However it does so in a more efficient way. + * Get an input stream to read the data in the blob. * - * @param in An InputStream to read data from. This method will not - * close the stream. + * @return the input stream to read the data from * @throws IOException */ - void readFrom(InputStream in) throws IOException; - InputStream getInputStream() throws IOException; /** @@ -55,5 +41,10 @@ */ void writeTo(OutputStream out) throws IOException; + /** + * Get the length of the data in the blob, i.e. the number of bytes. + * + * @return the length of the data in the blob + */ long getLength(); } \ No newline at end of file Added: 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=794410&view=auto ============================================================================== --- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/MemoryBlob.java (added) +++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/MemoryBlob.java Wed Jul 15 20:48:47 2009 @@ -0,0 +1,225 @@ +/* + * 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.util.blob; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +import org.apache.axiom.attachments.impl.BufferUtils; + +public class MemoryBlob implements WritableBlob { + final static int BUFFER_SIZE = BufferUtils.BUFFER_LEN; + + class OutputStreamImpl extends OutputStream { + public void write(byte[] b, int off, int len) throws IOException { + int total = 0; + while (total < len) { + int copy = Math.min(len-total, BUFFER_SIZE-index); + System.arraycopy(b, off, currBuffer, index, copy); + total += copy; + index += copy; + off += copy; + if (index >= BUFFER_SIZE) { + addBuffer(); + } + } + } + + public void write(byte[] b) throws IOException { + this.write(b, 0, b.length); + } + + byte[] writeByte = new byte[1]; + public void write(int b) throws IOException { + writeByte[0] = (byte) b; + this.write(writeByte, 0, 1); + } + + public void close() throws IOException { + outputStream = null; + committed = true; + } + } + + class InputStreamImpl extends InputStream { + private final int size; + private int i; + private int currIndex; + private int totalIndex; + private int mark; + private byte[] currBuffer; + private byte[] read_byte = new byte[1]; + + public InputStreamImpl() { + size = (int)getLength(); + currBuffer = (byte[]) data.get(0); + } + + public int read() throws IOException { + int read = read(read_byte); + + if (read < 0) { + return -1; + } else { + return read_byte[0] & 0xFF; + } + } + + public int available() throws IOException { + return size - totalIndex; + } + + + public synchronized void mark(int readlimit) { + mark = totalIndex; + } + + public boolean markSupported() { + return true; + } + + public int read(byte[] b, int off, int len) throws IOException { + int total = 0; + if (totalIndex >= size) { + return -1; + } + while (total < len && totalIndex < size) { + int copy = Math.min(len - total, BUFFER_SIZE - currIndex); + copy = Math.min(copy, size - totalIndex); + System.arraycopy(currBuffer, currIndex, b, off, copy); + total += copy; + currIndex += copy; + totalIndex += copy; + off += copy; + if (currIndex >= BUFFER_SIZE) { + if (i+1 < data.size()) { + currBuffer = (byte[]) data.get(i+1); + i++; + currIndex = 0; + } else { + currBuffer = null; + currIndex = BUFFER_SIZE; + } + } + } + return total; + } + + public int read(byte[] b) throws IOException { + return this.read(b, 0, b.length); + } + + public synchronized void reset() throws IOException { + i = mark / BUFFER_SIZE; + currIndex = mark - (i * BUFFER_SIZE); + currBuffer = (byte[]) data.get(i); + totalIndex = mark; + } + } + + List data; // null here indicates the blob is in state NEW + int index; + byte[] currBuffer; + OutputStreamImpl outputStream; + boolean committed; + + private void init() { + data = new ArrayList(); + addBuffer(); + } + + void addBuffer() { + currBuffer = new byte[BUFFER_SIZE]; + data.add(currBuffer); + index = 0; + } + + public long getLength() { + return (BUFFER_SIZE * (data.size()-1)) + index; + } + + public OutputStream getOutputStream() { + if (data != null) { + throw new IllegalStateException(); + } else { + init(); + return outputStream = new OutputStreamImpl(); + } + } + + public void readFrom(InputStream in, boolean commit) throws IOException { + if (data == null) { + init(); + } + + long bytesReceived = 0; + + // Now directly write to the buffers + boolean done = false; + while (!done) { + + // Don't get more than will fit in the current buffer + int len = BUFFER_SIZE - index; + + // Now get the bytes + int bytesRead = in.read(currBuffer, index, len); + if (bytesRead >= 0) { + bytesReceived += bytesRead; + index += bytesRead; + if (index >= BUFFER_SIZE) { + addBuffer(); + } + } else { + done = true; + } + } + + committed = commit; + } + + public void readFrom(InputStream in) throws IOException { + readFrom(in, data == null); + } + + public InputStream getInputStream() throws IOException { + if (!committed) { + throw new IllegalStateException(); + } else { + return new InputStreamImpl(); + } + } + + public void writeTo(OutputStream os) throws IOException { + 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); + } + } + } +} Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/MemoryBlob.java ------------------------------------------------------------------------------ svn:eol-style = native 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=794410&r1=794409&r2=794410&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 Wed Jul 15 20:48:47 2009 @@ -1,3 +1,22 @@ +/* + * 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.util.blob; import java.io.File; @@ -23,10 +42,13 @@ * on demand. Since a temporary file may be created it is mandatory to * call {...@link #release()} to discard the temporary data. */ -public class OverflowBlob implements Blob { - +public 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 OutputStream { private FileOutputStream fileOutputStream; @@ -85,6 +107,7 @@ if (fileOutputStream != null) { fileOutputStream.close(); } + state = STATE_COMMITTED; } } @@ -145,7 +168,7 @@ public int read() throws IOException { byte[] b = new byte[1]; - return read(b) == -1 ? -1 : (int)b[0] & 0xFF; + return read(b) == -1 ? -1 : b[0] & 0xFF; } public boolean markSupported() { @@ -216,6 +239,11 @@ */ File temporaryFile; + /** + * The state of the blob. + */ + int state = STATE_NEW; + public OverflowBlob(int numberOfChunks, int chunkSize, String tempPrefix, String tempSuffix) { this.chunkSize = chunkSize; this.tempPrefix = tempPrefix; @@ -270,10 +298,16 @@ } public OutputStream getOutputStream() { - return new OutputStreamImpl(); + if (state != STATE_NEW) { + throw new IllegalStateException(); + } else { + state = STATE_UNCOMMITTED; + return new OutputStreamImpl(); + } } - public void readFrom(InputStream in) throws IOException { + public void readFrom(InputStream in, boolean commit) throws IOException { + // TODO: this will not work if the blob is in state UNCOMMITTED and we have already switched to a temporary file while (true) { int c = in.read(getCurrentChunk(), chunkOffset, chunkSize-chunkOffset); if (c == -1) { @@ -291,10 +325,17 @@ } } } + state = commit ? STATE_COMMITTED : STATE_UNCOMMITTED; } + public void readFrom(InputStream in) throws IOException { + readFrom(in, state == STATE_NEW); + } + public InputStream getInputStream() throws IOException { - if (temporaryFile != null) { + if (state != STATE_COMMITTED) { + throw new IllegalStateException(); + } else if (temporaryFile != null) { return new FileInputStream(temporaryFile); } else { return new InputStreamImpl(); Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/Slice.java URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/Slice.java?rev=794410&view=auto ============================================================================== --- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/Slice.java (added) +++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/Slice.java Wed Jul 15 20:48:47 2009 @@ -0,0 +1,24 @@ +/* + * 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.util.blob; + +public class Slice { + +} Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/Slice.java ------------------------------------------------------------------------------ svn:eol-style = native Added: 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=794410&view=auto ============================================================================== --- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/WritableBlob.java (added) +++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/WritableBlob.java Wed Jul 15 20:48:47 2009 @@ -0,0 +1,124 @@ +/* + * 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.util.blob; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * A writable blob. + * <p> + * The behavior of the methods defined by this interface is described in terms of three logical + * states the blob can be in: + * <dl> + * <dt>NEW + * <dd>The blob has just been created and no data has been written to it yet. + * <dt>UNCOMMITTED + * <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. + * </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}. + */ +public interface WritableBlob extends Blob { + /** + * 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. + * <p> + * Calls to methods of the returned output stream will modify the state of the blob + * according to the following rules: + * <ul> + * <li>A call to {...@link OutputStream#close()} will change the state to COMMITTED. + * <li>Calls to other methods will not modify the state of the blob. They will result in + * an {...@link IOException} if the state is COMMITTED, i.e. if the stream has already been + * closed. + * </ul> + * + * @return an output stream that can be used to write data to the blob + * + * @throws IllegalStateException if the blob is not in state NEW + */ + OutputStream getOutputStream(); + + /** + * 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). + * + * @param in An input stream to read data from. This method will not + * close the stream. + * @throws IOException + * @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> + */ + void readFrom(InputStream in, boolean commit) throws IOException; + + /** + * Read data from the given input stream and write it to the blob. + * <p> + * This method is similar to {...@link #readFrom(InputStream, boolean)}, except that the state + * of the blob after the invocation (i.e. the <code>commit</code> argument) is determined + * automatically: + * <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> + * <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> + * + * @throws IOException + * @throws IllegalStateException if the blob is in state COMMITTED + */ + void readFrom(InputStream in) throws IOException; +} Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/blob/WritableBlob.java ------------------------------------------------------------------------------ svn:eol-style = native Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/MemoryBlobTest.java URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/MemoryBlobTest.java?rev=794410&view=auto ============================================================================== --- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/MemoryBlobTest.java (added) +++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/MemoryBlobTest.java Wed Jul 15 20:48:47 2009 @@ -0,0 +1,30 @@ +/* + * 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.util.blob; + +public class MemoryBlobTest extends WritableBlobTestBase { + protected WritableBlob createBlob() { + return new MemoryBlob(); + } + + protected void releaseBlob(WritableBlob blob) { + // Nothing to do here + } +} Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/MemoryBlobTest.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/OverflowBlobTest.java URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/OverflowBlobTest.java?rev=794410&r1=794409&r2=794410&view=diff ============================================================================== --- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/OverflowBlobTest.java (original) +++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/OverflowBlobTest.java Wed Jul 15 20:48:47 2009 @@ -1,134 +1,30 @@ /* - * 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 + * 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 + * 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. + * 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.util.blob; -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Arrays; -import java.util.Random; - -import org.apache.commons.io.IOUtils; - -import junit.framework.TestCase; - -public class OverflowBlobTest extends TestCase { - private final static Random random = new Random(); - - private void doTestRandomReadWrite(int size) throws IOException { - byte[] data = new byte[size]; - random.nextBytes(data); - OverflowBlob tmp = new OverflowBlob(16, 1024, "test", ".dat"); - try { - OutputStream out = tmp.getOutputStream(); - // 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; - } - out.close(); - assertEquals(size, tmp.getLength()); - // Reread the test data, again in chunks with random size - InputStream in = tmp.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; - } - int newOffset = offset + read; - assertTrue(newOffset <= data2.length); - System.arraycopy(buffer, bufferOffset, data2, offset, read); - offset = newOffset; - } - assertEquals(data2.length, offset); - in.close(); - assertTrue(Arrays.equals(data, data2)); - } - finally { - tmp.release(); - } - } - - public void testRandomReadWriteInMemory() throws IOException { - doTestRandomReadWrite(10000); - } - - public void testRandomReadWriteWithTemporaryFile() throws IOException { - doTestRandomReadWrite(100000); +public class OverflowBlobTest extends WritableBlobTestBase { + protected WritableBlob createBlob() { + return new OverflowBlob(16, 1024, "test", ".dat"); } - - public void testMarkReset() throws IOException { - byte[] sourceData1 = new byte[2000]; - byte[] sourceData2 = new byte[2000]; - random.nextBytes(sourceData1); - random.nextBytes(sourceData2); - OverflowBlob tmp = new OverflowBlob(16, 512, "test", ".dat"); - OutputStream out = tmp.getOutputStream(); - out.write(sourceData1); - out.write(sourceData2); - out.close(); - DataInputStream in = new DataInputStream(tmp.getInputStream()); - byte[] data1 = new byte[sourceData1.length]; - byte[] data2 = new byte[sourceData2.length]; - in.readFully(data1); - in.mark(sourceData2.length); - in.readFully(data2); - in.reset(); - in.readFully(data2); - assertTrue(Arrays.equals(sourceData1, data1)); - assertTrue(Arrays.equals(sourceData2, data2)); - } - - private void testReadFrom(int size) throws IOException { - byte[] data = new byte[size]; - random.nextBytes(data); - OverflowBlob tmp = new OverflowBlob(16, 1024, "test", ".dat"); - try { - tmp.readFrom(new ByteArrayInputStream(data)); - InputStream in = tmp.getInputStream(); - try { - assertTrue(Arrays.equals(data, IOUtils.toByteArray(in))); - } - finally { - in.close(); - } - } - finally { - tmp.release(); - } - } - - public void testReadFromInMemory() throws IOException { - testReadFrom(10000); - } - - public void testReadFromWithTemporaryFile() throws IOException { - testReadFrom(100000); + + protected void releaseBlob(WritableBlob blob) { + ((OverflowBlob)blob).release(); } } Copied: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/WritableBlobTestBase.java (from r793414, webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/OverflowBlobTest.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?p2=webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/WritableBlobTestBase.java&p1=webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/OverflowBlobTest.java&r1=793414&r2=794410&rev=794410&view=diff ============================================================================== --- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/OverflowBlobTest.java (original) +++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/test/java/org/apache/axiom/util/blob/WritableBlobTestBase.java Wed Jul 15 20:48:47 2009 @@ -1,20 +1,20 @@ /* - * 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 + * 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 + * 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. + * 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.util.blob; @@ -31,15 +31,18 @@ import junit.framework.TestCase; -public class OverflowBlobTest extends TestCase { +public abstract class WritableBlobTestBase extends TestCase { private final static Random random = new Random(); + protected abstract WritableBlob createBlob(); + protected abstract void releaseBlob(WritableBlob blob); + private void doTestRandomReadWrite(int size) throws IOException { byte[] data = new byte[size]; random.nextBytes(data); - OverflowBlob tmp = new OverflowBlob(16, 1024, "test", ".dat"); + WritableBlob blob = createBlob(); try { - OutputStream out = tmp.getOutputStream(); + OutputStream out = blob.getOutputStream(); // Write the test data in chunks with random size int offset = 0; while (offset < data.length) { @@ -48,9 +51,9 @@ offset += c; } out.close(); - assertEquals(size, tmp.getLength()); + assertEquals(size, blob.getLength()); // Reread the test data, again in chunks with random size - InputStream in = tmp.getInputStream(); + InputStream in = blob.getInputStream(); offset = 0; byte[] data2 = new byte[data.length]; byte[] buffer = new byte[2048]; @@ -71,15 +74,15 @@ assertTrue(Arrays.equals(data, data2)); } finally { - tmp.release(); + releaseBlob(blob); } } - public void testRandomReadWriteInMemory() throws IOException { + public void testRandomReadWriteLength10000() throws IOException { doTestRandomReadWrite(10000); } - public void testRandomReadWriteWithTemporaryFile() throws IOException { + public void testRandomReadWriteLength100000() throws IOException { doTestRandomReadWrite(100000); } @@ -88,30 +91,34 @@ byte[] sourceData2 = new byte[2000]; random.nextBytes(sourceData1); random.nextBytes(sourceData2); - OverflowBlob tmp = new OverflowBlob(16, 512, "test", ".dat"); - OutputStream out = tmp.getOutputStream(); - out.write(sourceData1); - out.write(sourceData2); - out.close(); - DataInputStream in = new DataInputStream(tmp.getInputStream()); - byte[] data1 = new byte[sourceData1.length]; - byte[] data2 = new byte[sourceData2.length]; - in.readFully(data1); - in.mark(sourceData2.length); - in.readFully(data2); - in.reset(); - in.readFully(data2); - assertTrue(Arrays.equals(sourceData1, data1)); - assertTrue(Arrays.equals(sourceData2, data2)); + WritableBlob blob = createBlob(); + try { + OutputStream out = blob.getOutputStream(); + out.write(sourceData1); + out.write(sourceData2); + out.close(); + DataInputStream in = new DataInputStream(blob.getInputStream()); + byte[] data1 = new byte[sourceData1.length]; + byte[] data2 = new byte[sourceData2.length]; + in.readFully(data1); + in.mark(sourceData2.length); + in.readFully(data2); + in.reset(); + in.readFully(data2); + assertTrue(Arrays.equals(sourceData1, data1)); + assertTrue(Arrays.equals(sourceData2, data2)); + } finally { + releaseBlob(blob); + } } private void testReadFrom(int size) throws IOException { byte[] data = new byte[size]; random.nextBytes(data); - OverflowBlob tmp = new OverflowBlob(16, 1024, "test", ".dat"); + WritableBlob blob = createBlob(); try { - tmp.readFrom(new ByteArrayInputStream(data)); - InputStream in = tmp.getInputStream(); + blob.readFrom(new ByteArrayInputStream(data)); + InputStream in = blob.getInputStream(); try { assertTrue(Arrays.equals(data, IOUtils.toByteArray(in))); } @@ -120,15 +127,79 @@ } } finally { - tmp.release(); + releaseBlob(blob); } } - public void testReadFromInMemory() throws IOException { + public void testReadFromLength10000() throws IOException { testReadFrom(10000); } - public void testReadFromWithTemporaryFile() throws IOException { + public void testReadFromLength100000() throws IOException { testReadFrom(100000); } + + public void testGetOutputStreamUncommitted() throws Exception { + WritableBlob blob = createBlob(); + try { + OutputStream out = blob.getOutputStream(); + try { + try { + blob.getOutputStream(); + fail("Expected IllegalStateException"); + } catch (IllegalStateException ex) { + // Expected + } + } finally { + out.close(); + } + } finally { + releaseBlob(blob); + } + } + + public void testGetOutputStreamCommitted() throws Exception { + WritableBlob blob = createBlob(); + try { + OutputStream out = blob.getOutputStream(); + out.close(); + try { + blob.getOutputStream(); + fail("Expected IllegalStateException"); + } catch (IllegalStateException ex) { + // Expected + } + } finally { + releaseBlob(blob); + } + } + + public void testGetInputStreamNew() throws Exception { + WritableBlob blob = createBlob(); + try { + blob.getInputStream(); + fail("Expected IllegalStateException"); + } catch (IllegalStateException ex) { + // Expected + } finally { + releaseBlob(blob); + } + } + + public void testGetInputStreamUncommitted() throws Exception { + WritableBlob blob = createBlob(); + try { + OutputStream out = blob.getOutputStream(); + try { + blob.getInputStream(); + fail("Expected IllegalStateException"); + } catch (IllegalStateException ex) { + // Expected + } finally { + out.close(); + } + } finally { + releaseBlob(blob); + } + } }