openamf/src/java/org/openamf/io AMFDeserializer.java,1.36,1.37 AMFSerializer.java,1.48,1.49 AMFSerializerTest.java,1.7,1.8
Darin Wilson <[email protected]> Tue, 01 Jun 2004 20:37:36 +0000
| Newsgroups | gmane.comp.java.openamf.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/openamf/openamf/src/java/org/openamf/io
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15934/src/java/org/openamf/io
Modified Files:
AMFDeserializer.java AMFSerializer.java AMFSerializerTest.java
Log Message:
Add support for LongString data type
Index: AMFSerializer.java
===================================================================
RCS file: /cvsroot/openamf/openamf/src/java/org/openamf/io/AMFSerializer.java,v
retrieving revision 1.48
retrieving revision 1.49
diff -C2 -d -r1.48 -r1.49
*** AMFSerializer.java 21 Mar 2004 03:09:49 -0000 1.48
--- AMFSerializer.java 1 Jun 2004 20:37:34 -0000 1.49
***************
*** 152,158 ****
outputStream.writeDouble(((Number) value).doubleValue());
} else if (value instanceof String) {
! // write String object
! outputStream.writeByte(AMFBody.DATA_TYPE_STRING);
! outputStream.writeUTF((String) value);
} else if (value instanceof Character) {
// write String object
--- 152,156 ----
outputStream.writeDouble(((Number) value).doubleValue());
} else if (value instanceof String) {
! writeString((String)value);
} else if (value instanceof Character) {
// write String object
***************
*** 353,356 ****
--- 351,415 ----
}
+ /**
+ * Most of this code was cribbed from Java's DataOutputStream.writeUTF method
+ * which only supports Strings <= 65535 UTF-encoded characters.
+ */
+ protected int writeString(String str)
+ throws IOException {
+ int strlen = str.length();
+ int utflen = 0;
+ char[] charr = new char[strlen];
+ int c, count = 0;
+
+ str.getChars(0, strlen, charr, 0);
+
+ // check the length of the UTF-encoded string
+ for (int i = 0; i < strlen; i++) {
+ c = charr[i];
+ if ((c >= 0x0001) && (c <= 0x007F)) {
+ utflen++;
+ } else if (c > 0x07FF) {
+ utflen += 3;
+ } else {
+ utflen += 2;
+ }
+ }
+
+ /**
+ * if utf-encoded String is < 64K, use the "String" data type, with a
+ * two-byte prefix specifying string length; otherwise use the "Long String"
+ * data type, withBUG#298 a four-byte prefix
+ */
+ byte[] bytearr;
+ if (utflen <= 65535) {
+ outputStream.writeByte(AMFBody.DATA_TYPE_STRING);
+ bytearr = new byte[utflen+2];
+ } else {
+ outputStream.writeByte(AMFBody.DATA_TYPE_LONG_STRING);
+ bytearr = new byte[utflen+4];
+ bytearr[count++] = (byte) ((utflen >>> 24) & 0xFF);
+ bytearr[count++] = (byte) ((utflen >>> 16) & 0xFF);
+ }
+
+ bytearr[count++] = (byte) ((utflen >>> 8) & 0xFF);
+ bytearr[count++] = (byte) ((utflen >>> 0) & 0xFF);
+ for (int i = 0; i < strlen; i++) {
+ c = charr[i];
+ if ((c >= 0x0001) && (c <= 0x007F)) {
+ bytearr[count++] = (byte) c;
+ } else if (c > 0x07FF) {
+ bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
+ bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
+ bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
+ } else {
+ bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
+ bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
+ }
+ }
+
+ outputStream.write(bytearr);
+ return utflen + 2;
+ }
+
private void writeStoredObject(Object obj) throws IOException {
if (log.isDebugEnabled())
***************
*** 368,370 ****
--- 427,430 ----
}
+
}
\ No newline at end of file
Index: AMFSerializerTest.java
===================================================================
RCS file: /cvsroot/openamf/openamf/src/java/org/openamf/io/AMFSerializerTest.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -d -r1.7 -r1.8
*** AMFSerializerTest.java 1 Apr 2004 04:26:04 -0000 1.7
--- AMFSerializerTest.java 1 Jun 2004 20:37:34 -0000 1.8
***************
*** 61,64 ****
--- 61,98 ----
}
+ public void testSerializeLargeStringMessage() throws Exception
+ {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ AMFSerializer serializer = new AMFSerializer(new DataOutputStream(output));
+ AMFMessage message = getLargeStringTestMessage(65536);
+ serializer.serializeMessage(message);
+
+ assertTrue(output.size() > 0);
+
+ InputStream in = new ByteArrayInputStream(output.toByteArray());
+ DataInputStream dis = new DataInputStream(in);
+ AMFDeserializer deserializer = new AMFDeserializer(dis);
+ AMFMessage deserializedMessage = deserializer.getAMFMessage();
+
+ assertNotNull(deserializedMessage);
+
+ assertNotNull(deserializedMessage.getBodies());
+
+ assertEquals(message.getHeaderCount(),
+ deserializedMessage.getHeaderCount());
+
+ assertEquals(message.getBodyCount(),
+ deserializedMessage.getBodyCount());
+
+ assertEquals(message.getVersion(),
+ deserializedMessage.getVersion());
+
+ AMFBody sentBody = message.getBody(0);
+ String sentString = (String)sentBody.getValue();
+ AMFBody receivedBody = deserializedMessage.getBody(0);
+ String receivedString = (String)receivedBody.getValue();
+ assertEquals(sentString, receivedString);
+ }
+
private AMFMessage getTestMessage() throws Exception
{
***************
*** 112,115 ****
--- 146,169 ----
}
+ private AMFMessage getLargeStringTestMessage(int stringSize)
+ {
+ StringBuffer buf = new StringBuffer(stringSize);
+ for (int i = 0; i < stringSize; i++)
+ {
+ buf.append("x");
+ }
+
+ AMFMessage message = new AMFMessage();
+
+ message.addHeader("testKey", true, "testValue");
+
+ message.addBody("someService.someMethod",
+ "someResponse",
+ buf.toString(),
+ AMFBody.DATA_TYPE_STRING);
+ return message;
+
+ }
+
private org.w3c.dom.Document getXMLDocument() throws Exception
{
Index: AMFDeserializer.java
===================================================================
RCS file: /cvsroot/openamf/openamf/src/java/org/openamf/io/AMFDeserializer.java,v
retrieving revision 1.36
retrieving revision 1.37
diff -C2 -d -r1.36 -r1.37
*** AMFDeserializer.java 21 Aug 2003 01:05:16 -0000 1.36
--- AMFDeserializer.java 1 Jun 2004 20:37:34 -0000 1.37
***************
*** 10,13 ****
--- 10,14 ----
import java.io.DataInputStream;
import java.io.IOException;
+ import java.io.UTFDataFormatException;
import java.util.*;
***************
*** 330,336 ****
return readDate();
case AMFBody.DATA_TYPE_LONG_STRING: // 12
! // TODO - fixme
! int utflen = inputStream.readInt();
! return inputStream.readUTF();
case AMFBody.DATA_TYPE_AS_OBJECT: // 13
return readASObject();
--- 331,335 ----
return readDate();
case AMFBody.DATA_TYPE_LONG_STRING: // 12
! return readLongUTF(inputStream);
case AMFBody.DATA_TYPE_AS_OBJECT: // 13
return readASObject();
***************
*** 346,348 ****
--- 345,401 ----
}
}
+
+ /**
+ * This is a hacked verison of Java's DataInputStream.readUTF(), which only
+ * supports Strings <= 65535 UTF-8-encoded characters
+ */
+ private Object readLongUTF(DataInputStream in) throws IOException {
+ int utflen = in.readInt();
+ StringBuffer str = new StringBuffer(utflen);
+ byte bytearr [] = new byte[utflen];
+ int c, char2, char3;
+ int count = 0;
+
+ in.readFully(bytearr, 0, utflen);
+
+ while (count < utflen) {
+ c = (int) bytearr[count] & 0xff;
+ switch (c >> 4) {
+ case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+ /* 0xxxxxxx*/
+ count++;
+ str.append((char)c);
+ break;
+ case 12: case 13:
+ /* 110x xxxx 10xx xxxx*/
+ count += 2;
+ if (count > utflen)
+ throw new UTFDataFormatException();
+ char2 = (int) bytearr[count-1];
+ if ((char2 & 0xC0) != 0x80)
+ throw new UTFDataFormatException();
+ str.append((char)(((c & 0x1F) << 6) | (char2 & 0x3F)));
+ break;
+ case 14:
+ /* 1110 xxxx 10xx xxxx 10xx xxxx */
+ count += 3;
+ if (count > utflen)
+ throw new UTFDataFormatException();
+ char2 = (int) bytearr[count-2];
+ char3 = (int) bytearr[count-1];
+ if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
+ throw new UTFDataFormatException();
+ str.append((char)(((c & 0x0F) << 12) |
+ ((char2 & 0x3F) << 6) |
+ ((char3 & 0x3F) << 0)));
+ break;
+ default:
+ /* 10xx xxxx, 1111 xxxx */
+ throw new UTFDataFormatException();
+ }
+ }
+
+ // The number of chars produced may be less than utflen
+ return new String(str);
+ }
}
\ No newline at end of file
-------------------------------------------------------
This SF.Net email is sponsored by the new InstallShield X.
From Windows to Linux, servers to mobile, InstallShield X is the one
installation-authoring solution that does it all. Learn more and
evaluate today! http://www.installshield.com/Dev2Dev/0504