--- old/src/share/classes/javax/sql/rowset/serial/SerialBlob.java 2012-09-21 10:59:38.122229639 +0800 +++ new/src/share/classes/javax/sql/rowset/serial/SerialBlob.java 2012-09-21 10:59:37.998229637 +0800 @@ -81,6 +81,8 @@ */ private long origLen; + private boolean isFree = false; + /** * Constructs a SerialBlob object that is a serialized version of * the given byte array. @@ -160,8 +162,11 @@ * SerialBlob object, starting at the given * position and containing the given number of consecutive bytes * @throws SerialException if the given starting position is out of bounds + * or called after free() has been called. */ public byte[] getBytes(long pos, int length) throws SerialException { + isFreed(); + if (length > len) { length = (int)len; } @@ -188,9 +193,10 @@ * * @return a long indicating the length in bytes of this * SerialBlob object's array of bytes - * @throws SerialException if an error occurs + * @throws SerialException if an error occurs or called after free() has been called. */ public long length() throws SerialException { + isFreed(); return len; } @@ -202,10 +208,13 @@ * * @return a java.io.InputStream object that contains * this SerialBlob object's array of bytes - * @throws SerialException if an error occurs + * @throws SerialException if an error occurs or called after free() has + * been called. * @see #setBinaryStream */ public java.io.InputStream getBinaryStream() throws SerialException { + isFreed(); + InputStream stream = new ByteArrayInputStream(buf); return stream; } @@ -226,12 +235,15 @@ * position; -1 if the pattern is not found * or the given starting position is out of bounds; position * numbering for the return value starts at 1 - * @throws SerialException if an error occurs when serializing the blob + * @throws SerialException if an error occurs when serializing the blob or + * called after free() has been called. * @throws SQLException if there is an error accessing the BLOB * value from the database */ public long position(byte[] pattern, long start) throws SerialException, SQLException { + isFreed(); + if (start < 1 || start > len) { return -1; } @@ -269,12 +281,14 @@ * at the specified position; -1 if the pattern is * not found or the given starting position is out of bounds; * position numbering for the return value starts at 1 - * @throws SerialException if an error occurs when serializing the blob + * @throws SerialException if an error occurs when serializing the blob or + * called after free() has been called. * @throws SQLException if there is an error accessing the BLOB * value from the database */ public long position(Blob pattern, long start) throws SerialException, SQLException { + isFreed(); return position(pattern.getBytes(1, (int)(pattern.length())), start); } @@ -292,13 +306,14 @@ * @return the number of bytes written * @throws SerialException if there is an error accessing the * BLOB value; or if an invalid position is set; if an - * invalid offset value is set + * invalid offset value is set or called after free() has been called. * @throws SQLException if there is an error accessing the BLOB * value from the database * @see #getBytes */ public int setBytes(long pos, byte[] bytes) throws SerialException, SQLException { + isFreed(); return (setBytes(pos, bytes, 0, bytes.length)); } @@ -327,13 +342,15 @@ * BLOB value; if an invalid position is set; if an * invalid offset value is set; if number of bytes to be written * is greater than the SerialBlob length; or the combined - * values of the length and offset is greater than the Blob buffer + * values of the length and offset is greater than the Blob buffer or + * called after free() has been called. * @throws SQLException if there is an error accessing the BLOB * value from the database. * @see #getBytes */ public int setBytes(long pos, byte[] bytes, int offset, int length) throws SerialException, SQLException { + isFreed(); if (offset < 0 || offset > bytes.length) { throw new SerialException("Invalid offset in byte array set"); @@ -378,10 +395,13 @@ * BLOB value * @throws SerialException if the SerialBlob in not instantiated with a * Blob object that supports setBinaryStream() + * or called after free() has been called. * @see #getBinaryStream */ public java.io.OutputStream setBinaryStream(long pos) throws SerialException, SQLException { + isFreed(); + if (this.blob != null) { return this.blob.setBinaryStream(pos); } else { @@ -399,9 +419,11 @@ * value that this Blob object represents should be * truncated * @throws SerialException if there is an error accessing the Blob value; - * or the length to truncate is greater that the SerialBlob length + * or the length to truncate is greater that the SerialBlob length or + * called after free() has been called. */ public void truncate(long length) throws SerialException { + isFreed(); if (length > len) { throw new SerialException @@ -424,30 +446,64 @@ * The first byte in the Blob is at position 1 * @param length the length in bytes of the partial value to be retrieved * @return InputStream through which the partial Blob value can be read. + * @throws SerialException if called after free() has been called. * @throws SQLException if pos is less than 1 or if pos is greater than the number of bytes * in the Blob or if pos + length is greater than the number of bytes * in the Blob * * @since 1.6 */ - public InputStream getBinaryStream(long pos,long length) throws SQLException { - throw new java.lang.UnsupportedOperationException("Not supported"); + public InputStream getBinaryStream(long pos,long length) throws SerialException, SQLException { + isFreed(); + + if (pos < 1 || pos > len) { + throw new SerialException("Invalid pos in getBinaryStream"); + } + if ((pos - 1) + length > len) { + throw new SerialException( + "pos + length greater than total number of bytes"); + } + return new ByteArrayInputStream(buf, (int) pos - 1, (int) length); } /** - * This method frees the Blob object and releases the resources that it holds. - * Blob object. The object is invalid once the free - * method is called. If free is called multiple times, the subsequent - * calls to free are treated as a no-op. + * This method frees the Blob object and releases the + * resources that it holds. Blob object. The object is + * invalid once the free method is called. After + * free has been called, any attempt to invoke a method + * other than free will result in a + * SerialException being thrown. If free is + * called multiple times, the subsequent calls to free + * are treated as a no-op. * - * @throws SQLException if an error occurs releasing - * the Blob's resources + * @throws SQLException if an error occurs releasing the Blob's resources * @since 1.6 */ public void free() throws SQLException { - throw new java.lang.UnsupportedOperationException("Not supported"); + if (isFree == false) { + len = -1; + origLen = -1; + buf = null; + + if (blob != null) { + blob.free(); + blob = null; + } + + isFree = true; + } } + + private void isFreed() throws SerialException { + if (isFree == true) { + throw new SerialException( + "Unsupported operation. SerialBlob cannot " + + "execute this operation when it" + + "has already been freed by free()"); + } + } + /** * The identifier that assists in the serialization of this SerialBlob * object. --- old/src/share/classes/javax/sql/rowset/serial/SerialClob.java 2012-09-21 10:59:38.754229654 +0800 +++ new/src/share/classes/javax/sql/rowset/serial/SerialClob.java 2012-09-21 10:59:38.610229651 +0800 @@ -60,7 +60,7 @@ * Internal Clob representation if SerialClob is initialized with a * Clob. Null if SerialClob is initialized with a char[]. */ - private final Clob clob; + private Clob clob; /** * The length in characters of this SerialClob object's @@ -76,7 +76,9 @@ * * @serial */ - private final long origLen; + private long origLen; + + private boolean isFree =false; /** * Constructs a SerialClob object that is a serialized version of @@ -179,9 +181,11 @@ * * @return a long indicating the length in characters of this * SerialClob object's array of character - * @throws SerialException if an error occurs + * @throws SerialException if an error occurs or + * called after free() has been called. */ public long length() throws SerialException { + isFreed(); return len; } @@ -193,9 +197,11 @@ * * @return a java.io.Reader object containing this * SerialClob object's data - * @throws SerialException if an error occurs + * @throws SerialException if an error occurs or + * called after free() has been called. */ public java.io.Reader getCharacterStream() throws SerialException { + isFreed(); return (java.io.Reader) new CharArrayReader(buf); } @@ -210,12 +216,15 @@ * @return a java.io.InputStream object containing * this SerialClob object's data * @throws SerialException if this SerialClob object was not instantiated - * with a Clob object - * @throws SQLException if there is an error accessing the + * with a Clob object or called after free() has been + * called. + * @throws SQLException + * if there is an error accessing the * CLOB value represented by the Clob object that was * used to create this SerialClob object */ public java.io.InputStream getAsciiStream() throws SerialException, SQLException { + isFreed(); if (this.clob != null) { return this.clob.getAsciiStream(); } else { @@ -247,9 +256,11 @@ * this SerialClob object beginning at the * given position and containing the specified number of * consecutive characters - * @throws SerialException if either of the arguments is out of bounds + * @throws SerialException if either of the arguments is out of bounds or called + * after free() has been called. */ public String getSubString(long pos, int length) throws SerialException { + isFreed(); if (pos < 1 || pos > this.length()) { throw new SerialException("Invalid position in BLOB object set"); @@ -287,11 +298,13 @@ * not found or the starting position is out of bounds; position * numbering for the return value starts at 1 * @throws SerialException if an error occurs locating the String signature + * or called after free() has been called. * @throws SQLException if there is an error accessing the Blob value * from the database. */ public long position(String searchStr, long start) throws SerialException, SQLException { + isFreed(); if (start < 1 || start > len) { return -1; @@ -332,11 +345,13 @@ * object begins in this SerialClob object, * at or after the specified starting position * @throws SerialException if an error occurs locating the Clob signature + * or called after free() has been called. * @throws SQLException if there is an error accessing the Blob value * from the database */ public long position(Clob searchStr, long start) throws SerialException, SQLException { + isFreed(); return position(searchStr.getSubString(1,(int)searchStr.length()), start); } @@ -357,9 +372,12 @@ * CLOB value; if an invalid position is set; if an * invalid offset value is set; if number of bytes to be written * is greater than the SerialClob length; or the combined - * values of the length and offset is greater than the Clob buffer + * values of the length and offset is greater than the Clob buffer or + * called after free() has been called. */ public int setString(long pos, String str) throws SerialException { + isFreed(); + return (setString(pos, str, 0, str.length())); } @@ -382,10 +400,13 @@ * CLOB value; if an invalid position is set; if an * invalid offset value is set; if number of bytes to be written * is greater than the SerialClob length; or the combined - * values of the length and offset is greater than the Clob buffer + * values of the length and offset is greater than the Clob buffer or + * called after free() has been called. */ public int setString(long pos, String str, int offset, int length) throws SerialException { + isFreed(); + String temp = str.substring(offset); char cPattern[] = temp.toCharArray(); @@ -429,13 +450,16 @@ * CLOB object * @return the stream to which ASCII encoded characters can be written * @throws SerialException if SerialClob is not instantiated with a - * Clob object that supports setAsciiStream + * Clob object that supports setAsciiStream or + * called after free() has been called. * @throws SQLException if there is an error accessing the * CLOB value * @see #getAsciiStream */ public java.io.OutputStream setAsciiStream(long pos) throws SerialException, SQLException { + isFreed(); + if (this.clob != null) { return this.clob.setAsciiStream(pos); } else { @@ -459,13 +483,16 @@ * * @return a stream to which Unicode encoded characters can be written * @throws SerialException if the SerialClob is not instantiated with - * a Clob object that supports setCharacterStream + * a Clob object that supports setCharacterStream or + * called after free() has been called. * @throws SQLException if there is an error accessing the * CLOB value * @see #getCharacterStream */ public java.io.Writer setCharacterStream(long pos) throws SerialException, SQLException { + isFreed(); + if (this.clob != null) { return this.clob.setCharacterStream(pos); } else { @@ -487,31 +514,97 @@ * value should be truncated * @throws SQLException if there is an error accessing the * CLOB value + * @throws SerialException if called after free() has been called. */ public void truncate(long length) throws SerialException { - if (length > len) { - throw new SerialException - ("Length more than what can be truncated"); - } else { - len = length; - // re-size the buffer + isFreed(); - if (len == 0) { - buf = new char[] {}; - } else { - buf = (this.getSubString(1, (int)len)).toCharArray(); - } + if (length > len) { + throw new SerialException("Length more than what can be truncated"); + } else { + len = length; + // re-size the buffer - } - } + if (len == 0) { + buf = new char[] {}; + } else { + buf = (this.getSubString(1, (int) len)).toCharArray(); + } + } + } + /** + * Returns a Reader object that contains a partial + * Clob value, starting with the character specified by + * pos, which is length characters in length. + * + * @param pos + * the offset to the first character of the partial value + * to be retrieved. The first character in the + * Clob is at position 1. + * @param length + * the length in characters of the partial value to be + * retrieved. + * + * @return Reader through which the partial Clob value + * can be read. + * @throws SQLException + * if pos is less than 1 or if pos is greater than the + * number of characters in the Clob or if + * pos + length is greater than the number of characters + * in the Clob + * @throws SQLFeatureNotSupportedException + * if the JDBC driver does not support this method + * @throws SerialException if called after free() has been called. + */ public Reader getCharacterStream(long pos, long length) throws SQLException { - throw new java.lang.UnsupportedOperationException("Not supported"); + isFreed(); + + if (pos < 1 || pos > len) { + throw new SerialException("Invalid pos in getCharacterStream"); + } + if ((pos - 1) + length > len) { + throw new SerialException("pos + length greater than total number of bytes"); + } + return (java.io.Reader) new CharArrayReader(buf, (int) pos -1, (int)length); } + /** + * This method frees the Clob object and releases the + * resources the resources that it holds. The object is invalid once + * the free method is called. After free + * has been called, any attempt to invoke a method other than + * free will result in a SQLException being + * thrown. If free is called multiple times, the + * subsequent calls to free are treated as a no-op. + * + * @throws SQLException if an error occurs releasing the Clob's + * resources + * @throws SQLFeatureNotSupportedException if the JDBC driver does + * not support this method + */ public void free() throws SQLException { - throw new java.lang.UnsupportedOperationException("Not supported"); + if (isFree == false) { + len = -1; + origLen = -1; + buf = null; + + if (clob != null) { + clob.free(); + clob = null; + } + + isFree = true; + } + } + + private void isFreed() throws SerialException { + if (isFree == true) { + throw new SerialException( + "Unsupported operation. SerialClob cannot " + + "execute this operation when it has already been freed by free()"); + } } /** --- /dev/null 2012-09-21 10:40:39.978073220 +0800 +++ new/test/javax/sql/rowset/serial/SerialBlob/SerialBlobFree.java 2012-09-21 10:59:39.082229662 +0800 @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * Portions Copyright (c) 2012 IBM Corporation + */ + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +import javax.sql.rowset.serial.SerialBlob; +import javax.sql.rowset.serial.SerialException; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.sql.Blob; +import java.sql.SQLException; + +/** + * @test + * @bug + * @summary tests for free() on SerialBlob + */ + +public class SerialBlobFree { + static byte[] byteArray = new byte[] { 1, 2, 3, 4, 5 }; + + static Map errorMsgs = new HashMap(); + + private static SerialBlob prepareSerialBlob() throws Exception { + return new SerialBlob(byteArray); + } + + public static int testGetBinaryStreamAfterFree() throws Exception { + SerialBlob sb = prepareSerialBlob(); + sb.free(); + + // should throw SerialException after free() has been called. + try { + sb.getBinaryStream(); + errorMsgs.put("testGetBinaryStreamAfterFree()", + "operation on a freed SerialBlob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testGetBytesAfterFree() throws Exception { + SerialBlob sb = prepareSerialBlob(); + sb.free(); + + // should throw SerialException after free() has been called. + try { + sb.getBytes(1, 3); + errorMsgs.put("testGetBytesAfterFree()", + "operation on a freed SerialBlob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testLengthAfterFree() throws Exception { + SerialBlob sb = prepareSerialBlob(); + sb.free(); + + // should throw SerialException after free() has been called. + try { + sb.length(); + errorMsgs.put("testLengthAfterFree()", + "operation on a freed SerialBlob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testPositionBAJAfterFree() throws Exception { + SerialBlob sb = prepareSerialBlob(); + sb.free(); + + // should throw SerialException after free() has been called. + try { + sb.position(new byte[] { 2, 3 }, 1); + errorMsgs.put("testPositionBAJAfterFree()", + "operation on a freed SerialBlob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testPositionBlobJAfterFree() throws Exception { + SerialBlob sb = prepareSerialBlob(); + sb.free(); + + // should throw SerialException after free() has been called. + try { + MockBlob mBlob = new MockBlob(); + sb.position(mBlob, 1); + errorMsgs.put("testPositionBlobJAfterFree()", + "operation on a freed SerialBlob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testSetBytesJBAAfterFree() throws Exception { + SerialBlob sb = prepareSerialBlob(); + sb.free(); + + // should throw SerialException after free() has been called. + try { + sb.setBytes(1, new byte[] { 2, 3 }); + errorMsgs.put("testSetBytesJBAAfterFree()", + "operation on a freed SerialBlob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testSetBytesJBAIIAfterFree() throws Exception { + SerialBlob sb = prepareSerialBlob(); + sb.free(); + + // should throw SerialException after free() has been called. + try { + sb.setBytes(1, new byte[] { 2, 3 }, 0, 2); + errorMsgs.put("testSetBytesJBAIIAfterFree()", + "operation on a freed SerialBlob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testSetBinaryStreamJAfterFree() throws Exception { + SerialBlob sb = prepareSerialBlob(); + sb.free(); + + // should throw SerialException after free() has been called. + try { + sb.setBinaryStream(1); + errorMsgs.put("testSetBinaryStreamJAfterFree()", + "operation on a freed SerialBlob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testTruncateAfterFree() throws Exception { + SerialBlob sb = prepareSerialBlob(); + sb.free(); + + // should throw SerialException after free() has been called. + try { + sb.truncate(3); + errorMsgs.put("testTruncateAfterFree()", + "operation on a freed SerialBlob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testGetBinaryStreamJJAfterFree() throws Exception { + SerialBlob sb = prepareSerialBlob(); + sb.free(); + + // should throw SerialException after free() has been called. + try { + sb.getBinaryStream(1, 3); + errorMsgs.put("testGetBinaryStreamJJAfterFree()", + "operation on a freed SerialBlob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testMultipleFree() throws Exception { + SerialBlob sb = prepareSerialBlob(); + try { + sb.free(); + + // multiple calls are treated as no-op + sb.free(); + } catch (Exception e) { + errorMsgs.put("testMultipleFree()", + "multiple calls should be treated as no-op"); + return 1; + } + + System.out.println("Test Passed"); + return 0; + + } + + public static void main(String[] args) throws Exception { + int totalNumber = 0; + int failedNumber = 0; + + failedNumber += testGetBinaryStreamAfterFree(); + totalNumber++; + + failedNumber += testGetBytesAfterFree(); + totalNumber++; + + failedNumber += testLengthAfterFree(); + totalNumber++; + + failedNumber += testPositionBAJAfterFree(); + totalNumber++; + + failedNumber += testPositionBlobJAfterFree(); + totalNumber++; + + failedNumber += testSetBytesJBAAfterFree(); + totalNumber++; + + failedNumber += testSetBytesJBAIIAfterFree(); + totalNumber++; + + failedNumber += testSetBinaryStreamJAfterFree(); + totalNumber++; + + failedNumber += testTruncateAfterFree(); + totalNumber++; + + failedNumber += testGetBinaryStreamJJAfterFree(); + totalNumber++; + + failedNumber += testMultipleFree(); + totalNumber++; + + System.out.println(); + System.out.println("Total tests " + totalNumber); + System.out.println("Passed: " + (totalNumber - failedNumber)); + System.out.println("Failed: " + failedNumber); + System.out.println(); + + if (failedNumber != 0) { + System.out.println("Failed details:"); + + Iterator> itr = errorMsgs.entrySet() + .iterator(); + + while (itr.hasNext()) { + Entry entry = itr.next(); + String testName = entry.getKey(); + String message = entry.getValue(); + + System.out.println(testName + ": " + message); + } + + throw new Exception("SerialBlob.free() test failed"); + } + } + + static class MockBlob implements Blob { + byte buff[] = { 3, 4, 5 }; + + @Override + public long length() throws SQLException { + return buff.length; + } + + @Override + public byte[] getBytes(long pos, int length) throws SQLException { + return buff; + } + + @Override + public InputStream getBinaryStream() throws SQLException { + return new ByteArrayInputStream(buff); + } + + @Override + public long position(byte[] pattern, long start) throws SQLException { + return 0; + } + + @Override + public long position(Blob pattern, long start) throws SQLException { + return 0; + } + + @Override + public int setBytes(long pos, byte[] bytes) throws SQLException { + return 0; + } + + @Override + public int setBytes(long pos, byte[] bytes, int offset, int len) + throws SQLException { + return 0; + } + + @Override + public OutputStream setBinaryStream(long pos) throws SQLException { + return null; + } + + @Override + public void truncate(long len) throws SQLException { + } + + @Override + public void free() throws SQLException { + } + + @Override + public InputStream getBinaryStream(long pos, long length) + throws SQLException { + return null; + } + + } + +} \ No newline at end of file --- /dev/null 2012-09-21 10:40:39.978073220 +0800 +++ new/test/javax/sql/rowset/serial/SerialBlob/SerialBlobGetBinaryStreamJJ.java 2012-09-21 10:59:39.430229670 +0800 @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * Portions Copyright (c) 2012 IBM Corporation + */ + +import java.io.InputStream; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +import javax.sql.rowset.serial.SerialBlob; +import javax.sql.rowset.serial.SerialException; + +/** + * @test + * @bug + * @summary tests for getBinaryStream(long, long) on SerialBlob + */ + +public class SerialBlobGetBinaryStreamJJ { + static byte[] byteArray = new byte[] { 1, 2, 3, 4, 5 }; + + static Map errorMsgs = new HashMap(); + + private static SerialBlob prepareSerialBlob() throws Exception { + return new SerialBlob(byteArray); + } + + // Test the normal behavior when use getBinaryStream(long, long) + public static int testGetBinaryStream() throws Exception { + SerialBlob sb = prepareSerialBlob(); + InputStream is = sb.getBinaryStream(1, 3); + + byte[] expected = new byte[] { 1, 2, 3 }; + for (int i = 0; i < 3; i++) { + if (expected[i] != is.read()) { + errorMsgs.put("testGetBinaryStream()", "Unexpected byte"); + return 1; + } + } + + if (is.read() != -1) { + errorMsgs.put("testGetBinaryStream()", "More left in SerialBlob"); + return 1; + } + System.out.println("Test Passed"); + return 0; + } + + // Test getBinaryStream with pos is less than 0 + public static int testGetBinaryStreamPosLT0() throws Exception { + SerialBlob sb = prepareSerialBlob(); + + try { + sb.getBinaryStream(-1, 3); + errorMsgs.put("testGetBinaryStreamPosLT0()", + "Should throw exception when pos < 0"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + // Test getBinaryStream with pos is 0 + public static int testGetBinaryStreamPosEquals0() throws Exception { + SerialBlob sb = prepareSerialBlob(); + + try { + sb.getBinaryStream(0, 3); + errorMsgs.put("testGetBinaryStreamPosEquals0()", + "Should throw exception when pos == 0"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + // Test getBinaryStream with length is larger than the back end buffer + // length of the SerialBlob object + public static int testGetBinaryStreamLengthOutOfBounds() throws Exception { + SerialBlob sb = prepareSerialBlob(); + + try { + sb.getBinaryStream(1, byteArray.length + 1); + errorMsgs.put("testGetBinaryStreamLengthOutOfBounds()", + "Should throw exception when pos + length >" + + "actual length + 1"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + // Test getBinaryStream with pos is larger than the back end buffer length + // of the SerialBlob object + public static int testGetBinaryStreamPosGTLength() throws Exception { + SerialBlob sb = prepareSerialBlob(); + + try { + sb.getBinaryStream(byteArray.length + 1, 2); + errorMsgs.put("testGetBinaryStreamPosGTLength()", + "Should throw exception when pos > Blob's length"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static void main(String[] args) throws Exception { + int totalNumber = 0; + int failedNumber = 0; + + failedNumber += testGetBinaryStream(); + totalNumber++; + + failedNumber += testGetBinaryStreamPosLT0(); + totalNumber++; + + failedNumber += testGetBinaryStreamPosEquals0(); + totalNumber++; + + failedNumber += testGetBinaryStreamLengthOutOfBounds(); + totalNumber++; + + failedNumber += testGetBinaryStreamPosGTLength(); + totalNumber++; + + System.out.println(); + System.out.println("Total tests " + totalNumber); + System.out.println("Passed: " + (totalNumber - failedNumber)); + System.out.println("Failed: " + failedNumber); + System.out.println(); + + if (failedNumber != 0) { + System.out.println("Failed details:"); + + Iterator> itr = errorMsgs.entrySet() + .iterator(); + + while (itr.hasNext()) { + Entry entry = itr.next(); + String testName = entry.getKey(); + String message = entry.getValue(); + + System.out.println(testName + ": " + message); + } + + throw new Exception( + "SerialBlob.getBinaryStream(long, long) test failed"); + } + } +} \ No newline at end of file --- /dev/null 2012-09-21 10:40:39.978073220 +0800 +++ new/test/javax/sql/rowset/serial/SerialClob/SerialClobFree.java 2012-09-21 10:59:39.794229679 +0800 @@ -0,0 +1,418 @@ +/* + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * Portions Copyright (c) 2012 IBM Corporation + */ + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.sql.Clob; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +import javax.sql.rowset.serial.SerialClob; +import javax.sql.rowset.serial.SerialException; + +/** + * @test + * @bug + * @summary tests for free() on SerialBlob + */ + +public class SerialClobFree { + static char[] charArray = "char array test".toCharArray(); + + static Map errorMsgs = new HashMap(); + + private static SerialClob prepareSerialClob() throws Exception { + return new SerialClob(charArray); + } + + public static int testGetCharacterStreamAfterFree() throws Exception { + SerialClob sc = prepareSerialClob(); + sc.free(); + + // should throw SerialException after free() has been called. + try { + sc.getCharacterStream(); + errorMsgs.put("testGetCharacterStreamAfterFree()", + "operation on a freed SerialClob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testGetAsciiStreamAfterFree() throws Exception { + SerialClob sc = prepareSerialClob(); + sc.free(); + + // should throw SerialException after free() has been called. + try { + sc.getAsciiStream(); + errorMsgs.put("testGetAsciiStreamAfterFree()", + "operation on a freed SerialClob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testGetSubStringJIAfterFree() throws Exception { + SerialClob sc = prepareSerialClob(); + sc.free(); + + // should throw SerialException after free() has been called. + try { + sc.getSubString(1, 3); + errorMsgs.put("testGetSubStringJIAfterFree()", + "operation on a freed SerialClob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testLengthAfterFree() throws Exception { + SerialClob sc = prepareSerialClob(); + sc.free(); + + // should throw SerialException after free() has been called. + try { + sc.length(); + errorMsgs.put("testLengthAfterFree()", + "operation on a freed SerialClob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testPositionStringJAfterFree() throws Exception { + SerialClob sc = prepareSerialClob(); + sc.free(); + + // should throw SerialException after free() has been called. + try { + sc.position("cha", 1); + errorMsgs.put("testPositionStringJAfterFree()", + "operation on a freed SerialClob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testPositionClobJAfterFree() throws Exception { + SerialClob sc = prepareSerialClob(); + sc.free(); + + // should throw SerialException after free() has been called. + try { + MockClob mClob = new MockClob(); + sc.position(mClob, 1); + errorMsgs.put("testPositionClobJAfterFree()", + "operation on a freed SerialClob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testSetStringJStringAfterFree() throws Exception { + SerialClob sc = prepareSerialClob(); + sc.free(); + + // should throw SerialException after free() has been called. + try { + sc.setString(1, "cha"); + errorMsgs.put("testSetStringJStringAfterFree()", + "operation on a freed SerialClob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testSetStringJStringIIAfterFree() throws Exception { + SerialClob sc = prepareSerialClob(); + sc.free(); + + // should throw SerialException after free() has been called. + try { + sc.setString(1, "char", 0, 3); + errorMsgs.put("testSetStringJStringIIAfterFree()", + "operation on a freed SerialClob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testSetAsciiStreamJAfterFree() throws Exception { + SerialClob sc = prepareSerialClob(); + sc.free(); + + // should throw SerialException after free() has been called. + try { + sc.setAsciiStream(1); + errorMsgs.put("testSetAsciiStreamJAfterFree()", + "operation on a freed SerialClob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testSetCharacterStreamJAfterFree() throws Exception { + SerialClob sc = prepareSerialClob(); + sc.free(); + + // should throw SerialException after free() has been called. + try { + sc.setCharacterStream(1); + errorMsgs.put("testSetCharacterStreamJAfterFree()", + "operation on a freed SerialClob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testTruncateAfterFree() throws Exception { + SerialClob sc = prepareSerialClob(); + sc.free(); + + // should throw SerialException after free() has been called. + try { + sc.truncate(3); + errorMsgs.put("testTruncateAfterFree()", + "operation on a freed SerialClob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testGetCharacterStreamJJAfterFree() throws Exception { + SerialClob sc = prepareSerialClob(); + sc.free(); + + // should throw SerialException after free() has been called. + try { + sc.getCharacterStream(1, 3); + errorMsgs.put("testGetCharacterStreamJJAfterFree()", + "operation on a freed SerialClob should throw exception"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testMultipleFree() throws Exception { + SerialClob sc = prepareSerialClob(); + try { + sc.free(); + + // multiple calls are treated as no-op + sc.free(); + } catch (Exception e) { + errorMsgs.put("testMultipleFree()", + "multiple calls should be treated as no-op"); + return 1; + } + + System.out.println("Test Passed"); + return 0; + + } + + public static void main(String[] args) throws Exception { + int totalNumber = 0; + int failedNumber = 0; + + failedNumber += testGetCharacterStreamAfterFree(); + totalNumber++; + + failedNumber += testGetAsciiStreamAfterFree(); + totalNumber++; + + failedNumber += testGetSubStringJIAfterFree(); + totalNumber++; + + failedNumber += testLengthAfterFree(); + totalNumber++; + + failedNumber += testPositionStringJAfterFree(); + totalNumber++; + + failedNumber += testPositionClobJAfterFree(); + totalNumber++; + + failedNumber += testSetStringJStringAfterFree(); + totalNumber++; + + failedNumber += testSetStringJStringIIAfterFree(); + totalNumber++; + + failedNumber += testSetAsciiStreamJAfterFree(); + totalNumber++; + + failedNumber += testSetCharacterStreamJAfterFree(); + totalNumber++; + + failedNumber += testTruncateAfterFree(); + totalNumber++; + + failedNumber += testGetCharacterStreamJJAfterFree(); + totalNumber++; + + failedNumber += testMultipleFree(); + totalNumber++; + + System.out.println(); + System.out.println("Total tests " + totalNumber); + System.out.println("Passed: " + (totalNumber - failedNumber)); + System.out.println("Failed: " + failedNumber); + System.out.println(); + + if (failedNumber != 0) { + System.out.println("Failed details:"); + + Iterator> itr = errorMsgs.entrySet() + .iterator(); + + while (itr.hasNext()) { + Entry entry = itr.next(); + String testName = entry.getKey(); + String message = entry.getValue(); + + System.out.println(testName + ": " + message); + } + + throw new Exception("SerialClob.free() test failed"); + } + } + + static class MockClob implements Clob { + + @Override + public long length() throws SQLException { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getSubString(long pos, int length) throws SQLException { + // TODO Auto-generated method stub + return null; + } + + @Override + public Reader getCharacterStream() throws SQLException { + // TODO Auto-generated method stub + return null; + } + + @Override + public InputStream getAsciiStream() throws SQLException { + // TODO Auto-generated method stub + return null; + } + + @Override + public long position(String searchstr, long start) throws SQLException { + // TODO Auto-generated method stub + return 0; + } + + @Override + public long position(Clob searchstr, long start) throws SQLException { + // TODO Auto-generated method stub + return 0; + } + + @Override + public int setString(long pos, String str) throws SQLException { + // TODO Auto-generated method stub + return 0; + } + + @Override + public int setString(long pos, String str, int offset, int len) + throws SQLException { + // TODO Auto-generated method stub + return 0; + } + + @Override + public OutputStream setAsciiStream(long pos) throws SQLException { + // TODO Auto-generated method stub + return null; + } + + @Override + public Writer setCharacterStream(long pos) throws SQLException { + // TODO Auto-generated method stub + return null; + } + + @Override + public void truncate(long len) throws SQLException { + // TODO Auto-generated method stub + + } + + @Override + public void free() throws SQLException { + // TODO Auto-generated method stub + + } + + @Override + public Reader getCharacterStream(long pos, long length) + throws SQLException { + // TODO Auto-generated method stub + return null; + } + + } +} \ No newline at end of file --- /dev/null 2012-09-21 10:40:39.978073220 +0800 +++ new/test/javax/sql/rowset/serial/SerialClob/SerialClobGetCharacterStreamJJ.java 2012-09-21 10:59:40.162229687 +0800 @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * Portions Copyright (c) 2012 IBM Corporation + */ + +import java.io.Reader; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +import javax.sql.rowset.serial.SerialClob; +import javax.sql.rowset.serial.SerialException; + +/** + * @test + * @bug + * @summary tests for getBinaryStream(long, long) on SerialBlob + */ + +public class SerialClobGetCharacterStreamJJ { + static char[] charArray = "char array test".toCharArray(); + + static Map errorMsgs = new HashMap(); + + private static SerialClob prepareSerialClob() throws Exception { + return new SerialClob(charArray); + } + + // Test the normal behavior of getCharacterStream(long, long) + public static int testGetCharacterStream() throws Exception { + SerialClob sc = prepareSerialClob(); + Reader is = sc.getCharacterStream(1, 3); + + char[] expected = "cha".toCharArray(); + for (int i = 0; i < 3; i++) { + if (expected[i] != is.read()) { + errorMsgs.put("testGetCharacterStream()", "Unexpected byte"); + return 1; + } + } + + if (is.read() != -1) { + errorMsgs + .put("testGetCharacterStream()", "More left in SerialClob"); + return 1; + } + System.out.println("Test Passed"); + return 0; + } + + // Test getCharacterStream with pos is less than 0 + public static int testGetCharacterStreamPosLT0() throws Exception { + SerialClob sc = prepareSerialClob(); + + try { + sc.getCharacterStream(-1, 3); + errorMsgs.put("testGetCharacterStreamPosLT0()", + "Should throw exception when pos < 0"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + // Test getCharacterStream with pos is 0 + public static int testGetCharacterStreamPosEquals0() throws Exception { + SerialClob sc = prepareSerialClob(); + + try { + sc.getCharacterStream(0, 3); + errorMsgs.put("testGetCharacterStreamPosEquals0()", + "Should throw exception when pos == 0"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + // Test getCharacterStream with length is larger than the back end buffer + // length of the SerialClob object + public static int testGetCharacterStreamLengthOutOfBounds() + throws Exception { + SerialClob sc = prepareSerialClob(); + + try { + sc.getCharacterStream(1, charArray.length + 1); + errorMsgs + .put("testGetCharacterStreamLengthOutOfBounds()", + "Should throw exception when pos + length > actual length + 1"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static int testGetCharacterStreamPosGTLength() throws Exception { + SerialClob sc = prepareSerialClob(); + + try { + sc.getCharacterStream(charArray.length + 1, 2); + errorMsgs.put("testGetBinaryStreamPosGTLength()", + "Should throw exception when pos > Blob's length"); + return 1; + } catch (SerialException se) { + System.out.println("Test Passed"); + return 0; + } + } + + public static void main(String[] args) throws Exception { + int totalNumber = 0; + int failedNumber = 0; + + failedNumber += testGetCharacterStream(); + totalNumber++; + + failedNumber += testGetCharacterStreamPosLT0(); + totalNumber++; + + failedNumber += testGetCharacterStreamPosEquals0(); + totalNumber++; + + failedNumber += testGetCharacterStreamLengthOutOfBounds(); + totalNumber++; + + failedNumber += testGetCharacterStreamPosGTLength(); + totalNumber++; + + System.out.println(); + System.out.println("Total tests " + totalNumber); + System.out.println("Passed: " + (totalNumber - failedNumber)); + System.out.println("Failed: " + failedNumber); + System.out.println(); + + if (failedNumber != 0) { + System.out.println("Failed details:"); + + Iterator> itr = errorMsgs.entrySet() + .iterator(); + + while (itr.hasNext()) { + Entry entry = itr.next(); + String testName = entry.getKey(); + String message = entry.getValue(); + + System.out.println(testName + ": " + message); + } + + throw new Exception( + "SerialClob.getCharacterStream(long, long) test failed"); + } + } +} \ No newline at end of file