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 2009/04/14 16:05:05 UTC

svn commit: r764780 - in /activemq/activemq-cpp/trunk/activemq-cpp/src: main/ main/activemq/commands/ main/activemq/wireformat/openwire/marshal/ main/activemq/wireformat/openwire/utils/ main/decaf/io/ test/activemq/wireformat/openwire/utils/ test/decaf...

Author: tabish
Date: Tue Apr 14 14:05:04 2009
New Revision: 764780

URL: http://svn.apache.org/viewvc?rev=764780&view=rev
Log:
http://issues.apache.org/activemq/browse/AMQCPP-235

Fixed the DataInputStream, DataOutputStream and OpenwireStringSupport classes to all read and write correct modified UTF-8 strings for all ascii values 0-255.   OpenwireStringSupport now correctly write the data with an int size prefix to support larger strings enabling primitive maps to store strings larger than 65535 characters.

Added:
    activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/UTFDataFormatException.h   (with props)
Modified:
    activemq/activemq-cpp/trunk/activemq-cpp/src/main/Makefile.am
    activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/commands/ActiveMQTextMessage.cpp
    activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/marshal/PrimitiveMapMarshaller.cpp
    activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/utils/OpenwireStringSupport.cpp
    activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.cpp
    activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.h
    activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.cpp
    activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.h
    activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.cpp
    activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.h
    activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.cpp
    activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.h
    activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.cpp
    activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.h

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/Makefile.am
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/Makefile.am?rev=764780&r1=764779&r2=764780&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/Makefile.am (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/Makefile.am Tue Apr 14 14:05:04 2009
@@ -573,6 +573,7 @@
     decaf/io/BufferedOutputStream.h \
     decaf/io/ByteArrayInputStream.h \
     decaf/io/OutputStream.h \
+    decaf/io/UTFDataFormatException.h \
     decaf/io/BufferedInputStream.h \
     decaf/io/DataInputStream.h \
     decaf/io/IOException.h \

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/commands/ActiveMQTextMessage.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/commands/ActiveMQTextMessage.cpp?rev=764780&r1=764779&r2=764780&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/commands/ActiveMQTextMessage.cpp (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/commands/ActiveMQTextMessage.cpp Tue Apr 14 14:05:04 2009
@@ -18,11 +18,15 @@
 
 #include <decaf/io/ByteArrayOutputStream.h>
 #include <decaf/io/DataOutputStream.h>
+#include <activemq/wireformat/openwire/utils/OpenwireStringSupport.h>
 
 using namespace std;
 using namespace activemq;
 using namespace activemq::exceptions;
 using namespace activemq::commands;
+using namespace activemq::wireformat;
+using namespace activemq::wireformat::openwire;
+using namespace activemq::wireformat::openwire::utils;
 using namespace decaf::lang;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -67,10 +71,9 @@
         std::vector<unsigned char>& content = getContent();
         content.clear();
         decaf::io::ByteArrayOutputStream bos( content );
-        decaf::io::DataOutputStream dos( &bos );
+        decaf::io::DataOutputStream dataOut( &bos );
 
-        dos.writeInt( (int)msg.length() );
-        dos.write( (const unsigned char*)msg.c_str(), 0, msg.length() );
+        OpenwireStringSupport::writeString( dataOut, &msg );
     }
     AMQ_CATCH_ALL_THROW_CMSEXCEPTION()
 }

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/marshal/PrimitiveMapMarshaller.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/marshal/PrimitiveMapMarshaller.cpp?rev=764780&r1=764779&r2=764780&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/marshal/PrimitiveMapMarshaller.cpp (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/marshal/PrimitiveMapMarshaller.cpp Tue Apr 14 14:05:04 2009
@@ -23,6 +23,7 @@
 #include <decaf/io/DataOutputStream.h>
 #include <activemq/wireformat/openwire/utils/OpenwireStringSupport.h>
 #include <activemq/exceptions/ActiveMQException.h>
+#include <decaf/lang/Short.h>
 
 using namespace activemq;
 using namespace activemq::util;
@@ -72,7 +73,7 @@
             PrimitiveMap* map = new PrimitiveMap;
 
             for( int i=0; i < size; i++ ) {
-                std::string key = OpenwireStringSupport::readString( dataIn );
+                std::string key = dataIn.readUTF();
                 map->put( key, unmarshalPrimitive( dataIn ) );
             }
 
@@ -124,7 +125,7 @@
 
         for(; iter != keys.end(); ++iter ) {
 
-            OpenwireStringSupport::writeString( dataOut, &(*iter) );
+            dataOut.writeUTF( *iter );
             PrimitiveValueNode value = map.get( *iter );
             marshalPrimitive( dataOut, value );
         }
@@ -213,14 +214,14 @@
             std::string data = value.getString();
 
             // is the string big??
-            if( data.size() > 8191 ) {
+            if( data.size() > Short::MAX_VALUE / 4 ) {
                 dataOut.writeByte( PrimitiveValueNode::BIG_STRING_TYPE );
+                OpenwireStringSupport::writeString( dataOut, &data );
             } else {
                 dataOut.writeByte( PrimitiveValueNode::STRING_TYPE );
+                dataOut.writeUTF( data );
             }
 
-            OpenwireStringSupport::writeString( dataOut, &data );
-
         } else if( value.getValueType() == PrimitiveValueNode::LIST_TYPE ) {
 
             dataOut.writeByte( PrimitiveValueNode::LIST_TYPE );
@@ -254,7 +255,7 @@
 
         if( size > 0 ) {
             for( int i=0; i < size; i++ ) {
-                std::string key = OpenwireStringSupport::readString( dataIn );
+                std::string key = dataIn.readUTF();
                 map.put( key, unmarshalPrimitive( dataIn ) );
             }
         }
@@ -331,6 +332,8 @@
                 break;
             }
             case PrimitiveValueNode::STRING_TYPE:
+                value.setString( dataIn.readUTF() );
+                break;
             case PrimitiveValueNode::BIG_STRING_TYPE:
                 value.setString( OpenwireStringSupport::readString( dataIn ) );
                 break;

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/utils/OpenwireStringSupport.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/utils/OpenwireStringSupport.cpp?rev=764780&r1=764779&r2=764780&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/utils/OpenwireStringSupport.cpp (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/activemq/wireformat/openwire/utils/OpenwireStringSupport.cpp Tue Apr 14 14:05:04 2009
@@ -34,71 +34,86 @@
 
     try {
 
-        short utflen = dataIn.readShort();
+        int utfLength = dataIn.readInt();
 
-        if( utflen > -1 )
-        {
-            // Let the stream get us all that data.
-            std::vector<unsigned char> value;
-            value.resize( utflen );
-            dataIn.readFully( value );
-
-            unsigned char c = 0;
-            int count = 0;
-
-            // x counts the number of 2-byte UTF8 sequences decoded
-            int x = 0;
-
-            while( count+x < utflen )
-            {
-                c = value[count+x];
-                switch( c >> 4 )
-                {
-                    case 0:
-                    case 1:
-                    case 2:
-                    case 3:
-                    case 4:
-                    case 5:
-                    case 6:
-                    case 7:
-                        // 1-byte UTF8 encoding: 0xxxxxxx
-                        value[count] = c;
-                        count++;
-                        break;
-                    case 12:
-                    case 13:
-                        // 2-byte UTF8 encoding: 110X XXxx 10xx xxxx
-                        // Bits set at 'X' means we have encountered a UTF8 encoded value
-                        // greater than 255, which is not supported.
-                        if( c & 0x1C ) {
-                            throw IOException(
-                                __FILE__,
-                                __LINE__,
-                                "OpenwireStringSupport::readString - Encoding not supported" );
-                        }
-                        // Place the decoded UTF8 character back into the value array
-                        value[count] = ((c & 0x1F) << 6) | (value[count+x+1] & 0x3F);
-                        count++;
-                        x++;
-                        break;
-                    case 14:
-                    default:
-                    {
-                        // 3-byte UTF8 encoding: 1110 xxxx  10xx xxxx  10xx xxxx
-                        throw IOException(
-                            __FILE__,
-                            __LINE__,
-                            "OpenwireStringSupport::readString - Encoding not supported" );
-                    }
+        if( utfLength == -1 ) {
+            return "";
+        }
+
+        std::vector<unsigned char> buffer( utfLength );
+        std::string result( utfLength, char() );
+
+        dataIn.readFully( &buffer[0], 0, utfLength );
+
+        int count = 0;
+        int index = 0;
+        unsigned char a = 0;
+
+        while( count < utfLength ) {
+            if( (unsigned char)( result[index] = (char)buffer[count++] ) < 0x80 ) {
+                index++;
+            } else if( ( ( a = result[index++] ) & 0xE0 ) == 0xC0 ) {
+                if( count >= utfLength ) {
+                    throw UTFDataFormatException(
+                        __FILE__, __LINE__,
+                        "Invalid UTF-8 encoding found, start of two byte char found at end.");
+                }
+
+                unsigned char b = buffer[count++];
+                if( ( b & 0xC0 ) != 0x80 ) {
+                    throw UTFDataFormatException(
+                        __FILE__, __LINE__,
+                        "Invalid UTF-8 encoding found, byte two does not start with 0x80." );
                 }
-            }
 
-            // Let the Compiler give us a string.
-            return std::string(reinterpret_cast<const char*>(&value[0]), count);
+                // 2-byte UTF8 encoding: 110X XXxx 10xx xxxx
+                // Bits set at 'X' means we have encountered a UTF8 encoded value
+                // greater than 255, which is not supported.
+                if( a & 0x1C ) {
+                    throw UTFDataFormatException(
+                        __FILE__, __LINE__,
+                        "Invalid 2 byte UTF-8 encoding found, "
+                        "This method only supports encoded ASCII values of (0-255)." );
+                }
+
+                result[index++] = (char)( ( ( a & 0x1F ) << 6 ) | ( b & 0x3F ) );
+
+            } else if( ( a & 0xF0 ) == 0xE0 ) {
+
+                if( count + 1 >= utfLength ) {
+                    throw UTFDataFormatException(
+                        __FILE__, __LINE__,
+                        "Invalid UTF-8 encoding found, start of three byte char found at end.");
+                } else {
+                    throw UTFDataFormatException(
+                        __FILE__, __LINE__,
+                        "Invalid 3 byte UTF-8 encoding found, "
+                        "This method only supports encoded ASCII values of (0-255)." );
+                }
+
+                // If we were to support multibyte strings in the future this would be
+                // the remainder of this method decoding logic.
+                //
+                //int b = buffer[count++];
+                //int c = buffer[count++];
+                //if( ( ( b & 0xC0 ) != 0x80 ) || ( ( c & 0xC0 ) != 0x80 ) ) {
+                //    throw UTFDataFormatException(
+                //        __FILE__, __LINE__,
+                //        "Invalid UTF-8 encoding found, byte two does not start with 0x80." );
+                //}
+                //
+                //result[inde++] = (char)( ( ( a & 0x0F ) << 12 ) |
+                //                         ( ( b & 0x3F ) << 6 ) | ( c & 0x3F ) );
+
+            } else {
+                throw UTFDataFormatException(
+                    __FILE__, __LINE__, "Invalid UTF-8 encoding found, aborting.");
+            }
         }
 
-        return "";
+        result.resize( index );
+
+        return result;
     }
     AMQ_CATCH_RETHROW( decaf::io::IOException )
     AMQ_CATCH_EXCEPTION_CONVERT( Exception, decaf::io::IOException )
@@ -114,50 +129,60 @@
 
         if( str != NULL ) {
 
-            if( str->size() > 65536 ) {
+            int utfLength = 0;
+            std::size_t length = str->length();
 
-                throw IOException(
-                    __FILE__,
-                    __LINE__,
-                    ( std::string( "OpenwireStringSupport::writeString - Cannot marshall " ) +
-                    "string longer than: 65536 characters, supplied string was: " +
-                    Integer::toString( (int)str->size() ) + " characters long." ).c_str() );
-            }
+            for( std::size_t i = 0; i < length; ++i ) {
+
+                unsigned int charValue = (unsigned char)str->at( i );
 
-            unsigned short utflen = 0;
-            int count = 0;
-            unsigned char c;
-
-            std::string::const_iterator iter = str->begin();
-
-            for(; iter != str->end(); ++iter ) {
-                c = *iter;
-                if( c < 0x80 ) {
-                    utflen++;
+                // Written to allow for expansion to wide character strings at some
+                // point, as it stands now the value can never be > 255 since the
+                // string class returns a single byte char.
+                if( charValue > 0 && charValue <= 127 ) {
+                    utfLength++;
+                } else if( charValue <= 2047 ) {
+                    utfLength += 2;
                 } else {
-                    utflen += 2;
+                    utfLength += 3;
                 }
             }
 
-            dataOut.writeUnsignedShort( utflen );
-            std::vector<unsigned char> byteArr;
-            byteArr.resize( utflen );
-
-            for( iter = str->begin(); iter != str->end(); ++iter ) {
-
-                c = *iter;
-                if( c < 0x80 ) {
-                    byteArr[count++] = (unsigned char)c;
+            if( utfLength > Integer::MAX_VALUE ) {
+                throw UTFDataFormatException(
+                    __FILE__, __LINE__,
+                    ( std::string( "OpenwireStringSupport::writeString - Cannot marshall " ) +
+                    "string utf8 encoding longer than: 2^31 bytes, supplied string utf8 encoding was: " +
+                    Integer::toString( (int)utfLength ) + " bytes long." ).c_str() );
+            }
+
+            std::vector<unsigned char> utfBytes( (std::size_t)utfLength );
+            unsigned int utfIndex = 0;
+
+            for( std::size_t i = 0; i < length; i++ ) {
+
+                unsigned int charValue = (unsigned char)str->at( i );
+
+                // Written to allow for expansion to wide character strings at some
+                // point, as it stands now the value can never be > 255 since the
+                // string class returns a single byte char.
+                if( charValue > 0 && charValue <= 127 ) {
+                    utfBytes[utfIndex++] = (unsigned char)charValue;
+                } else if( charValue <= 2047 ) {
+                    utfBytes[utfIndex++] = (unsigned char)(0xc0 | (0x1f & (charValue >> 6)));
+                    utfBytes[utfIndex++] = (unsigned char)(0x80 | (0x3f & charValue));
                 } else {
-                    byteArr[count++] = (unsigned char)( 0xC0 | ( (c >> 6) & 0x1F) );
-                    byteArr[count++] = (unsigned char)( 0x80 | ( (c >> 0) & 0x3F) );
+                    utfBytes[utfIndex++] = (unsigned char)(0xe0 | (0x0f & (charValue >> 12)));
+                    utfBytes[utfIndex++] = (unsigned char)(0x80 | (0x3f & (charValue >> 6)));
+                    utfBytes[utfIndex++] = (unsigned char)(0x80 | (0x3f & charValue));
                 }
             }
 
-            dataOut.write( byteArr );
+            dataOut.writeInt( utfLength );
+            dataOut.write( &utfBytes[0], 0, utfLength );
 
         } else {
-            dataOut.writeShort( (short)-1 );
+            dataOut.writeInt( -1 );
         }
     }
     AMQ_CATCH_RETHROW( decaf::io::IOException )

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.cpp?rev=764780&r1=764779&r2=764780&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.cpp (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.cpp Tue Apr 14 14:05:04 2009
@@ -32,8 +32,7 @@
 DataInputStream::~DataInputStream() {}
 
 ////////////////////////////////////////////////////////////////////////////////
-int DataInputStream::read( std::vector<unsigned char>& buffer )
-    throw ( io::IOException ) {
+int DataInputStream::read( std::vector<unsigned char>& buffer ) throw ( io::IOException ) {
 
     try {
         return this->read( &buffer[0], 0, buffer.size() );
@@ -75,13 +74,11 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-bool DataInputStream::readBoolean()
-    throw( IOException, EOFException ) {
+bool DataInputStream::readBoolean() throw( IOException, EOFException ) {
 
     try {
-        unsigned char value = 0;
-        readAllData( &value, sizeof(value) );
-        return (bool)( value != 0 );
+        readAllData( buffer, sizeof(char) );
+        return (bool)( buffer[0] != 0 );
     }
     DECAF_CATCH_RETHROW( EOFException )
     DECAF_CATCH_RETHROW( IOException )
@@ -89,13 +86,11 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-char DataInputStream::readByte()
-    throw ( IOException, EOFException ) {
+char DataInputStream::readByte() throw ( IOException, EOFException ) {
 
     try {
-        unsigned char value = 0;
-        readAllData( &value, sizeof(value) );
-        return (char)( value );
+        readAllData( buffer, sizeof(unsigned char) );
+        return (char)( buffer[0] );
     }
     DECAF_CATCH_RETHROW( EOFException )
     DECAF_CATCH_RETHROW( IOException )
@@ -103,13 +98,11 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-unsigned char DataInputStream::readUnsignedByte()
-    throw ( IOException, EOFException ) {
+unsigned char DataInputStream::readUnsignedByte() throw ( IOException, EOFException ) {
 
     try {
-        unsigned char value = 0;
-        readAllData( &value, sizeof(value) );
-        return value;
+        readAllData( buffer, sizeof(unsigned char) );
+        return buffer[0];
     }
     DECAF_CATCH_RETHROW( EOFException )
     DECAF_CATCH_RETHROW( IOException )
@@ -118,10 +111,10 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 char DataInputStream::readChar() throw ( IOException, EOFException ) {
+
     try {
-        unsigned char value = 0;
-        readAllData( &value, sizeof(value) );
-        return (char)( value );
+        readAllData( buffer, sizeof(unsigned char) );
+        return (char)( buffer[0] );
     }
     DECAF_CATCH_RETHROW( EOFException )
     DECAF_CATCH_RETHROW( IOException )
@@ -130,10 +123,10 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 short DataInputStream::readShort() throw ( io::IOException, io::EOFException ) {
+
     try {
         short value = 0;
-        unsigned char buffer[sizeof(value)] = {0};
-        readAllData( buffer, sizeof(value) );
+        readAllData( buffer, sizeof(short) );
         value |= (buffer[0] << 8 | buffer[1] << 0);
         return value;
     }
@@ -143,12 +136,11 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-unsigned short DataInputStream::readUnsignedShort()
-    throw ( io::IOException, io::EOFException ) {
+unsigned short DataInputStream::readUnsignedShort() throw ( io::IOException, io::EOFException ) {
+
     try {
         unsigned short value = 0;
-        unsigned char buffer[sizeof(value)] = {0};
-        readAllData( buffer, sizeof(value) );
+        readAllData( buffer, sizeof(unsigned short) );
         value |= (buffer[0] << 8 | buffer[1] << 0);
         return value;
     }
@@ -159,10 +151,10 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 int DataInputStream::readInt() throw ( io::IOException, io::EOFException ) {
+
     try {
         unsigned int value = 0;
-        unsigned char buffer[sizeof(value)] = {0};
-        readAllData( buffer, sizeof(value) );
+        readAllData( buffer, sizeof(int) );
         value |= (buffer[0] << 24 | buffer[1] << 16 |
                   buffer[2] << 8 | buffer[3] << 0);
         return value;
@@ -174,6 +166,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 double DataInputStream::readDouble() throw ( io::IOException, io::EOFException ) {
+
     try {
         unsigned long long lvalue = this->readLong();
         double value = 0.0;
@@ -187,6 +180,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 float DataInputStream::readFloat() throw ( io::IOException, io::EOFException ) {
+
     try {
         unsigned int lvalue = this->readInt();
         float value = 0.0f;
@@ -201,10 +195,10 @@
 ////////////////////////////////////////////////////////////////////////////////
 long long DataInputStream::readLong()
     throw ( io::IOException, io::EOFException ) {
+
     try {
         unsigned long long value = 0;
-        unsigned char buffer[sizeof(value)] = {0};
-        readAllData( buffer, sizeof(value) );
+        readAllData( buffer, sizeof(long long) );
 
         // Have to do it this way because on Solaris and Cygwin we get all
         // kinds of warnings when shifting a byte up into a long long.
@@ -228,8 +222,8 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-std::string DataInputStream::readString()
-    throw ( io::IOException, io::EOFException ) {
+std::string DataInputStream::readString() throw ( io::IOException, io::EOFException ) {
+
     try {
 
         if( inputStream == NULL ) {
@@ -271,7 +265,8 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 std::string DataInputStream::readUTF()
-    throw ( io::IOException, io::EOFException ) {
+    throw ( io::IOException, io::EOFException, io::UTFDataFormatException ) {
+
     try {
 
         if( inputStream == NULL ) {
@@ -280,23 +275,83 @@
                 "DataInputStream::readFully - Base input stream is null" );
         }
 
-        std::vector<unsigned char> buffer;
-        unsigned short length = readUnsignedShort();
-        buffer.resize(length + 1);  // Add one for a null charactor.
-
-        std::size_t n = 0;
-        while( n < length ) {
-            int count = inputStream->read( &buffer[n], 0, (length - n) );
-            if( count == -1 ) {
-                throw EOFException(
-                    __FILE__, __LINE__,
-                    "DataInputStream::readUTF - Reached EOF" );
+        unsigned short utfLength = readUnsignedShort();
+        std::vector<unsigned char> buffer( utfLength );
+        std::string result( utfLength, char() );
+
+        this->readFully( &buffer[0], 0, utfLength );
+
+        std::size_t count = 0;
+        std::size_t index = 0;
+        unsigned char a = 0;
+
+        while( count < utfLength ) {
+            if( (unsigned char)( result[index] = (char)buffer[count++] ) < 0x80 ) {
+                index++;
+            } else if( ( ( a = result[index++] ) & 0xE0 ) == 0xC0 ) {
+                if( count >= utfLength ) {
+                    throw UTFDataFormatException(
+                        __FILE__, __LINE__,
+                        "Invalid UTF-8 encoding found, start of two byte char found at end.");
+                }
+
+                unsigned char b = buffer[count++];
+                if( ( b & 0xC0 ) != 0x80 ) {
+                    throw UTFDataFormatException(
+                        __FILE__, __LINE__,
+                        "Invalid UTF-8 encoding found, byte two does not start with 0x80." );
+                }
+
+                // 2-byte UTF8 encoding: 110X XXxx 10xx xxxx
+                // Bits set at 'X' means we have encountered a UTF8 encoded value
+                // greater than 255, which is not supported.
+                if( a & 0x1C ) {
+                    throw UTFDataFormatException(
+                        __FILE__, __LINE__,
+                        "Invalid 2 byte UTF-8 encoding found, "
+                        "This method only supports encoded ASCII values of (0-255)." );
+                }
+
+                result[index++] = (char)( ( ( a & 0x1F ) << 6 ) | ( b & 0x3F ) );
+
+            } else if( ( a & 0xF0 ) == 0xE0 ) {
+
+                if( count + 1 >= utfLength ) {
+                    throw UTFDataFormatException(
+                        __FILE__, __LINE__,
+                        "Invalid UTF-8 encoding found, start of three byte char found at end.");
+                } else {
+                    throw UTFDataFormatException(
+                        __FILE__, __LINE__,
+                        "Invalid 3 byte UTF-8 encoding found, "
+                        "This method only supports encoded ASCII values of (0-255)." );
+                }
+
+                // If we were to support multibyte strings in the future this would be
+                // the remainder of this method decoding logic.
+                //
+                //int b = buffer[count++];
+                //int c = buffer[count++];
+                //if( ( ( b & 0xC0 ) != 0x80 ) || ( ( c & 0xC0 ) != 0x80 ) ) {
+                //    throw UTFDataFormatException(
+                //        __FILE__, __LINE__,
+                //        "Invalid UTF-8 encoding found, byte two does not start with 0x80." );
+                //}
+                //
+                //result[inde++] = (char)( ( ( a & 0x0F ) << 12 ) |
+                //                         ( ( b & 0x3F ) << 6 ) | ( c & 0x3F ) );
+
+            } else {
+                throw UTFDataFormatException(
+                    __FILE__, __LINE__, "Invalid UTF-8 encoding found, aborting.");
             }
-            n += count;
         }
 
-        return (char*)&buffer[0];
+        result.resize( index );
+
+        return result;
     }
+    DECAF_CATCH_RETHROW( UTFDataFormatException )
     DECAF_CATCH_RETHROW( EOFException )
     DECAF_CATCH_RETHROW( IOException )
     DECAF_CATCHALL_THROW( IOException )
@@ -305,6 +360,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 void DataInputStream::readFully( std::vector< unsigned char >& buffer )
     throw ( io::IOException, io::EOFException ) {
+
     try {
         if( buffer.empty() ) {
             return;
@@ -362,6 +418,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 std::size_t DataInputStream::skip( std::size_t num )
     throw( io::IOException, lang::exceptions::UnsupportedOperationException ) {
+
     try {
 
         if( inputStream == NULL ) {

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.h?rev=764780&r1=764779&r2=764780&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.h (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataInputStream.h Tue Apr 14 14:05:04 2009
@@ -21,6 +21,7 @@
 #include <decaf/io/FilterInputStream.h>
 #include <decaf/io/IOException.h>
 #include <decaf/io/EOFException.h>
+#include <decaf/io/UTFDataFormatException.h>
 #include <decaf/lang/exceptions/NullPointerException.h>
 #include <decaf/lang/exceptions/IndexOutOfBoundsException.h>
 
@@ -39,9 +40,16 @@
      * creation of the underlying stream can occur in a Java like way. Ex:
      *
      *  DataInputStream os = new DataInputStream( new InputStream(), true )
+     *
+     *  @since 1.0
      */
-    class DECAF_API DataInputStream : public FilterInputStream
-    {
+    class DECAF_API DataInputStream : public FilterInputStream {
+    private:
+
+        // Buffer used to store bytes read from the stream while reconstructed into
+        // higher order C++ primitives.
+        unsigned char buffer[8];
+
     public:
 
         /**
@@ -266,15 +274,22 @@
             throw ( io::IOException, io::EOFException );
 
         /**
-         * Reads a UTF8 encoded string in ASCII format and returns it, this is
-         * only useful if you know for sure that the string that is to be read
-         * was a string that contained all ascii values, and not uncide chars.
-         * @returns string read from stream.
+         * Reads a modified UTF-8 encoded string in ASCII format and returns it,
+         * this is only useful if you know for sure that the string that is to be read
+         * was a string that contained all ASCII values (0-255), if so this method will
+         * throw a UTFFormatException.  This method reads String value written from a
+         * Java DataOutputStream and assumes that the length prefix the precedes the
+         * encoded UTF-8 bytes is an unsigned short, which implies that the String will
+         * be no longer than 65535 characters.
+         *
+         * @returns The decoded string read from stream.
+         *
          * @throws IOException
          * @throws EOFException
+         * @throws UTFDataFormatException
          */
         virtual std::string readUTF()
-            throw ( io::IOException, io::EOFException );
+            throw ( io::IOException, io::EOFException, io::UTFDataFormatException );
 
         /**
          * Reads some bytes from an input stream and stores them into the

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.cpp?rev=764780&r1=764779&r2=764780&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.cpp (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.cpp Tue Apr 14 14:05:04 2009
@@ -16,6 +16,7 @@
  */
 
 #include <decaf/io/DataOutputStream.h>
+#include <decaf/io/UTFDataFormatException.h>
 #include <decaf/util/Config.h>
 #include <string.h>
 #include <stdio.h>
@@ -113,8 +114,8 @@
 ////////////////////////////////////////////////////////////////////////////////
 void DataOutputStream::writeBoolean( bool value ) throw ( IOException ) {
     try {
-        unsigned char ivalue = 0;
-        value == true ? ivalue = 1 : ivalue = 0;
+
+        value == true ? buffer[0] = 1 : buffer[0] = 0;
 
         if( outputStream == NULL ) {
             throw IOException(
@@ -122,7 +123,7 @@
                 "DataOutputStream::write - Base stream is Null");
         }
 
-        outputStream->write( ivalue );
+        outputStream->write( buffer[0] );
         written++;
     }
     DECAF_CATCH_RETHROW( IOException )
@@ -173,8 +174,6 @@
                 "DataOutputStream::write - Base stream is Null");
         }
 
-        unsigned char buffer[sizeof(value)];
-
         buffer[0] = (value & 0xFF00) >> 8;
         buffer[1] = (value & 0x00FF) >> 0;
 
@@ -197,8 +196,6 @@
                 "DataOutputStream::write - Base stream is Null");
         }
 
-        unsigned char buffer[sizeof(value)];
-
         buffer[0] = (value & 0xFF00) >> 8;
         buffer[1] = (value & 0x00FF) >> 0;
 
@@ -219,8 +216,6 @@
                 "DataOutputStream::write - Base stream is Null");
         }
 
-        unsigned char buffer[sizeof(value)];
-
         buffer[0] = (value & 0xFF000000) >> 24;
         buffer[1] = (value & 0x00FF0000) >> 16;
         buffer[2] = (value & 0x0000FF00) >> 8;
@@ -243,8 +238,6 @@
                 "DataOutputStream::write - Base stream is Null");
         }
 
-        unsigned char buffer[sizeof(value)];
-
         buffer[0] = (unsigned char)((value & 0xFF00000000000000ULL) >> 56);
         buffer[1] = (unsigned char)((value & 0x00FF000000000000ULL) >> 48);
         buffer[2] = (unsigned char)((value & 0x0000FF0000000000ULL) >> 40);
@@ -314,16 +307,72 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-void DataOutputStream::writeUTF( const std::string& value ) throw ( IOException ) {
+void DataOutputStream::writeUTF( const std::string& value )
+    throw ( IOException, UTFDataFormatException ) {
+
     try {
 
-        if( value.length() == 0 ) {
-            return;
+        unsigned int utfLength = this->countUTFLength( value );
+
+        if( utfLength > 65535 ) {
+            throw UTFDataFormatException(
+                __FILE__, __LINE__,
+                "Attempted to write a string as UTF-8 whose length is longer "
+                "than the supported 65535 bytes" );
         }
 
-        this->writeUnsignedShort( (unsigned short)value.length() );
-        this->write( (const unsigned char*)value.c_str(), 0, value.length() );
+        std::size_t length = value.length();
+        std::vector<unsigned char> utfBytes( (std::size_t)utfLength );
+        unsigned int utfIndex = 0;
+
+        for( std::size_t i = 0; i < length; i++ ) {
+
+            unsigned int charValue = (unsigned char)value.at( i );
+
+            // Written to allow for expansion to wide character strings at some
+            // point, as it stands now the value can never be > 255 since the
+            // string class returns a single byte char.
+            if( charValue > 0 && charValue <= 127 ) {
+                utfBytes[utfIndex++] = (unsigned char)charValue;
+            } else if( charValue <= 2047 ) {
+                utfBytes[utfIndex++] = (unsigned char)(0xc0 | (0x1f & (charValue >> 6)));
+                utfBytes[utfIndex++] = (unsigned char)(0x80 | (0x3f & charValue));
+            } else {
+                utfBytes[utfIndex++] = (unsigned char)(0xe0 | (0x0f & (charValue >> 12)));
+                utfBytes[utfIndex++] = (unsigned char)(0x80 | (0x3f & (charValue >> 6)));
+                utfBytes[utfIndex++] = (unsigned char)(0x80 | (0x3f & charValue));
+            }
+        }
+
+        this->writeUnsignedShort( (unsigned short)utfLength );
+        this->write( &utfBytes[0], 0, utfIndex );
     }
+    DECAF_CATCH_RETHROW( UTFDataFormatException )
     DECAF_CATCH_RETHROW( IOException )
     DECAF_CATCHALL_THROW( IOException )
 }
+
+////////////////////////////////////////////////////////////////////////////////
+unsigned int DataOutputStream::countUTFLength( const std::string& value ) {
+
+    unsigned int utfCount = 0;
+    std::size_t length = value.length();
+
+    for( std::size_t i = 0; i < length; ++i ) {
+
+        unsigned int charValue = (unsigned char)value.at( i );
+
+        // Written to allow for expansion to wide character strings at some
+        // point, as it stands now the value can never be > 255 since the
+        // string class returns a single byte char.
+        if( charValue > 0 && charValue <= 127 ) {
+            utfCount++;
+        } else if( charValue <= 2047 ) {
+            utfCount += 2;
+        } else {
+            utfCount += 3;
+        }
+    }
+
+    return utfCount;
+}

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.h?rev=764780&r1=764779&r2=764780&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.h (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/DataOutputStream.h Tue Apr 14 14:05:04 2009
@@ -19,6 +19,9 @@
 #define _DECAF_IO_DATAOUTPUTSTREAM_H_
 
 #include <decaf/io/FilterOutputStream.h>
+#include <decaf/io/IOException.h>
+#include <decaf/io/UTFDataFormatException.h>
+#include <string>
 
 namespace decaf{
 namespace io{
@@ -28,13 +31,15 @@
      * types to an output stream in a portable way. An application can then
      * use a data input stream to read the data back in.
      */
-    class DECAF_API DataOutputStream : public FilterOutputStream
-    {
+    class DECAF_API DataOutputStream : public FilterOutputStream {
     protected:
 
         // The number of bytes written to the data output stream so far.
         std::size_t written;
 
+        // Buffer used for storing byte values to write to the stream
+        unsigned char buffer[8];
+
     public:
 
         /**
@@ -190,20 +195,33 @@
          * characters. Each character is written to the data output stream
          * as if by the writeChar method. If no exception is thrown, the
          * counter written is incremented by the length of value.  The trailing
-         * NULL charactor is written by this method.
+         * NULL character is written by this method.
          * @param value the value to write.
          * @throws IOException
          */
         virtual void writeChars( const std::string& value ) throw ( IOException );
 
         /**
-         * Writes out the string to the underlying output stream as a
-         * unsigned short indicating its length followed by the rest of
-         * the string.
-         * @param value the value to write.
-         * @throws IOException
+         * Writes out the string to the underlying output stream as a modeified UTF-8
+         * encoded sequence of bytes.  The first two bytes written are indicate its
+         * encoded length followed by the rest of the string's characters encoded as
+         * modified UTF-8.  The length represent the encoded length of the data not the
+         * actual length of the string.
+         *
+         * @param value
+         *        the value to write.
+         *
+         * @throws IOException - on a write error
+         * @throws UTFDataFormatException - if encoded size if greater than 65535
          */
-        virtual void writeUTF( const std::string& value ) throw ( IOException );
+        virtual void writeUTF( const std::string& value )
+            throw ( IOException, UTFDataFormatException );
+
+    private:
+
+        // Determine the encoded length of a string when written as modified UTF-8
+        unsigned int countUTFLength( const std::string& value );
+
     };
 
 }}

Added: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/UTFDataFormatException.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/UTFDataFormatException.h?rev=764780&view=auto
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/UTFDataFormatException.h (added)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/UTFDataFormatException.h Tue Apr 14 14:05:04 2009
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+#ifndef _DECAF_IO_UTFDATAFORMATEXCEPTION_H_
+#define _DECAF_IO_UTFDATAFORMATEXCEPTION_H_
+
+#include <decaf/io/IOException.h>
+
+namespace decaf {
+namespace io {
+
+    /**
+     * Thrown from classes that attempt to read or write a UTF-8 encoded string
+     * and an encoding error is encountered.
+     *
+     * @since 1.0
+     */
+    class DECAF_API UTFDataFormatException : public decaf::io::IOException {
+    public:
+
+        /**
+         * Default Constructor
+         */
+        UTFDataFormatException() throw() {}
+
+        /**
+         * Copy Constructor
+         * @param ex the exception to copy
+         */
+        UTFDataFormatException( const lang::Exception& ex ) throw()
+        : IOException()
+        {
+            *(lang::Exception*)this = ex;
+        }
+
+        /**
+         * Copy Constructor
+         * @param ex the exception to copy, which is an instance of this type
+         */
+        UTFDataFormatException( const UTFDataFormatException& ex ) throw()
+        : IOException()
+        {
+            *(lang::Exception*)this = ex;
+        }
+
+        /**
+         * Constructor - Initializes the file name and line number where
+         * this message occurred.  Sets the message to report, using an
+         * optional list of arguments to parse into the message
+         * @param file name where exception occurs
+         * @param line number where the exception occurred.
+         * @param cause The exception that was the cause for this one to be thrown.
+         * @param message to report
+         * @param list of primitives that are formatted into the message
+         */
+        UTFDataFormatException( const char* file, const int lineNumber,
+                                const std::exception* cause,
+                                const char* msg, ... ) throw() : IOException( cause )
+        {
+            va_list vargs;
+            va_start( vargs, msg );
+            buildMessage( msg, vargs );
+
+            // Set the first mark for this exception.
+            setMark( file, lineNumber );
+        }
+
+        /**
+         * Constructor
+         * @param cause Pointer to the exception that caused this one to
+         * be thrown, the object is cloned caller retains ownership.
+         */
+        UTFDataFormatException( const std::exception* cause ) throw() : IOException( cause ) {}
+
+        /**
+         * Constructor
+         * @param file name of the file were the exception occurred.
+         * @param lineNumber line where the exception occurred
+         * @param msg the message that was generated
+         */
+        UTFDataFormatException( const char* file, const int lineNumber,
+                                const char* msg, ... ) throw()
+        : IOException()
+        {
+            va_list vargs;
+            va_start( vargs, msg );
+            buildMessage( msg, vargs );
+
+            // Set the first mark for this exception.
+            setMark( file, lineNumber );
+        }
+
+        /**
+         * Clones this exception.  This is useful for cases where you need
+         * to preserve the type of the original exception as well as the message.
+         * All subclasses should override.
+         */
+        virtual UTFDataFormatException* clone() const{
+            return new UTFDataFormatException( *this );
+        }
+
+        virtual ~UTFDataFormatException() throw() {}
+
+    };
+
+}}
+
+#endif /* _DECAF_IO_UTFDATAFORMATEXCEPTION_H_ */

Propchange: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/io/UTFDataFormatException.h
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.cpp?rev=764780&r1=764779&r2=764780&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.cpp (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.cpp Tue Apr 14 14:05:04 2009
@@ -23,6 +23,7 @@
 #include <decaf/io/ByteArrayOutputStream.h>
 #include <decaf/io/DataInputStream.h>
 #include <decaf/io/DataOutputStream.h>
+#include <decaf/lang/Integer.h>
 
 using namespace std;
 using namespace decaf;
@@ -33,102 +34,195 @@
 using namespace activemq::wireformat::openwire;
 using namespace activemq::wireformat::openwire::utils;
 
-
 ////////////////////////////////////////////////////////////////////////////////
-void OpenwireStringSupportTest::testHelper( unsigned char* input, int inputLength,
-                                            unsigned char* output, int outputLength,
-                                            bool negative ) {
-    try {
-
-        ByteArrayInputStream bytesIn;
-        ByteArrayOutputStream bytesOut;
-
-        DataInputStream dataIn( &bytesIn );
-        DataOutputStream dataOut( &bytesOut );
-
-        bytesIn.setByteArray( input, inputLength );
-
-        string resultStr = OpenwireStringSupport::readString( dataIn );
-        if( !negative ) {
-            CPPUNIT_ASSERT( resultStr == std::string( (char*)output, outputLength ) );
-
-            OpenwireStringSupport::writeString( dataOut, &resultStr );
-            CPPUNIT_ASSERT( bytesOut.toString() == std::string( (char*)input, inputLength ) );
-        } else {
-            CPPUNIT_ASSERT( 0 );
-        }
+void OpenwireStringSupportTest::writeTestHelper( unsigned char* input, int inputLength,
+                                                 unsigned char* expect, int expectLength ) {
+
+    ByteArrayOutputStream baos;
+    DataOutputStream writer( &baos );
+
+    std::string testStr( (char*)input, inputLength );
+    OpenwireStringSupport::writeString( writer, &testStr );
+
+    const unsigned char* result = baos.toByteArray();
+
+    CPPUNIT_ASSERT( result[0] == 0x00 );
+    CPPUNIT_ASSERT( result[1] == 0x00 );
+    CPPUNIT_ASSERT( result[2] == 0x00 );
+    CPPUNIT_ASSERT( result[3] == (unsigned char)( expectLength ) );
 
-    } catch( Exception& e ) {
-        CPPUNIT_ASSERT( negative );
+    for( std::size_t i = 4; i < baos.size(); ++i ) {
+        CPPUNIT_ASSERT( result[i] == expect[i-4] );
     }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-void OpenwireStringSupportTest::test()
-{
-    ByteArrayInputStream bytesIn;
-    ByteArrayOutputStream bytesOut;
+void OpenwireStringSupportTest::testWriteString() {
 
-    DataInputStream dataIn( &bytesIn );
-    DataOutputStream dataOut( &bytesOut );
+    // Test data with 1-byte UTF8 encoding.
+    {
+        unsigned char input[] = {0x00, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64};
+        unsigned char expect[] = {0xC0, 0x80, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64};
 
-    string testStr = "This is a test string for Openwire";
+        writeTestHelper( input, sizeof(input)/sizeof(unsigned char),
+                         expect, sizeof(expect)/sizeof(unsigned char) );
+    }
 
-    OpenwireStringSupport::writeString( dataOut, &testStr );
+    // Test data with 2-byte UT8 encoding.
+    {
+        unsigned char input[] = {0x00, 0xC2, 0xA9, 0xC3, 0xA6 };
+        unsigned char expect[] = {0xC0, 0x80, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC2, 0xA6 };
+        writeTestHelper( input, sizeof(input)/sizeof(unsigned char),
+                         expect, sizeof(expect)/sizeof(unsigned char)  );
+    }
 
-    // Move the output back to the input.
-    bytesIn.setByteArray( bytesOut.toByteArray(), bytesOut.size() );
+    // Test data with 1-byte and 2-byte encoding with embedded NULL's.
+    {
+        unsigned char input[] = {0x00, 0x04, 0xC2, 0xA9, 0xC3, 0x00, 0xA6 };
+        unsigned char expect[] = {0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
 
-    string resultStr = OpenwireStringSupport::readString( dataIn );
+        writeTestHelper( input, sizeof(input)/sizeof(unsigned char),
+                         expect, sizeof(expect)/sizeof(unsigned char) );
+    }
 
-    CPPUNIT_ASSERT( testStr == resultStr );
+    // Test data with 1-byte and 2-byte encoding with embedded NULL's.
+    {
+        ByteArrayOutputStream baos;
+        ByteArrayInputStream bais;
+        DataOutputStream writer( &baos );
+        DataInputStream dataIn( &bais );
+
+        OpenwireStringSupport::writeString( writer, NULL );
+
+        bais.setByteArray( baos.toByteArray(), baos.size() );
+
+        CPPUNIT_ASSERT( dataIn.readInt() == -1 );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void OpenwireStringSupportTest::readTestHelper( unsigned char* input, int inputLength,
+                                                unsigned char* expect, int expectLength ) {
+
+    ByteArrayInputStream myStream( input, inputLength );
+    DataInputStream reader( &myStream );
+
+    std::string result = reader.readUTF();
+
+    for( std::size_t i; i < result.length(); ++i ) {
+        CPPUNIT_ASSERT( (unsigned char)result[i] == expect[i] );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void OpenwireStringSupportTest::testReadString() {
 
     // Test data with 1-byte UTF8 encoding.
     {
-        unsigned char input[] = {0x00, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64};
-        unsigned char output[] = {0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64};
+        unsigned char expect[] = {0x00, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64};
+        unsigned char input[] = { 0x00, 0x00, 0x00, 0x0E ,0xC0, 0x80, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64};
 
-        testHelper( input, sizeof(input)/sizeof(unsigned char),
-                    output, sizeof(output)/sizeof(unsigned char), false );
+        readTestHelper( input, sizeof(input)/sizeof(unsigned char),
+                        expect, sizeof(expect)/sizeof(unsigned char) );
     }
 
     // Test data with 2-byte UT8 encoding.
     {
-        unsigned char input[] = {0x00, 0x04, 0xC2, 0xA9, 0xC3, 0xA6};
-        unsigned char output[] = {0xA9, 0xE6};
-        testHelper( input, sizeof(input)/sizeof(unsigned char),
-                    output, sizeof(output)/sizeof(unsigned char), false );
+        unsigned char expect[] = {0x00, 0xC2, 0xA9, 0xC3, 0xA6 };
+        unsigned char input[] = { 0x00, 0x00, 0x00, 0x0A, 0xC0, 0x80, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC2, 0xA6 };
+        readTestHelper( input, sizeof(input)/sizeof(unsigned char),
+                        expect, sizeof(expect)/sizeof(unsigned char)  );
     }
 
-    // Test data with value greater than 255 in 2-byte encoding.
-    // Expect : IO Exception
+    // Test data with 1-byte and 2-byte encoding with embedded NULL's.
     {
-        unsigned char input[] = {0x00, 0x04, 0xC8, 0xA9, 0xC3, 0xA6};
-        testHelper( input, sizeof(input)/sizeof(unsigned char), NULL, 0, true );
+        unsigned char expect[] = {0x00, 0x04, 0xC2, 0xA9, 0xC3, 0x00, 0xA6 };
+        unsigned char input[] = { 0x00, 0x00, 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
+
+        readTestHelper( input, sizeof(input)/sizeof(unsigned char),
+                        expect, sizeof(expect)/sizeof(unsigned char) );
     }
 
-    // Test data with value greater than 255 in 3-byte encoding.
-    // Expect : IO Exception
+    // Test with bad UTF-8 encoding, missing 2nd byte of two byte value
     {
-        unsigned char input[] = {0x00, 0x05, 0xE8, 0xA8, 0xA9, 0xC3, 0xA6};
-        testHelper( input, sizeof(input)/sizeof(unsigned char), NULL, 0, true );
+        unsigned char input[] = { 0x00, 0x00, 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xC2, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
+
+        ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) );
+        DataInputStream reader( &myStream );
+
+        CPPUNIT_ASSERT_THROW_MESSAGE(
+            "Should throw a IOException",
+            OpenwireStringSupport::readString( reader ),
+            IOException );
     }
 
-    // Test data with 1-byte encoding with embedded NULL's.
+    // Test with bad UTF-8 encoding, encoded value greater than 255
     {
-        unsigned char input[] = {0x00, 0x0D, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x00, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x00};
-        unsigned char output[] = {0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x00, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x00};
+        unsigned char input[] = { 0x00, 0x00, 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xC2, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
+
+        ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) );
+        DataInputStream reader( &myStream );
 
-        testHelper( input, sizeof(input)/sizeof(unsigned char),
-                    output, sizeof(output)/sizeof(unsigned char), false );
+        CPPUNIT_ASSERT_THROW_MESSAGE(
+            "Should throw a IOException",
+            OpenwireStringSupport::readString( reader ),
+            IOException );
     }
 
-    // Test data with 1-byte and 2-byte encoding with embedded NULL's.
+    // Test data with value greater than 255 in 2-byte encoding.
     {
-        unsigned char input[] = {0x00, 0x11, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x00, 0xC2, 0xA9, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x00, 0xC3, 0xA6};
-        unsigned char output[] = {0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x00, 0xA9, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x00, 0xE6};
+        unsigned char input[] = { 0x00, 0x00, 0x00, 0x04, 0xC8, 0xA9, 0xC3, 0xA6};
+        ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) );
+        DataInputStream reader( &myStream );
+
+        CPPUNIT_ASSERT_THROW_MESSAGE(
+            "Should throw a IOException",
+            OpenwireStringSupport::readString( reader ),
+            IOException );
+    }
 
-        testHelper( input, sizeof(input)/sizeof(unsigned char),
-                    output, sizeof(output)/sizeof(unsigned char), false );
+    // Test data with value greater than 255 in 3-byte encoding.
+    {
+        unsigned char input[] = { 0x00, 0x00, 0x00, 0x05, 0xE8, 0xA8, 0xA9, 0xC3, 0xA6};
+        ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) );
+        DataInputStream reader( &myStream );
+
+        CPPUNIT_ASSERT_THROW_MESSAGE(
+            "Should throw a IOException",
+            OpenwireStringSupport::readString( reader ),
+            IOException );
+    }
+
+    // Test with three byte encode that's missing a last byte.
+    {
+        unsigned char input[] = { 0x00, 0x00, 0x00, 0x02, 0xE8, 0xA8};
+        ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) );
+        DataInputStream reader( &myStream );
+
+        CPPUNIT_ASSERT_THROW_MESSAGE(
+            "Should throw a IOException",
+            OpenwireStringSupport::readString( reader ),
+            IOException );
     }
 }
+
+////////////////////////////////////////////////////////////////////////////////
+void OpenwireStringSupportTest::test() {
+
+    ByteArrayInputStream bytesIn;
+    ByteArrayOutputStream bytesOut;
+
+    DataInputStream dataIn( &bytesIn );
+    DataOutputStream dataOut( &bytesOut );
+
+    string testStr = "This is a test string for Openwire";
+
+    OpenwireStringSupport::writeString( dataOut, &testStr );
+
+    // Move the output back to the input.
+    bytesIn.setByteArray( bytesOut.toByteArray(), bytesOut.size() );
+
+    string resultStr = OpenwireStringSupport::readString( dataIn );
+
+    CPPUNIT_ASSERT( testStr == resultStr );
+}

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.h?rev=764780&r1=764779&r2=764780&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.h (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/activemq/wireformat/openwire/utils/OpenwireStringSupportTest.h Tue Apr 14 14:05:04 2009
@@ -30,6 +30,8 @@
 
         CPPUNIT_TEST_SUITE( OpenwireStringSupportTest );
         CPPUNIT_TEST( test );
+        CPPUNIT_TEST( testWriteString );
+        CPPUNIT_TEST( testReadString );
         CPPUNIT_TEST_SUITE_END();
 
     public:
@@ -39,8 +41,16 @@
 
         void test();
 
-        void testHelper( unsigned char* input, int inputLength,
-                         unsigned char* output, int outputLength, bool negative );
+        void testWriteString();
+        void testReadString();
+
+    private:
+
+        void readTestHelper( unsigned char* input, int inputLength,
+                             unsigned char* expect, int expectLength );
+
+        void writeTestHelper( unsigned char* input, int inputLength,
+                              unsigned char* expect, int expectLength );
 
     };
 

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.cpp?rev=764780&r1=764779&r2=764780&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.cpp (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.cpp Tue Apr 14 14:05:04 2009
@@ -516,3 +516,110 @@
         CPPUNIT_ASSERT( true );
     }
 }
+
+////////////////////////////////////////////////////////////////////////////////
+void DataInputStreamTest::testHelper( unsigned char* input, int inputLength,
+                                      unsigned char* expect, int expectLength ) {
+
+    ByteArrayInputStream myStream( input, inputLength );
+    DataInputStream reader( &myStream );
+
+    std::string result = reader.readUTF();
+
+    for( std::size_t i; i < result.length(); ++i ) {
+        CPPUNIT_ASSERT( (unsigned char)result[i] == expect[i] );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void DataInputStreamTest::testUTFDecoding() {
+
+    // Test data with 1-byte UTF8 encoding.
+    {
+        unsigned char expect[] = {0x00, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64};
+        unsigned char input[] = { 0x00, 0x0E ,0xC0, 0x80, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64};
+
+        testHelper( input, sizeof(input)/sizeof(unsigned char),
+                    expect, sizeof(expect)/sizeof(unsigned char) );
+    }
+
+    // Test data with 2-byte UT8 encoding.
+    {
+        unsigned char expect[] = {0x00, 0xC2, 0xA9, 0xC3, 0xA6 };
+        unsigned char input[] = { 0x00, 0x0A, 0xC0, 0x80, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC2, 0xA6 };
+        testHelper( input, sizeof(input)/sizeof(unsigned char),
+                    expect, sizeof(expect)/sizeof(unsigned char)  );
+    }
+
+    // Test data with 1-byte and 2-byte encoding with embedded NULL's.
+    {
+        unsigned char expect[] = {0x00, 0x04, 0xC2, 0xA9, 0xC3, 0x00, 0xA6 };
+        unsigned char input[] = { 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
+
+        testHelper( input, sizeof(input)/sizeof(unsigned char),
+                    expect, sizeof(expect)/sizeof(unsigned char) );
+    }
+
+    // Test with bad UTF-8 encoding, missing 2nd byte of two byte value
+    {
+        unsigned char input[] = { 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xC2, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
+
+        ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) );
+        DataInputStream reader( &myStream );
+
+        CPPUNIT_ASSERT_THROW_MESSAGE(
+            "Should throw a UTFDataFormatException",
+            reader.readUTF(),
+            UTFDataFormatException );
+    }
+
+    // Test with bad UTF-8 encoding, encoded value greater than 255
+    {
+        unsigned char input[] = { 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xC2, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
+
+        ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) );
+        DataInputStream reader( &myStream );
+
+        CPPUNIT_ASSERT_THROW_MESSAGE(
+            "Should throw a UTFDataFormatException",
+            reader.readUTF(),
+            UTFDataFormatException );
+    }
+
+    // Test data with value greater than 255 in 2-byte encoding.
+    {
+        unsigned char input[] = {0x00, 0x04, 0xC8, 0xA9, 0xC3, 0xA6};
+        ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) );
+        DataInputStream reader( &myStream );
+
+        CPPUNIT_ASSERT_THROW_MESSAGE(
+            "Should throw a UTFDataFormatException",
+            reader.readUTF(),
+            UTFDataFormatException );
+    }
+
+    // Test data with value greater than 255 in 3-byte encoding.
+    {
+        unsigned char input[] = {0x00, 0x05, 0xE8, 0xA8, 0xA9, 0xC3, 0xA6};
+        ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) );
+        DataInputStream reader( &myStream );
+
+        CPPUNIT_ASSERT_THROW_MESSAGE(
+            "Should throw a UTFDataFormatException",
+            reader.readUTF(),
+            UTFDataFormatException );
+    }
+
+    // Test with three byte encode that's missing a last byte.
+    {
+        unsigned char input[] = {0x00, 0x02, 0xE8, 0xA8};
+        ByteArrayInputStream myStream( input, sizeof(input)/sizeof(unsigned char) );
+        DataInputStream reader( &myStream );
+
+        CPPUNIT_ASSERT_THROW_MESSAGE(
+            "Should throw a UTFDataFormatException",
+            reader.readUTF(),
+            UTFDataFormatException );
+    }
+
+}

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.h?rev=764780&r1=764779&r2=764780&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.h (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataInputStreamTest.h Tue Apr 14 14:05:04 2009
@@ -28,6 +28,7 @@
 #include <decaf/io/DataInputStream.h>
 #include <decaf/io/DataOutputStream.h>
 #include <algorithm>
+#include <memory>
 
 namespace decaf{
 namespace io{
@@ -38,6 +39,7 @@
         CPPUNIT_TEST( test );
         CPPUNIT_TEST( testString );
         CPPUNIT_TEST( testUTF );
+        CPPUNIT_TEST( testUTFDecoding );
         CPPUNIT_TEST( testConstructor );
         CPPUNIT_TEST( testRead1 );
         CPPUNIT_TEST( testRead2 );
@@ -59,11 +61,11 @@
         CPPUNIT_TEST( test_skipBytes );
         CPPUNIT_TEST_SUITE_END();
 
-        ByteArrayOutputStream* baos;
-        ByteArrayInputStream* bais;
+        std::auto_ptr<ByteArrayOutputStream> baos;
+        std::auto_ptr<ByteArrayInputStream> bais;
 
-        DataOutputStream* os;
-        DataInputStream* is;
+        std::auto_ptr<DataOutputStream> os;
+        std::auto_ptr<DataInputStream> is;
 
         std::string testData;
 
@@ -72,23 +74,22 @@
         virtual ~DataInputStreamTest(){}
         virtual void setUp(){
             testData = "Test_All_Tests\nTest_decaf_io_BufferedInputStream\nTest_BufferedOutputStream\nTest_decaf_io_ByteArrayInputStream\nTest_decaf_io_ByteArrayOutputStream\nTest_decaf_io_DataInputStream\nTest_decaf_io_File\nTest_decaf_io_FileDescriptor\nTest_decaf_io_FileInputStream\nTest_decaf_io_FileNotFoundException\nTest_decaf_io_FileOutputStream\nTest_decaf_io_FilterInputStream\nTest_decaf_io_FilterOutputStream\nTest_decaf_io_InputStream\nTest_decaf_io_IOException\nTest_decaf_io_OutputStream\nTest_decaf_io_PrintStream\nTest_decaf_io_RandomAccessFile\nTest_decaf_io_SyncFailedException\nTest_decaf_lang_AbstractMethodError\nTest_decaf_lang_ArithmeticException\nTest_decaf_lang_ArrayIndexOutOfBoundsException\nTest_decaf_lang_ArrayStoreException\nTest_decaf_lang_Boolean\nTest_decaf_lang_Byte\nTest_decaf_lang_Character\nTest_decaf_lang_Class\nTest_decaf_lang_ClassCastException\nTest_decaf_lang_ClassCircularityError\nTest_decaf_lang_ClassFormatError\nTest_decaf_lang_ClassLoad
 er\nTest_decaf_lang_ClassNotFoundException\nTest_decaf_lang_CloneNotSupportedException\nTest_decaf_lang_Double\nTest_decaf_lang_Error\nTest_decaf_lang_Exception\nTest_decaf_lang_ExceptionInInitializerError\nTest_decaf_lang_Float\nTest_decaf_lang_IllegalAccessError\nTest_decaf_lang_IllegalAccessException\nTest_decaf_lang_IllegalArgumentException\nTest_decaf_lang_IllegalMonitorStateException\nTest_decaf_lang_IllegalThreadStateException\nTest_decaf_lang_IncompatibleClassChangeError\nTest_decaf_lang_IndexOutOfBoundsException\nTest_decaf_lang_InstantiationError\nTest_decaf_lang_InstantiationException\nTest_decaf_lang_Integer\nTest_decaf_lang_InternalError\nTest_decaf_lang_InterruptedException\nTest_decaf_lang_LinkageError\nTest_decaf_lang_Long\nTest_decaf_lang_Math\nTest_decaf_lang_NegativeArraySizeException\nTest_decaf_lang_NoClassDefFoundError\nTest_decaf_lang_NoSuchFieldError\nTest_decaf_lang_NoSuchMethodError\nTest_decaf_lang_NullPointerException\nTest_decaf_lang_Number\nTest
 _decaf_lang_NumberFormatException\nTest_decaf_lang_Object\nTest_decaf_lang_OutOfMemoryError\nTest_decaf_lang_RuntimeException\nTest_decaf_lang_SecurityManager\nTest_decaf_lang_Short\nTest_decaf_lang_StackOverflowError\nTest_decaf_lang_String\nTest_decaf_lang_StringBuffer\nTest_decaf_lang_StringIndexOutOfBoundsException\nTest_decaf_lang_System\nTest_decaf_lang_Thread\nTest_decaf_lang_ThreadDeath\nTest_decaf_lang_ThreadGroup\nTest_decaf_lang_Throwable\nTest_decaf_lang_UnknownError\nTest_decaf_lang_UnsatisfiedLinkError\nTest_decaf_lang_VerifyError\nTest_decaf_lang_VirtualMachineError\nTest_decaf_lang_vm_Image\nTest_decaf_lang_vm_MemorySegment\nTest_decaf_lang_vm_ROMStoreException\nTest_decaf_lang_vm_VM\nTest_decaf_lang_Void\nTest_decaf_net_BindException\nTest_decaf_net_ConnectException\nTest_decaf_net_DatagramPacket\nTest_decaf_net_DatagramSocket\nTest_decaf_net_DatagramSocketImpl\nTest_decaf_net_InetAddress\nTest_decaf_net_NoRouteToHostException\nTest_decaf_net_PlainDatagramSo
 cketImpl\nTest_decaf_net_PlainSocketImpl\nTest_decaf_net_Socket\nTest_decaf_net_SocketException\nTest_decaf_net_SocketImpl\nTest_decaf_net_SocketInputStream\nTest_decaf_net_SocketOutputStream\nTest_decaf_net_UnknownHostException\nTest_decaf_util_ArrayEnumerator\nTest_decaf_util_Date\nTest_decaf_util_EventObject\nTest_decaf_util_HashEnumerator\nTest_decaf_util_Hashtable\nTest_decaf_util_Properties\nTest_decaf_util_ResourceBundle\nTest_decaf_util_tm\nTest_decaf_util_Vector\n";
-            baos = new ByteArrayOutputStream();
-            os = new DataOutputStream( baos );
-            is = NULL;
-            bais = NULL;
+            this->baos.reset( new ByteArrayOutputStream() );
+            this->os.reset( new DataOutputStream( baos.get() ) );
         }
         virtual void tearDown(){
             try {
-                delete os;
-                delete baos;
-                delete is;
-                delete bais;
+                this->os.reset( NULL );
+                this->baos.reset( NULL );
+                this->is.reset( NULL );
+                this->bais.reset( NULL );
             } catch(...) {}
         }
 
         void test();
         void testString();
         void testUTF();
+        void testUTFDecoding();
         void testConstructor();
         void testRead1();
         void testRead2();
@@ -111,12 +112,12 @@
 
     private:
 
-        void openDataInputStream() {
-            delete bais;
-            delete is;
+        void testHelper( unsigned char* input, int inputLength,
+                         unsigned char* expect, int expectLength );
 
-            bais = new ByteArrayInputStream( baos->toByteArray(), baos->size() );
-            is = new DataInputStream( bais );
+        void openDataInputStream() {
+            this->bais.reset( new ByteArrayInputStream( baos->toByteArray(), baos->size() ) );
+            this->is.reset( new DataInputStream( bais.get() ) );
         }
 
     };

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.cpp?rev=764780&r1=764779&r2=764780&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.cpp (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.cpp Tue Apr 14 14:05:04 2009
@@ -251,6 +251,95 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+void DataOutputStreamTest::testWriteUTFStringLength() {
+
+    // String of length 65536 of Null Characters.
+    // Expect: UTFDataFormatException.
+    std::string testStr( 65536, char('a') );
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Should throw a UTFDataFormatException",
+        os->writeUTF( testStr ),
+        UTFDataFormatException );
+
+    baos->reset();
+    // String of length 65535 of non Null Characters since Null encodes as UTF-8.
+    // Expect: Success.
+    testStr.resize( 65535 );
+    CPPUNIT_ASSERT_NO_THROW_MESSAGE(
+        "String of 65535 Non-Null chars should not throw.",
+        os->writeUTF( testStr ) );
+
+    baos->reset();
+    // Set one of the 65535 bytes to a value that will result in a 2 byte UTF8 encoded sequence.
+    // This will cause the string of length 65535 to have a utf length of 65536.
+    // Expect: UTFDataFormatException.
+    testStr[0] = char( 255 );
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Should throw an UTFDataFormatException",
+        os->writeUTF( testStr ),
+        UTFDataFormatException );
+
+    // Test that a zero length string write the zero size marker.
+    ByteArrayInputStream byteIn;
+    ByteArrayOutputStream byteOut;
+    DataInputStream dataIn( &byteIn );
+    DataOutputStream dataOut( &byteOut );
+    dataOut.writeUTF( "" );
+    CPPUNIT_ASSERT( dataOut.size() == 2 );
+    byteIn.setByteArray( byteOut.toByteArray(), byteOut.size() );
+    CPPUNIT_ASSERT( dataIn.readUnsignedShort() == 0 );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void DataOutputStreamTest::testHelper( unsigned char* input, int inputLength,
+                                       unsigned char* expect, int expectLength ) {
+
+    std::string testStr( (char*)input, inputLength );
+    os->writeUTF( testStr );
+
+    const unsigned char* result = baos->toByteArray();
+
+    CPPUNIT_ASSERT( result[0] == 0x00 );
+    CPPUNIT_ASSERT( result[1] == (unsigned char)( expectLength ) );
+
+    for( std::size_t i = 2; i < baos->size(); ++i ) {
+        CPPUNIT_ASSERT( result[i] == expect[i-2] );
+    }
+
+    baos->reset();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void DataOutputStreamTest::testWriteUTFEncoding() {
+
+    // Test data with 1-byte UTF8 encoding.
+    {
+        unsigned char input[] = {0x00, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64};
+        unsigned char expect[] = {0xC0, 0x80, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64};
+
+        testHelper( input, sizeof(input)/sizeof(unsigned char),
+                    expect, sizeof(expect)/sizeof(unsigned char) );
+    }
+
+    // Test data with 2-byte UT8 encoding.
+    {
+        unsigned char input[] = {0x00, 0xC2, 0xA9, 0xC3, 0xA6 };
+        unsigned char expect[] = {0xC0, 0x80, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC2, 0xA6 };
+        testHelper( input, sizeof(input)/sizeof(unsigned char),
+                    expect, sizeof(expect)/sizeof(unsigned char)  );
+    }
+
+    // Test data with 1-byte and 2-byte encoding with embedded NULL's.
+    {
+        unsigned char input[] = {0x00, 0x04, 0xC2, 0xA9, 0xC3, 0x00, 0xA6 };
+        unsigned char expect[] = {0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
+
+        testHelper( input, sizeof(input)/sizeof(unsigned char),
+                    expect, sizeof(expect)/sizeof(unsigned char) );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
 void DataOutputStreamTest::test(){
 
     unsigned char byteVal = (unsigned char)'T';

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.h?rev=764780&r1=764779&r2=764780&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.h (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/io/DataOutputStreamTest.h Tue Apr 14 14:05:04 2009
@@ -26,6 +26,7 @@
 #include <decaf/io/DataInputStream.h>
 #include <decaf/io/ByteArrayOutputStream.h>
 #include <decaf/io/ByteArrayInputStream.h>
+#include <memory>
 
 namespace decaf{
 namespace io{
@@ -49,13 +50,15 @@
         CPPUNIT_TEST( testWriteLong );
         CPPUNIT_TEST( testWriteShort );
         CPPUNIT_TEST( testWriteUTF );
+        CPPUNIT_TEST( testWriteUTFStringLength );
+        CPPUNIT_TEST( testWriteUTFEncoding );
         CPPUNIT_TEST_SUITE_END();
 
-        ByteArrayOutputStream* baos;
-        ByteArrayInputStream* bais;
+        std::auto_ptr<ByteArrayOutputStream> baos;
+        std::auto_ptr<ByteArrayInputStream> bais;
 
-        DataOutputStream* os;
-        DataInputStream* is;
+        std::auto_ptr<DataOutputStream> os;
+        std::auto_ptr<DataInputStream> is;
 
         std::string testData;
 
@@ -64,17 +67,15 @@
         virtual ~DataOutputStreamTest(){}
         virtual void setUp(){
             testData = "Test_All_Tests\nTest_decaf_io_BufferedInputStream\nTest_BufferedOutputStream\nTest_decaf_io_ByteArrayInputStream\nTest_decaf_io_ByteArrayOutputStream\nTest_decaf_io_DataInputStream\nTest_decaf_io_File\nTest_decaf_io_FileDescriptor\nTest_decaf_io_FileInputStream\nTest_decaf_io_FileNotFoundException\nTest_decaf_io_FileOutputStream\nTest_decaf_io_FilterInputStream\nTest_decaf_io_FilterOutputStream\nTest_decaf_io_InputStream\nTest_decaf_io_IOException\nTest_decaf_io_OutputStream\nTest_decaf_io_PrintStream\nTest_decaf_io_RandomAccessFile\nTest_decaf_io_SyncFailedException\nTest_decaf_lang_AbstractMethodError\nTest_decaf_lang_ArithmeticException\nTest_decaf_lang_ArrayIndexOutOfBoundsException\nTest_decaf_lang_ArrayStoreException\nTest_decaf_lang_Boolean\nTest_decaf_lang_Byte\nTest_decaf_lang_Character\nTest_decaf_lang_Class\nTest_decaf_lang_ClassCastException\nTest_decaf_lang_ClassCircularityError\nTest_decaf_lang_ClassFormatError\nTest_decaf_lang_ClassLoad
 er\nTest_decaf_lang_ClassNotFoundException\nTest_decaf_lang_CloneNotSupportedException\nTest_decaf_lang_Double\nTest_decaf_lang_Error\nTest_decaf_lang_Exception\nTest_decaf_lang_ExceptionInInitializerError\nTest_decaf_lang_Float\nTest_decaf_lang_IllegalAccessError\nTest_decaf_lang_IllegalAccessException\nTest_decaf_lang_IllegalArgumentException\nTest_decaf_lang_IllegalMonitorStateException\nTest_decaf_lang_IllegalThreadStateException\nTest_decaf_lang_IncompatibleClassChangeError\nTest_decaf_lang_IndexOutOfBoundsException\nTest_decaf_lang_InstantiationError\nTest_decaf_lang_InstantiationException\nTest_decaf_lang_Integer\nTest_decaf_lang_InternalError\nTest_decaf_lang_InterruptedException\nTest_decaf_lang_LinkageError\nTest_decaf_lang_Long\nTest_decaf_lang_Math\nTest_decaf_lang_NegativeArraySizeException\nTest_decaf_lang_NoClassDefFoundError\nTest_decaf_lang_NoSuchFieldError\nTest_decaf_lang_NoSuchMethodError\nTest_decaf_lang_NullPointerException\nTest_decaf_lang_Number\nTest
 _decaf_lang_NumberFormatException\nTest_decaf_lang_Object\nTest_decaf_lang_OutOfMemoryError\nTest_decaf_lang_RuntimeException\nTest_decaf_lang_SecurityManager\nTest_decaf_lang_Short\nTest_decaf_lang_StackOverflowError\nTest_decaf_lang_String\nTest_decaf_lang_StringBuffer\nTest_decaf_lang_StringIndexOutOfBoundsException\nTest_decaf_lang_System\nTest_decaf_lang_Thread\nTest_decaf_lang_ThreadDeath\nTest_decaf_lang_ThreadGroup\nTest_decaf_lang_Throwable\nTest_decaf_lang_UnknownError\nTest_decaf_lang_UnsatisfiedLinkError\nTest_decaf_lang_VerifyError\nTest_decaf_lang_VirtualMachineError\nTest_decaf_lang_vm_Image\nTest_decaf_lang_vm_MemorySegment\nTest_decaf_lang_vm_ROMStoreException\nTest_decaf_lang_vm_VM\nTest_decaf_lang_Void\nTest_decaf_net_BindException\nTest_decaf_net_ConnectException\nTest_decaf_net_DatagramPacket\nTest_decaf_net_DatagramSocket\nTest_decaf_net_DatagramSocketImpl\nTest_decaf_net_InetAddress\nTest_decaf_net_NoRouteToHostException\nTest_decaf_net_PlainDatagramSo
 cketImpl\nTest_decaf_net_PlainSocketImpl\nTest_decaf_net_Socket\nTest_decaf_net_SocketException\nTest_decaf_net_SocketImpl\nTest_decaf_net_SocketInputStream\nTest_decaf_net_SocketOutputStream\nTest_decaf_net_UnknownHostException\nTest_decaf_util_ArrayEnumerator\nTest_decaf_util_Date\nTest_decaf_util_EventObject\nTest_decaf_util_HashEnumerator\nTest_decaf_util_Hashtable\nTest_decaf_util_Properties\nTest_decaf_util_ResourceBundle\nTest_decaf_util_tm\nTest_decaf_util_Vector\n";
-            baos = new ByteArrayOutputStream();
-            os = new DataOutputStream( baos );
-            is = NULL;
-            bais = NULL;
+            this->baos.reset( new ByteArrayOutputStream() );
+            this->os.reset( new DataOutputStream( baos.get() ) );
         }
         virtual void tearDown(){
             try {
-                delete os;
-                delete baos;
-                delete is;
-                delete bais;
+                os.reset( NULL );
+                baos.reset( NULL );
+                is.reset( NULL );
+                bais.reset( NULL );
             } catch(...) {}
         }
 
@@ -94,12 +95,17 @@
         void testWriteLong();
         void testWriteShort();
         void testWriteUTF();
+        void testWriteUTFStringLength();
+        void testWriteUTFEncoding();
 
     private:
 
+        void testHelper( unsigned char* input, int inputLength,
+                         unsigned char* expect, int expectLength );
+
         void openDataInputStream() {
-            bais = new ByteArrayInputStream( baos->toByteArray(), baos->size() );
-            is = new DataInputStream( bais );
+            this->bais.reset( new ByteArrayInputStream( baos->toByteArray(), baos->size() ) );
+            this->is.reset( new DataInputStream( bais.get() ) );
         }
 
     };