activemq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tab...@apache.org
Subject svn commit: r905418 - in /activemq/activemq-cpp/trunk/activemq-cpp/src: main/decaf/util/Properties.cpp main/decaf/util/Properties.h test/decaf/util/PropertiesTest.cpp test/decaf/util/PropertiesTest.h
Date Mon, 01 Feb 2010 21:32:39 GMT
Author: tabish
Date: Mon Feb  1 21:32:39 2010
New Revision: 905418

URL: http://svn.apache.org/viewvc?rev=905418&view=rev
Log:
Updated Properties class with added propertyNames method and implementation for load / store
added tests for the new code.

Modified:
    activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Properties.cpp
    activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Properties.h
    activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/PropertiesTest.cpp
    activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/PropertiesTest.h

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Properties.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Properties.cpp?rev=905418&r1=905417&r2=905418&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Properties.cpp (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Properties.cpp Mon Feb  1
21:32:39 2010
@@ -20,8 +20,12 @@
 #include <map>
 #include <sstream>
 #include <decaf/util/Date.h>
-#include <decaf/lang/exceptions/UnsupportedOperationException.h>
+#include <decaf/util/Map.h>
 #include <decaf/util/StlMap.h>
+#include <decaf/io/BufferedInputStream.h>
+#include <decaf/lang/Character.h>
+#include <decaf/lang/Integer.h>
+#include <decaf/lang/exceptions/UnsupportedOperationException.h>
 
 using namespace decaf;
 using namespace decaf::util;
@@ -45,14 +49,64 @@
 ////////////////////////////////////////////////////////////////////////////////
 namespace {
 
-    enum TokenState {
+    /**
+     * internal namespace for Properties utility methods, these might change often
+     * so we hide them in here to preserve ABI rules on the header.
+     */
+
+    enum ParsingMode {
         NONE = 0,
         SLASH = 1,
         CONTINUE = 2,
         KEY_DONE = 3,
-        IGNOE = 4
+        IGNORE = 4
     };
 
+    void dumpString( std::ostringstream& buffer, const std::string& string, bool
key ) {
+
+        std::size_t i = 0;
+        if( !key && i < string.length() && string.at(i) == ' ' ) {
+            buffer << "\\ ";
+            i++;
+        }
+
+        for( ; i < string.length(); i++ ) {
+
+            char ch = string.at(i);
+
+            switch(ch) {
+                case '\t':
+                    buffer << "\\t";
+                    break;
+                case '\n':
+                    buffer << "\\n";
+                    break;
+                case '\f':
+                    buffer << "\\f";
+                    break;
+                case '\r':
+                    buffer << "\\r";
+                    break;
+                default:
+                    if( std::string( "\\#!=:" ).find( ch ) != std::string::npos || ( key
&& ch == ' ' ) ) {
+                        buffer << '\\';
+                    }
+
+                    if( ch >= ' ' && ch <= '~' ) {
+                        buffer << ch;
+                    } else {
+
+                        std::string hex = Integer::toHexString( ch );
+                        buffer << "\\u";
+                        for( std::size_t j = 0; j < 4 - hex.length(); j++ ) {
+                            buffer << "0";
+                        }
+                        buffer << hex;
+                    }
+            }
+        }
+    }
+
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -244,6 +298,31 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+std::vector<std::string> Properties::propertyNames() const {
+
+    StlMap<std::string, std::string> selectedProperties;
+
+    this->selectProperties( selectedProperties );
+
+    return selectedProperties.keySet();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void Properties::selectProperties( StlMap<std::string, std::string>& selectProperties
) const {
+
+    if( this->defaults != NULL ) {
+        this->defaults->selectProperties( selectProperties );
+    }
+
+    std::vector<std::string> keys = this->internal->properties.keySet();
+    std::vector<std::string>::const_iterator key = keys.begin();
+
+    for( ; key != keys.end(); ++key ) {
+        selectProperties.put( *key, this->internal->properties.get( *key ) );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
 void Properties::load( decaf::io::InputStream* stream )
     throw( decaf::io::IOException,
            decaf::lang::exceptions::IllegalArgumentException,
@@ -257,9 +336,149 @@
                 "The Stream instance passed was Null" );
         }
 
-        throw UnsupportedOperationException(
-            __FILE__, __LINE__,
-            "Not yet Implemented." );
+        int mode = NONE;
+        char nextChar;
+        std::vector<char> buf;
+        int offset = 0;
+        int keyLength = -1;
+        int intVal;
+        bool firstChar = true;
+        BufferedInputStream bis( stream );
+
+        while(true) {
+
+            intVal = bis.read();
+
+            if( intVal == -1 ) {
+                break;
+            }
+
+            nextChar = (char) ( intVal & 0xFF );
+
+            if( mode == SLASH ) {
+
+                mode = NONE;
+                switch( nextChar ) {
+                    case '\r':
+                        mode = CONTINUE; // Look for a following \n
+                        continue;
+                    case '\n':
+                        mode = IGNORE; // Ignore whitespace on the next line
+                        continue;
+                    case 'b':
+                        nextChar = '\b';
+                        break;
+                    case 'f':
+                        nextChar = '\f';
+                        break;
+                    case 'n':
+                        nextChar = '\n';
+                        break;
+                    case 'r':
+                        nextChar = '\r';
+                        break;
+                    case 't':
+                        nextChar = '\t';
+                        break;
+                }
+
+            } else {
+
+                switch( nextChar ) {
+                case '#':
+                case '!':
+                    if( firstChar ) {
+                        while( true ) {
+                            intVal = bis.read();
+                            if( intVal == -1 ) {
+                                break;
+                            }
+
+                            nextChar = (char)( intVal & 0xFF );
+
+                            if( nextChar == '\r' || nextChar == '\n' ) {
+                                break;
+                            }
+                        }
+                        continue;
+                    }
+                    break;
+                case '\n':
+                    if( mode == CONTINUE) { // Part of a \r\n sequence
+                        mode = IGNORE; // Ignore whitespace on the next line
+                        continue;
+                    }
+                    // fall into the next case
+                case '\r':
+                    mode = NONE;
+                    firstChar = true;
+                    if( offset > 0 || ( offset == 0 && keyLength == 0 ) ) {
+
+                        if( keyLength == -1 ) {
+                            keyLength = offset;
+                        }
+                        std::string temp( &buf[0], 0, offset );
+
+                        this->internal->properties.put( temp.substr( 0, keyLength ),
+                                                        temp.substr( keyLength ) );
+                    }
+
+                    keyLength = -1;
+                    offset = 0;
+                    buf.clear();
+                    continue;
+                case '\\':
+                    if( mode == KEY_DONE ) {
+                        keyLength = offset;
+                    }
+                    mode = SLASH;
+                    continue;
+                case ':':
+                case '=':
+                    if( keyLength == -1 ) { // if parsing the key
+                        mode = NONE;
+                        keyLength = offset;
+                        continue;
+                    }
+                    break;
+                }
+                if( Character::isWhitespace( nextChar ) ) {
+                    if( mode == CONTINUE ) {
+                        mode = IGNORE;
+                    }
+                    // if key length == 0 or value length == 0
+                    if( offset == 0 || offset == keyLength || mode == IGNORE ) {
+                        continue;
+                    }
+                    if( keyLength == -1 ) { // if parsing the key
+                        mode = KEY_DONE;
+                        continue;
+                    }
+                }
+
+                if( mode == IGNORE || mode == CONTINUE ) {
+                    mode = NONE;
+                }
+            }
+
+            firstChar = false;
+            if( mode == KEY_DONE ) {
+                keyLength = offset;
+                mode = NONE;
+            }
+
+            offset += 1;
+            buf.push_back( nextChar );
+        }
+
+        if( keyLength == -1 && offset > 0 ) {
+            keyLength = offset;
+        }
+
+        if( keyLength >= 0 ) {
+            std::string temp( &buf[0], 0, offset );
+            this->internal->properties.put( temp.substr( 0, keyLength ), temp.substr(
keyLength ) );
+        }
     }
     DECAF_CATCH_RETHROW( IOException )
     DECAF_CATCH_RETHROW( IllegalArgumentException )
@@ -306,9 +525,35 @@
                 "The OutputStream instance passed was Null" );
         }
 
-        throw UnsupportedOperationException(
-            __FILE__, __LINE__,
-            "Not yet Implemented." );
+        std::ostringstream buffer;
+        std::ostringstream writer;
+
+        if( comments != "" ) {
+            writer << "#";
+            writer << comments;
+            writer << std::endl;
+        }
+
+        writer << "#";
+        writer << Date().toString();
+        writer << std::endl;
+
+        std::vector<std::string> keys = this->internal->properties.keySet();
+        std::vector<std::string>::const_iterator key = keys.begin();
+
+        for( ; key != keys.end(); ++key ) {
+
+            dumpString( buffer, *key, true );
+            buffer << "=";
+            dumpString( buffer, this->internal->properties.get( *key ), false );
+            buffer << std::endl;
+
+            writer << buffer.str();
+            buffer.str("");
+        }
+
+        out->write( (const unsigned char*)writer.str().c_str(), 0, writer.str().length()
);
+        out->flush();
     }
     DECAF_CATCH_RETHROW( IOException )
     DECAF_CATCH_RETHROW( NullPointerException )
@@ -338,3 +583,4 @@
     DECAF_CATCH_EXCEPTION_CONVERT( Exception, IOException )
     DECAF_CATCHALL_THROW( IOException )
 }
