You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ta...@apache.org on 2011/09/19 14:46:38 UTC

svn commit: r1172600 - in /activemq/trunk/kahadb/src: main/java/org/apache/kahadb/util/ test/java/org/apache/kahadb/page/ test/java/org/apache/kahadb/util/

Author: tabish
Date: Mon Sep 19 12:46:38 2011
New Revision: 1172600

URL: http://svn.apache.org/viewvc?rev=1172600&view=rev
Log:
Some updates and changes to support some work on https://issues.apache.org/jira/browse/AMQ-3467

Cleanup some code in the DataByteArrayOutputStream and fix an issue in the readUTF 
code that code result in a UTFDataFormatException to be thrown for no reason.

Adds some tests for those classes as well.

Added:
    activemq/trunk/kahadb/src/test/java/org/apache/kahadb/util/DataByteArrayInputStreamTest.java   (with props)
    activemq/trunk/kahadb/src/test/java/org/apache/kahadb/util/DataByteArrayOutputStreamTest.java   (with props)
Modified:
    activemq/trunk/kahadb/src/main/java/org/apache/kahadb/util/DataByteArrayInputStream.java
    activemq/trunk/kahadb/src/main/java/org/apache/kahadb/util/DataByteArrayOutputStream.java
    activemq/trunk/kahadb/src/test/java/org/apache/kahadb/page/PageFileTest.java

