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