+

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Properties.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Properties.h?rev=905418&r1=905417&r2=905418&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Properties.h (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/main/decaf/util/Properties.h Mon Feb  1 21:32:39
2010
@@ -21,6 +21,7 @@
 #include <vector>
 #include <string>
 #include <decaf/util/Config.h>
+#include <decaf/util/StlMap.h>
 #include <decaf/io/InputStream.h>
 #include <decaf/io/OutputStream.h>
 #include <decaf/io/Reader.h>
@@ -131,6 +132,16 @@
         void remove( const std::string& name );
 
         /**
+         * Returns an enumeration of all the keys in this property list, including distinct
keys
+         * in the default property list if a key of the same name has not already been found
from
+         * the main properties list.
+         *
+         * @returns a set of keys in this property list where the key and its corresponding
value are
+         *          strings, including the keys in the default property list.
+         */
+        std::vector<std::string> propertyNames() const;
+
+        /**
          * Method that serializes the contents of the property map to
          * an array.
          * @return list of pairs where the first is the name and the second
@@ -375,6 +386,10 @@
             throw( decaf::io::IOException,
                    decaf::lang::exceptions::NullPointerException );
 
+    private:
+
+        void selectProperties( decaf::util::StlMap<std::string, std::string>& selectProperties
) const;
+
     };
 
 }}

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/PropertiesTest.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/PropertiesTest.cpp?rev=905418&r1=905417&r2=905418&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/PropertiesTest.cpp (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/PropertiesTest.cpp Mon Feb
 1 21:32:39 2010
@@ -19,10 +19,24 @@
 
 #include <memory>
 #include <decaf/util/Properties.h>
+#include <decaf/io/ByteArrayInputStream.h>
+#include <decaf/io/ByteArrayOutputStream.h>
 
 using namespace std;
 using namespace decaf;
 using namespace decaf::util;
+using namespace decaf::io;
+
+////////////////////////////////////////////////////////////////////////////////
+void PropertiesTest::setUp() {
+
+    this->testProperties.setProperty( "test.prop", "this is a test property" );
+    this->testProperties.setProperty( "bogus.prop", "bogus" );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void PropertiesTest::tearDown() {
+}
 
 ////////////////////////////////////////////////////////////////////////////////
 void PropertiesTest::testPutAndGet() {
@@ -188,3 +202,151 @@
 
     CPPUNIT_ASSERT( properties2.equals( properties1 ) );
 }
+
+////////////////////////////////////////////////////////////////////////////////
+void PropertiesTest::testLoadNPE() {
+
+    Properties properties;
+    decaf::io::InputStream* nullStream = NULL;
+    decaf::io::Reader* nullReader = NULL;
+
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Should have thrown a NullPointerException",
+        properties.load( nullStream ),
+        decaf::lang::exceptions::NullPointerException );
+
+    CPPUNIT_ASSERT_THROW_MESSAGE(
+        "Should have thrown a NullPointerException",
+        properties.load( nullReader ),
+        decaf::lang::exceptions::NullPointerException );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void PropertiesTest::testLoadInputStream() {
+
+    {
+        Properties properties;
+        string value(" a= b");
+        ByteArrayInputStream stream( (const unsigned char*)value.c_str(), value.size() );
+        properties.load( &stream );
+        CPPUNIT_ASSERT( string( "b" ) == properties.getProperty( "a" ) );
+    }
+
+    {
+        Properties properties;
+        string value(" a b");
+        ByteArrayInputStream stream( (const unsigned char*)value.c_str(), value.size() );
+        properties.load( &stream );
+        CPPUNIT_ASSERT( string( "b" ) == properties.getProperty( "a" ) );
+    }
+
+    {
+        Properties properties;
+        string value("#comment\na=value");
+        ByteArrayInputStream stream( (const unsigned char*)value.c_str(), value.size() );
+        properties.load( &stream );
+        CPPUNIT_ASSERT( string( "value" ) == properties.getProperty( "a" ) );
+    }
+
+    {
+        Properties properties;
+        string value("#properties file\r\nfred=1\r\n#last comment");
+        ByteArrayInputStream stream( (const unsigned char*)value.c_str(), value.size() );
+        properties.load( &stream );
+        CPPUNIT_ASSERT( string( "1" ) == properties.getProperty( "fred" ) );
+    }
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void PropertiesTest::testPropertyNames() {
+
+    Properties myProps( this->testProperties );
+
+    std::vector<std::string> names = myProps.propertyNames();
+    std::vector<std::string>::const_iterator name = names.begin();
+    int i = 0;
+
+    CPPUNIT_ASSERT( names.size() == 2 );
+
+    for( ; name != names.end(); ++name, ++i ) {
+        CPPUNIT_ASSERT_MESSAGE( "Incorrect names returned",
+                                *name == "test.prop" || *name == "bogus.prop" );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void PropertiesTest::testPropertyNamesOverride() {
+
+    Properties props( this->testProperties );
+    props.setProperty( "test.prop", "anotherValue" );
+    props.setProperty( "3rdKey", "3rdValue" );
+    std::vector<string> set = props.propertyNames();
+    CPPUNIT_ASSERT( 3 == set.size() );
+    CPPUNIT_ASSERT( std::find( set.begin(), set.end(), "test.prop" ) != set.end() );
+    CPPUNIT_ASSERT( std::find( set.begin(), set.end(), "bogus.prop") != set.end() );
+    CPPUNIT_ASSERT( std::find( set.begin(), set.end(), "3rdKey" ) != set.end() );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void PropertiesTest::testPropertyNamesScenario1() {
+
+    string keys[] = { "key1", "key2", "key3" };
+    string values[] = { "value1", "value2", "value3" };
+
+    std::set<string> keyList;
+
+    Properties properties;
+    for( int index = 0; index < 3; index++ ) {
+        properties.setProperty( keys[index], values[index] );
+        keyList.insert( keyList.begin(), keys[index] );
+    }
+
+    Properties properties2( properties );
+    std::vector<string> nameSet = properties.propertyNames();
+    CPPUNIT_ASSERT_EQUAL( 3, (int)nameSet.size() );
+    std::vector<string>::const_iterator iterator = nameSet.begin();
+    for( ; iterator != nameSet.end(); ++iterator ) {
+        CPPUNIT_ASSERT( keyList.find( *iterator ) != keyList.end() );
+    }
+
+    Properties properties3( properties2 );
+    nameSet = properties2.propertyNames();
+    CPPUNIT_ASSERT_EQUAL( 3, (int)nameSet.size() );
+    iterator = nameSet.begin();
+    for( ; iterator != nameSet.end(); ++iterator ) {
+        CPPUNIT_ASSERT( keyList.find( *iterator ) != keyList.end() );
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void PropertiesTest::testStoreOutputStream() {
+
+    Properties myProps;
+    Properties myProps2;
+
+    myProps.setProperty( "Property A", " aye\\\f\t\n\r" );
+    myProps.setProperty( "Property B", "b ee#!=:" );
+    myProps.setProperty( "Property C", "see" );
+
+    try {
+
+        ByteArrayOutputStream out;
+        myProps.store( &out, "A Header" );
+        out.close();
+
+        ByteArrayInputStream in( out.toByteArray(), out.size() );
+        myProps2.load( &in );
+        in.close();
+
+    } catch( IOException& ioe ) {
+        CPPUNIT_FAIL( string("IOException occurred reading/writing file : ") + ioe.getMessage()
);
+    }
+
+    CPPUNIT_ASSERT( myProps.size() == myProps2.size() );
+    std::vector<string> nameSet = myProps.propertyNames();
+    std::vector<string>::const_iterator iterator = nameSet.begin();
+    for( ; iterator != nameSet.end(); ++iterator ) {
+        CPPUNIT_ASSERT( string( myProps2.getProperty( *iterator ) ) == string( myProps.getProperty(
*iterator ) ) );
+    }
+}

Modified: activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/PropertiesTest.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/PropertiesTest.h?rev=905418&r1=905417&r2=905418&view=diff
==============================================================================
--- activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/PropertiesTest.h (original)
+++ activemq/activemq-cpp/trunk/activemq-cpp/src/test/decaf/util/PropertiesTest.h Mon Feb
 1 21:32:39 2010
@@ -21,6 +21,8 @@
 #include <cppunit/TestFixture.h>
 #include <cppunit/extensions/HelperMacros.h>
 
+#include <decaf/util/Properties.h>
+
 namespace decaf {
 namespace util {
 
@@ -34,14 +36,27 @@
         CPPUNIT_TEST( testRemove );
         CPPUNIT_TEST( testClear );
         CPPUNIT_TEST( testEquals );
+        CPPUNIT_TEST( testLoadNPE );
+        CPPUNIT_TEST( testLoadInputStream );
+        CPPUNIT_TEST( testPropertyNames );
+        CPPUNIT_TEST( testPropertyNamesOverride );
+        CPPUNIT_TEST( testPropertyNamesScenario1 );
+        CPPUNIT_TEST( testStoreOutputStream );
         CPPUNIT_TEST_SUITE_END();
 
+    private:
+
+        Properties testProperties;
+
     public:
 
         PropertiesTest() {}
 
         virtual ~PropertiesTest() {}
 
+        virtual void setUp();
+        virtual void tearDown();
+
         void testPutAndGet();
         void testAssign();
         void testCopy();
@@ -49,6 +64,12 @@
         void testRemove();
         void testClear();
         void testEquals();
+        void testLoadNPE();
+        void testLoadInputStream();
+        void testPropertyNames();
+        void testPropertyNamesOverride();
+        void testPropertyNamesScenario1();
+        void testStoreOutputStream();
 
     };
 



Mime
View raw message