Modified: activemq/trunk/kahadb/src/main/java/org/apache/kahadb/util/DataByteArrayInputStream.java
URL: http://svn.apache.org/viewvc/activemq/trunk/kahadb/src/main/java/org/apache/kahadb/util/DataByteArrayInputStream.java?rev=1172600&r1=1172599&r2=1172600&view=diff
==============================================================================
--- activemq/trunk/kahadb/src/main/java/org/apache/kahadb/util/DataByteArrayInputStream.java (original)
+++ activemq/trunk/kahadb/src/main/java/org/apache/kahadb/util/DataByteArrayInputStream.java Mon Sep 19 12:46:38 2011
@@ -23,8 +23,8 @@ import java.io.UTFDataFormatException;
 
 /**
  * Optimized ByteArrayInputStream that can be used more than once
- * 
- * 
+ *
+ *
  */
 public final class DataByteArrayInputStream extends InputStream implements DataInput {
     private byte[] buf;
@@ -32,9 +32,11 @@ public final class DataByteArrayInputStr
     private int offset;
     private int length;
 
+    private byte[] work;
+
     /**
      * Creates a <code>StoreByteArrayInputStream</code>.
-     * 
+     *
      * @param buf the input buffer.
      */
     public DataByteArrayInputStream(byte buf[]) {
@@ -42,11 +44,12 @@ public final class DataByteArrayInputStr
         this.pos = 0;
         this.offset = 0;
         this.length = buf.length;
+        this.work = new byte[8];
     }
 
     /**
      * Creates a <code>StoreByteArrayInputStream</code>.
-     * 
+     *
      * @param sequence the input buffer.
      */
     public DataByteArrayInputStream(ByteSequence sequence) {
@@ -54,6 +57,7 @@ public final class DataByteArrayInputStr
         this.offset = sequence.getOffset();
         this.pos =  this.offset;
         this.length = sequence.length;
+        this.work = new byte[8];
     }
 
     /**
@@ -81,7 +85,7 @@ public final class DataByteArrayInputStr
     /**
      * reset the <code>StoreByteArrayInputStream</code> to use an new byte
      * array
-     * 
+     *
      * @param newBuff
      */
     public void restart(byte[] newBuff) {
@@ -98,7 +102,7 @@ public final class DataByteArrayInputStr
     /**
      * reset the <code>StoreByteArrayInputStream</code> to use an new
      * ByteSequence
-     * 
+     *
      * @param sequence
      */
     public void restart(ByteSequence sequence) {
@@ -109,7 +113,7 @@ public final class DataByteArrayInputStr
 
     /**
      * re-start the input stream - reusing the current buffer
-     * 
+     *
      * @param size
      */
     public void restart(int size) {
@@ -127,7 +131,7 @@ public final class DataByteArrayInputStr
      * stream has been reached, the value <code>-1</code> is returned.
      * <p>
      * This <code>read</code> method cannot block.
-     * 
+     *
      * @return the next byte of data, or <code>-1</code> if the end of the
      *         stream has been reached.
      */
@@ -138,7 +142,7 @@ public final class DataByteArrayInputStr
     /**
      * Reads up to <code>len</code> bytes of data into an array of bytes from
      * this input stream.
-     * 
+     *
      * @param b the buffer into which the data is read.
      * @param off the start offset of the data.
      * @param len the maximum number of bytes read.
@@ -204,34 +208,35 @@ public final class DataByteArrayInputStr
     }
 
     public short readShort() {
-        int ch1 = read();
-        int ch2 = read();
-        return (short)((ch1 << 8) + (ch2 << 0));
+        this.read(work, 0, 2);
+        return (short) (((work[0] & 0xff) << 8) | (work[1] & 0xff));
     }
 
     public int readUnsignedShort() {
-        int ch1 = read();
-        int ch2 = read();
-        return (ch1 << 8) + (ch2 << 0);
+        this.read(work, 0, 2);
+        return (int) (((work[0] & 0xff) << 8) | (work[1] & 0xff));
     }
 
     public char readChar() {
-        int ch1 = read();
-        int ch2 = read();
-        return (char)((ch1 << 8) + (ch2 << 0));
+        this.read(work, 0, 2);
+        return (char) (((work[0] & 0xff) << 8) | (work[1] & 0xff));
     }
 
     public int readInt() {
-        int ch1 = read();
-        int ch2 = read();
-        int ch3 = read();
-        int ch4 = read();
-        return (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0);
+        this.read(work, 0, 4);
+        return ((work[0] & 0xff) << 24) | ((work[1] & 0xff) << 16) |
+               ((work[2] & 0xff) << 8) | (work[3] & 0xff);
     }
 
     public long readLong() {
-        long rc = ((long)buf[pos++] << 56) + ((long)(buf[pos++] & 255) << 48) + ((long)(buf[pos++] & 255) << 40) + ((long)(buf[pos++] & 255) << 32);
-        return rc + ((long)(buf[pos++] & 255) << 24) + ((buf[pos++] & 255) << 16) + ((buf[pos++] & 255) << 8) + ((buf[pos++] & 255) << 0);
+        this.read(work, 0, 8);
+
+        int i1 = ((work[0] & 0xff) << 24) | ((work[1] & 0xff) << 16) |
+            ((work[2] & 0xff) << 8) | (work[3] & 0xff);
+        int i2 = ((work[4] & 0xff) << 24) | ((work[5] & 0xff) << 16) |
+            ((work[6] & 0xff) << 8) | (work[7] & 0xff);
+
+        return ((i1 & 0xffffffffL) << 32) | (i2 & 0xffffffffL);
     }
 
     public float readFloat() throws IOException {
@@ -262,59 +267,32 @@ public final class DataByteArrayInputStr
 
     public String readUTF() throws IOException {
         int length = readUnsignedShort();
+        int endPos = pos + length;
+        int count = 0, a;
         char[] characters = new char[length];
-        int c;
-        int c2;
-        int c3;
-        int count = 0;
-        int total = pos + length;
-        while (pos < total) {
-            c = (int)buf[pos] & 0xff;
-            if (c > 127) {
-                break;
-            }
-            pos++;
-            characters[count++] = (char)c;
-        }
-        while (pos < total) {
-            c = (int)buf[pos] & 0xff;
-            switch (c >> 4) {
-            case 0:
-            case 1:
-            case 2:
-            case 3:
-            case 4:
-            case 5:
-            case 6:
-            case 7:
-                pos++;
-                characters[count++] = (char)c;
-                break;
-            case 12:
-            case 13:
-                pos += 2;
-                if (pos > length) {
+        while (pos < endPos) {
+            if ((characters[count] = (char) buf[pos++]) < '\u0080')
+                count++;
+            else if (((a = characters[count]) & 0xE0) == 0xC0) {
+                if (pos >= endPos) {
                     throw new UTFDataFormatException("bad string");
                 }
-                c2 = (int)buf[pos - 1];
-                if ((c2 & 0xC0) != 0x80) {
+                int b = buf[pos++];
+                if ((b & 0xC0) != 0x80) {
                     throw new UTFDataFormatException("bad string");
                 }
-                characters[count++] = (char)(((c & 0x1F) << 6) | (c2 & 0x3F));
-                break;
-            case 14:
-                pos += 3;
-                if (pos > length) {
+                characters[count++] = (char) (((a & 0x1F) << 6) | (b & 0x3F));
+            } else if ((a & 0xf0) == 0xe0) {
+                if (pos + 1 >= endPos) {
                     throw new UTFDataFormatException("bad string");
                 }
-                c2 = (int)buf[pos - 2];
-                c3 = (int)buf[pos - 1];
-                if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80)) {
+                int b = buf[pos++];
+                int c = buf[pos++];
+                if (((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80)) {
                     throw new UTFDataFormatException("bad string");
                 }
-                characters[count++] = (char)(((c & 0x0F) << 12) | ((c2 & 0x3F) << 6) | ((c3 & 0x3F) << 0));
-                break;
-            default:
+                characters[count++] = (char) (((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F));
+            } else {
                 throw new UTFDataFormatException("bad string");
             }
         }

Modified: activemq/trunk/kahadb/src/main/java/org/apache/kahadb/util/DataByteArrayOutputStream.java
URL: http://svn.apache.org/viewvc/activemq/trunk/kahadb/src/main/java/org/apache/kahadb/util/DataByteArrayOutputStream.java?rev=1172600&r1=1172599&r2=1172600&view=diff
==============================================================================
--- activemq/trunk/kahadb/src/main/java/org/apache/kahadb/util/DataByteArrayOutputStream.java (original)
+++ activemq/trunk/kahadb/src/main/java/org/apache/kahadb/util/DataByteArrayOutputStream.java Mon Sep 19 12:46:38 2011
@@ -21,20 +21,22 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.io.UTFDataFormatException;
 
+import org.apache.kahadb.page.PageFile;
+
 /**
  * Optimized ByteArrayOutputStream
- * 
- * 
+ *
+ *
  */
 public class DataByteArrayOutputStream extends OutputStream implements DataOutput {
-    private static final int DEFAULT_SIZE = 2048;
+    private static final int DEFAULT_SIZE = PageFile.DEFAULT_PAGE_SIZE;
     protected byte buf[];
     protected int pos;
 
     /**
      * Creates a new byte array output stream, with a buffer capacity of the
      * specified size, in bytes.
-     * 
+     *
      * @param size the initial size.
      * @exception IllegalArgumentException if size is negative.
      */
@@ -54,7 +56,7 @@ public class DataByteArrayOutputStream e
 
     /**
      * start using a fresh byte array
-     * 
+     *
      * @param size
      */
     public void restart(int size) {
@@ -71,7 +73,7 @@ public class DataByteArrayOutputStream e
 
     /**
      * Get a ByteSequence from the stream
-     * 
+     *
      * @return the byte sequence
      */
     public ByteSequence toByteSequence() {
@@ -80,9 +82,9 @@ public class DataByteArrayOutputStream e
 
     /**
      * Writes the specified byte to this byte array output stream.
-     * 
+     *
      * @param b the byte to be written.
-     * @throws IOException 
+     * @throws IOException
      */
     public void write(int b) throws IOException {
         int newcount = pos + 1;
@@ -95,11 +97,11 @@ public class DataByteArrayOutputStream e
     /**
      * Writes <code>len</code> bytes from the specified byte array starting at
      * offset <code>off</code> to this byte array output stream.
-     * 
+     *
      * @param b the data.
      * @param off the start offset in the data.
      * @param len the number of bytes to write.
-     * @throws IOException 
+     * @throws IOException
      */
     public void write(byte b[], int off, int len) throws IOException {
         if (len == 0) {
@@ -128,9 +130,9 @@ public class DataByteArrayOutputStream e
 
     /**
      * Set the current position for writing
-     * 
+     *
      * @param offset
-     * @throws IOException 
+     * @throws IOException
      */
     public void position(int offset) throws IOException {
         ensureEnoughBuffer(offset);
@@ -233,26 +235,18 @@ public class DataByteArrayOutputStream e
         }
         ensureEnoughBuffer(pos + encodedsize + 2);
         writeShort(encodedsize);
-        int i = 0;
-        for (i = 0; i < strlen; i++) {
-            c = str.charAt(i);
-            if (!((c >= 0x0001) && (c <= 0x007F))) {
-                break;
-            }
-            buf[pos++] = (byte)c;
-        }
-        for (; i < strlen; i++) {
-            c = str.charAt(i);
-            if ((c >= 0x0001) && (c <= 0x007F)) {
-                buf[pos++] = (byte)c;
-            } else if (c > 0x07FF) {
-                buf[pos++] = (byte)(0xE0 | ((c >> 12) & 0x0F));
-                buf[pos++] = (byte)(0x80 | ((c >> 6) & 0x3F));
-                buf[pos++] = (byte)(0x80 | ((c >> 0) & 0x3F));
+        for (int i = 0; i < strlen; i++) {
+            int charValue = str.charAt(i);
+            if (charValue > 0 && charValue <= 127) {
+                buf[pos++] = (byte) charValue;
+            } else if (charValue <= 2047) {
+                buf[pos++] = (byte) (0xc0 | (0x1f & (charValue >> 6)));
+                buf[pos++] = (byte) (0x80 | (0x3f & charValue));
             } else {
-                buf[pos++] = (byte)(0xC0 | ((c >> 6) & 0x1F));
-                buf[pos++] = (byte)(0x80 | ((c >> 0) & 0x3F));
-            }
+                buf[pos++] = (byte) (0xe0 | (0x0f & (charValue >> 12)));
+                buf[pos++] = (byte) (0x80 | (0x3f & (charValue >> 6)));
+                buf[pos++] = (byte) (0x80 | (0x3f & charValue));
+             }
         }
         onWrite();
     }
@@ -264,10 +258,10 @@ public class DataByteArrayOutputStream e
             buf = newbuf;
         }
     }
-    
+
     /**
-     * This method is called after each write to the buffer.  This should allow subclasses 
-     * to take some action based on the writes, for example flushing data to an external system based on size. 
+     * This method is called after each write to the buffer.  This should allow subclasses
+     * to take some action based on the writes, for example flushing data to an external system based on size.
      */
     protected void onWrite() throws IOException {
     }

Modified: activemq/trunk/kahadb/src/test/java/org/apache/kahadb/page/PageFileTest.java
URL: http://svn.apache.org/viewvc/activemq/trunk/kahadb/src/test/java/org/apache/kahadb/page/PageFileTest.java?rev=1172600&r1=1172599&r2=1172600&view=diff
==============================================================================
--- activemq/trunk/kahadb/src/test/java/org/apache/kahadb/page/PageFileTest.java (original)
+++ activemq/trunk/kahadb/src/test/java/org/apache/kahadb/page/PageFileTest.java Mon Sep 19 12:46:38 2011
@@ -28,6 +28,7 @@ import org.apache.kahadb.util.StringMars
 
 import junit.framework.TestCase;
 
+@SuppressWarnings("rawtypes")
 public class PageFileTest extends TestCase {
 
     public void testCRUD() throws IOException {

Added: activemq/trunk/kahadb/src/test/java/org/apache/kahadb/util/DataByteArrayInputStreamTest.java
URL: http://svn.apache.org/viewvc/activemq/trunk/kahadb/src/test/java/org/apache/kahadb/util/DataByteArrayInputStreamTest.java?rev=1172600&view=auto
==============================================================================
--- activemq/trunk/kahadb/src/test/java/org/apache/kahadb/util/DataByteArrayInputStreamTest.java (added)
+++ activemq/trunk/kahadb/src/test/java/org/apache/kahadb/util/DataByteArrayInputStreamTest.java Mon Sep 19 12:46:38 2011
@@ -0,0 +1,76 @@
+/**
+ * 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.kahadb.util;
+
+import junit.framework.TestCase;
+
+public class DataByteArrayInputStreamTest extends TestCase {
+
+    /**
+     * https://issues.apache.org/activemq/browse/AMQ-1911
+     */
+    public void testNonAscii() throws Exception {
+        doMarshallUnMarshallValidation("meißen");
+        
+        String accumulator = new String();
+        
+        int test = 0; // int to get Supplementary chars
+        while(Character.isDefined(test)) {
+            String toTest = String.valueOf((char)test);
+            accumulator += toTest;
+            doMarshallUnMarshallValidation(toTest);
+            test++;
+        }
+        
+        int massiveThreeByteCharValue = 0x0FFF;
+        String toTest = String.valueOf((char)massiveThreeByteCharValue);
+        accumulator += toTest;
+        doMarshallUnMarshallValidation(String.valueOf((char)massiveThreeByteCharValue));
+        
+        // Altogether
+        doMarshallUnMarshallValidation(accumulator);
+        
+        // the three byte values
+        char t = '\u0800';
+        final char max =  '\uffff';
+        accumulator = String.valueOf(t);
+        while (t < max) {
+            String val = String.valueOf(t);
+            accumulator += val;
+            doMarshallUnMarshallValidation(val);
+            t++;
+        }
+        
+        // Altogether so long as it is not too big
+        while (accumulator.length() > 20000) {
+            accumulator = accumulator.substring(20000);
+        }
+        doMarshallUnMarshallValidation(accumulator);
+    }
+    
+    void doMarshallUnMarshallValidation(String value) throws Exception {        
+        DataByteArrayOutputStream out = new DataByteArrayOutputStream();
+        out.writeBoolean(true);
+        out.writeUTF(value);
+        out.close();
+        
+        DataByteArrayInputStream in = new DataByteArrayInputStream(out.getData());
+        in.readBoolean();
+        String readBack = in.readUTF();
+        assertEquals(value, readBack);
+    }
+}

Propchange: activemq/trunk/kahadb/src/test/java/org/apache/kahadb/util/DataByteArrayInputStreamTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: activemq/trunk/kahadb/src/test/java/org/apache/kahadb/util/DataByteArrayOutputStreamTest.java
URL: http://svn.apache.org/viewvc/activemq/trunk/kahadb/src/test/java/org/apache/kahadb/util/DataByteArrayOutputStreamTest.java?rev=1172600&view=auto
==============================================================================
--- activemq/trunk/kahadb/src/test/java/org/apache/kahadb/util/DataByteArrayOutputStreamTest.java (added)
+++ activemq/trunk/kahadb/src/test/java/org/apache/kahadb/util/DataByteArrayOutputStreamTest.java Mon Sep 19 12:46:38 2011
@@ -0,0 +1,100 @@
+/**
+ * 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.kahadb.util;
+
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+public class DataByteArrayOutputStreamTest extends TestCase {
+
+    /**
+     * This test case assumes that an ArrayIndexOutOfBoundsException will be thrown when the buffer fails to resize
+     * @throws IOException
+     */
+    public void testResize() throws IOException {
+        int initSize = 64;
+        DataByteArrayOutputStream out = new DataByteArrayOutputStream();
+
+        fillOut(out, initSize);
+        // Should resized here
+        out.writeBoolean(true);
+
+        fillOut(out, initSize);
+        // Should resized here
+        out.writeByte(1);
+
+        fillOut(out, initSize);
+        // Should resized here
+        out.writeBytes("test");
+
+        fillOut(out, initSize);
+        // Should resized here
+        out.writeChar('C');
+
+        fillOut(out, initSize);
+        // Should resized here
+        out.writeChars("test");
+
+        fillOut(out, initSize);
+        // Should resized here
+        out.writeDouble(3.1416);
+
+        fillOut(out, initSize);
+        // Should resized here
+        out.writeFloat((float)3.1416);
+
+        fillOut(out, initSize);
+        // Should resized here
+        out.writeInt(12345);
+
+        fillOut(out, initSize);
+        // Should resized here
+        out.writeLong(12345);
+
+        fillOut(out, initSize);
+        // Should resized here
+        out.writeShort(1234);
+
+        fillOut(out, initSize);
+        // Should resized here
+        out.writeUTF("test");
+
+        fillOut(out, initSize);
+        // Should resized here
+        out.write(1234);
+
+        fillOut(out, initSize);
+        // Should resized here
+        out.write(new byte[10], 5, 5);
+
+        fillOut(out, initSize);
+        // Should resized here
+        out.write(new byte[10]);
+    }
+
+    /**
+     * This method restarts the stream to the init size, and fills it up with data
+     * @param out
+     * @param size
+     * @throws IOException
+     */
+    public void fillOut(DataByteArrayOutputStream out, int size) throws IOException {
+        out.restart(size);
+        out.write(new byte[size]);
+    }
+}

Propchange: activemq/trunk/kahadb/src/test/java/org/apache/kahadb/util/DataByteArrayOutputStreamTest.java
------------------------------------------------------------------------------
    svn:eol-style = native