mirror of https://github.com/apache/activemq.git
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. git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@1172600 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
a36e618f71
commit
199c6838d4
|
@ -32,6 +32,8 @@ public final class DataByteArrayInputStream extends InputStream implements DataI
|
||||||
private int offset;
|
private int offset;
|
||||||
private int length;
|
private int length;
|
||||||
|
|
||||||
|
private byte[] work;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a <code>StoreByteArrayInputStream</code>.
|
* Creates a <code>StoreByteArrayInputStream</code>.
|
||||||
*
|
*
|
||||||
|
@ -42,6 +44,7 @@ public final class DataByteArrayInputStream extends InputStream implements DataI
|
||||||
this.pos = 0;
|
this.pos = 0;
|
||||||
this.offset = 0;
|
this.offset = 0;
|
||||||
this.length = buf.length;
|
this.length = buf.length;
|
||||||
|
this.work = new byte[8];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,6 +57,7 @@ public final class DataByteArrayInputStream extends InputStream implements DataI
|
||||||
this.offset = sequence.getOffset();
|
this.offset = sequence.getOffset();
|
||||||
this.pos = this.offset;
|
this.pos = this.offset;
|
||||||
this.length = sequence.length;
|
this.length = sequence.length;
|
||||||
|
this.work = new byte[8];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -204,34 +208,35 @@ public final class DataByteArrayInputStream extends InputStream implements DataI
|
||||||
}
|
}
|
||||||
|
|
||||||
public short readShort() {
|
public short readShort() {
|
||||||
int ch1 = read();
|
this.read(work, 0, 2);
|
||||||
int ch2 = read();
|
return (short) (((work[0] & 0xff) << 8) | (work[1] & 0xff));
|
||||||
return (short)((ch1 << 8) + (ch2 << 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int readUnsignedShort() {
|
public int readUnsignedShort() {
|
||||||
int ch1 = read();
|
this.read(work, 0, 2);
|
||||||
int ch2 = read();
|
return (int) (((work[0] & 0xff) << 8) | (work[1] & 0xff));
|
||||||
return (ch1 << 8) + (ch2 << 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public char readChar() {
|
public char readChar() {
|
||||||
int ch1 = read();
|
this.read(work, 0, 2);
|
||||||
int ch2 = read();
|
return (char) (((work[0] & 0xff) << 8) | (work[1] & 0xff));
|
||||||
return (char)((ch1 << 8) + (ch2 << 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int readInt() {
|
public int readInt() {
|
||||||
int ch1 = read();
|
this.read(work, 0, 4);
|
||||||
int ch2 = read();
|
return ((work[0] & 0xff) << 24) | ((work[1] & 0xff) << 16) |
|
||||||
int ch3 = read();
|
((work[2] & 0xff) << 8) | (work[3] & 0xff);
|
||||||
int ch4 = read();
|
|
||||||
return (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public long readLong() {
|
public long readLong() {
|
||||||
long rc = ((long)buf[pos++] << 56) + ((long)(buf[pos++] & 255) << 48) + ((long)(buf[pos++] & 255) << 40) + ((long)(buf[pos++] & 255) << 32);
|
this.read(work, 0, 8);
|
||||||
return rc + ((long)(buf[pos++] & 255) << 24) + ((buf[pos++] & 255) << 16) + ((buf[pos++] & 255) << 8) + ((buf[pos++] & 255) << 0);
|
|
||||||
|
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 {
|
public float readFloat() throws IOException {
|
||||||
|
@ -262,59 +267,32 @@ public final class DataByteArrayInputStream extends InputStream implements DataI
|
||||||
|
|
||||||
public String readUTF() throws IOException {
|
public String readUTF() throws IOException {
|
||||||
int length = readUnsignedShort();
|
int length = readUnsignedShort();
|
||||||
|
int endPos = pos + length;
|
||||||
|
int count = 0, a;
|
||||||
char[] characters = new char[length];
|
char[] characters = new char[length];
|
||||||
int c;
|
while (pos < endPos) {
|
||||||
int c2;
|
if ((characters[count] = (char) buf[pos++]) < '\u0080')
|
||||||
int c3;
|
count++;
|
||||||
int count = 0;
|
else if (((a = characters[count]) & 0xE0) == 0xC0) {
|
||||||
int total = pos + length;
|
if (pos >= endPos) {
|
||||||
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) {
|
|
||||||
throw new UTFDataFormatException("bad string");
|
throw new UTFDataFormatException("bad string");
|
||||||
}
|
}
|
||||||
c2 = (int)buf[pos - 1];
|
int b = buf[pos++];
|
||||||
if ((c2 & 0xC0) != 0x80) {
|
if ((b & 0xC0) != 0x80) {
|
||||||
throw new UTFDataFormatException("bad string");
|
throw new UTFDataFormatException("bad string");
|
||||||
}
|
}
|
||||||
characters[count++] = (char)(((c & 0x1F) << 6) | (c2 & 0x3F));
|
characters[count++] = (char) (((a & 0x1F) << 6) | (b & 0x3F));
|
||||||
break;
|
} else if ((a & 0xf0) == 0xe0) {
|
||||||
case 14:
|
if (pos + 1 >= endPos) {
|
||||||
pos += 3;
|
|
||||||
if (pos > length) {
|
|
||||||
throw new UTFDataFormatException("bad string");
|
throw new UTFDataFormatException("bad string");
|
||||||
}
|
}
|
||||||
c2 = (int)buf[pos - 2];
|
int b = buf[pos++];
|
||||||
c3 = (int)buf[pos - 1];
|
int c = buf[pos++];
|
||||||
if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80)) {
|
if (((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80)) {
|
||||||
throw new UTFDataFormatException("bad string");
|
throw new UTFDataFormatException("bad string");
|
||||||
}
|
}
|
||||||
characters[count++] = (char)(((c & 0x0F) << 12) | ((c2 & 0x3F) << 6) | ((c3 & 0x3F) << 0));
|
characters[count++] = (char) (((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F));
|
||||||
break;
|
} else {
|
||||||
default:
|
|
||||||
throw new UTFDataFormatException("bad string");
|
throw new UTFDataFormatException("bad string");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,13 +21,15 @@ import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.UTFDataFormatException;
|
import java.io.UTFDataFormatException;
|
||||||
|
|
||||||
|
import org.apache.kahadb.page.PageFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optimized ByteArrayOutputStream
|
* Optimized ByteArrayOutputStream
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DataByteArrayOutputStream extends OutputStream implements DataOutput {
|
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 byte buf[];
|
||||||
protected int pos;
|
protected int pos;
|
||||||
|
|
||||||
|
@ -233,26 +235,18 @@ public class DataByteArrayOutputStream extends OutputStream implements DataOutpu
|
||||||
}
|
}
|
||||||
ensureEnoughBuffer(pos + encodedsize + 2);
|
ensureEnoughBuffer(pos + encodedsize + 2);
|
||||||
writeShort(encodedsize);
|
writeShort(encodedsize);
|
||||||
int i = 0;
|
for (int i = 0; i < strlen; i++) {
|
||||||
for (i = 0; i < strlen; i++) {
|
int charValue = str.charAt(i);
|
||||||
c = str.charAt(i);
|
if (charValue > 0 && charValue <= 127) {
|
||||||
if (!((c >= 0x0001) && (c <= 0x007F))) {
|
buf[pos++] = (byte) charValue;
|
||||||
break;
|
} else if (charValue <= 2047) {
|
||||||
}
|
buf[pos++] = (byte) (0xc0 | (0x1f & (charValue >> 6)));
|
||||||
buf[pos++] = (byte)c;
|
buf[pos++] = (byte) (0x80 | (0x3f & charValue));
|
||||||
}
|
|
||||||
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));
|
|
||||||
} else {
|
} else {
|
||||||
buf[pos++] = (byte)(0xC0 | ((c >> 6) & 0x1F));
|
buf[pos++] = (byte) (0xe0 | (0x0f & (charValue >> 12)));
|
||||||
buf[pos++] = (byte)(0x80 | ((c >> 0) & 0x3F));
|
buf[pos++] = (byte) (0x80 | (0x3f & (charValue >> 6)));
|
||||||
}
|
buf[pos++] = (byte) (0x80 | (0x3f & charValue));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onWrite();
|
onWrite();
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.apache.kahadb.util.StringMarshaller;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
public class PageFileTest extends TestCase {
|
public class PageFileTest extends TestCase {
|
||||||
|
|
||||||
public void testCRUD() throws IOException {
|
public void testCRUD() throws IOException {
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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]);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue