activemq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tab...@apache.org
Subject [4/4] git commit: https://issues.apache.org/jira/browse/AMQCPP-511
Date Wed, 30 Oct 2013 23:35:31 GMT
https://issues.apache.org/jira/browse/AMQCPP-511

Project: http://git-wip-us.apache.org/repos/asf/activemq-cpp/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq-cpp/commit/b1746b23
Tree: http://git-wip-us.apache.org/repos/asf/activemq-cpp/tree/b1746b23
Diff: http://git-wip-us.apache.org/repos/asf/activemq-cpp/diff/b1746b23

Branch: refs/heads/trunk
Commit: b1746b23e4af5cdad7ebfed49472dea35559d107
Parents: e348ac1
Author: Timothy Bish <tabish121@gmai.com>
Authored: Wed Oct 30 19:35:18 2013 -0400
Committer: Timothy Bish <tabish121@gmai.com>
Committed: Wed Oct 30 19:35:18 2013 -0400

----------------------------------------------------------------------
 activemq-cpp/src/main/Makefile.am               |    6 +
 .../internal/net/URLStreamHandlerManager.cpp    |  165 +++
 .../internal/net/URLStreamHandlerManager.h      |   94 ++
 .../src/main/decaf/internal/net/URLType.h       |   50 +-
 .../decaf/internal/net/http/HttpHandler.cpp     |   52 +
 .../main/decaf/internal/net/http/HttpHandler.h  |   48 +
 .../main/decaf/internal/util/StringUtils.cpp    |   26 +
 .../src/main/decaf/internal/util/StringUtils.h  |   13 +
 activemq-cpp/src/main/decaf/lang/String.cpp     | 1231 +++++++++++++++++-
 activemq-cpp/src/main/decaf/lang/String.h       |  806 +++++++++++-
 .../ArrayIndexOutOfBoundsException.cpp          |   79 ++
 .../exceptions/ArrayIndexOutOfBoundsException.h |  139 ++
 activemq-cpp/src/main/decaf/net/URL.cpp         |  490 ++++---
 activemq-cpp/src/main/decaf/net/URL.h           |   35 +-
 activemq-cpp/src/main/decaf/net/URLConnection.h |    2 +-
 .../src/main/decaf/net/URLStreamHandler.cpp     |  380 +++---
 .../src/main/decaf/net/URLStreamHandler.h       |   16 +-
 activemq-cpp/src/test/Makefile.am               |    2 +
 activemq-cpp/src/test/decaf/lang/StringTest.cpp |  774 ++++++++++-
 activemq-cpp/src/test/decaf/lang/StringTest.h   |  134 +-
 activemq-cpp/src/test/decaf/net/URLTest.cpp     |   55 +
 activemq-cpp/src/test/decaf/net/URLTest.h       |   46 +
 activemq-cpp/src/test/testRegistry.cpp          | 1008 +++++++-------
 23 files changed, 4580 insertions(+), 1071 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/activemq-cpp/blob/b1746b23/activemq-cpp/src/main/Makefile.am
----------------------------------------------------------------------
diff --git a/activemq-cpp/src/main/Makefile.am b/activemq-cpp/src/main/Makefile.am
index efc214b..8ca9b15 100644
--- a/activemq-cpp/src/main/Makefile.am
+++ b/activemq-cpp/src/main/Makefile.am
@@ -352,7 +352,9 @@ cc_sources = \
     decaf/internal/net/URIEncoderDecoder.cpp \
     decaf/internal/net/URIHelper.cpp \
     decaf/internal/net/URIType.cpp \
+    decaf/internal/net/URLStreamHandlerManager.cpp \
     decaf/internal/net/URLType.cpp \
+    decaf/internal/net/http/HttpHandler.cpp \
     decaf/internal/net/ssl/DefaultSSLContext.cpp \
     decaf/internal/net/ssl/DefaultSSLServerSocketFactory.cpp \
     decaf/internal/net/ssl/DefaultSSLSocketFactory.cpp \
@@ -463,6 +465,7 @@ cc_sources = \
     decaf/lang/ThreadLocal.cpp \
     decaf/lang/Throwable.cpp \
     decaf/lang/Types.cpp \
+    decaf/lang/exceptions/ArrayIndexOutOfBoundsException.cpp \
     decaf/lang/exceptions/ClassCastException.cpp \
     decaf/lang/exceptions/CloneNotSupportedException.cpp \
     decaf/lang/exceptions/IllegalArgumentException.cpp \
@@ -1025,7 +1028,9 @@ h_sources = \
     decaf/internal/net/URIEncoderDecoder.h \
     decaf/internal/net/URIHelper.h \
     decaf/internal/net/URIType.h \
+    decaf/internal/net/URLStreamHandlerManager.h \
     decaf/internal/net/URLType.h \
+    decaf/internal/net/http/HttpHandler.h \
     decaf/internal/net/ssl/DefaultSSLContext.h \
     decaf/internal/net/ssl/DefaultSSLServerSocketFactory.h \
     decaf/internal/net/ssl/DefaultSSLSocketFactory.h \
@@ -1143,6 +1148,7 @@ h_sources = \
     decaf/lang/ThreadLocal.h \
     decaf/lang/Throwable.h \
     decaf/lang/Types.h \
+    decaf/lang/exceptions/ArrayIndexOutOfBoundsException.h \
     decaf/lang/exceptions/ClassCastException.h \
     decaf/lang/exceptions/CloneNotSupportedException.h \
     decaf/lang/exceptions/ExceptionDefines.h \

http://git-wip-us.apache.org/repos/asf/activemq-cpp/blob/b1746b23/activemq-cpp/src/main/decaf/internal/net/URLStreamHandlerManager.cpp
----------------------------------------------------------------------
diff --git a/activemq-cpp/src/main/decaf/internal/net/URLStreamHandlerManager.cpp b/activemq-cpp/src/main/decaf/internal/net/URLStreamHandlerManager.cpp
new file mode 100644
index 0000000..7beea65
--- /dev/null
+++ b/activemq-cpp/src/main/decaf/internal/net/URLStreamHandlerManager.cpp
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ */
+
+#include <decaf/internal/net/URLStreamHandlerManager.h>
+
+#include <decaf/lang/Runnable.h>
+#include <decaf/lang/exceptions/RuntimeException.h>
+#include <decaf/lang/Exception.h>
+#include <decaf/net/URLStreamHandler.h>
+#include <decaf/net/URLStreamHandlerFactory.h>
+#include <decaf/internal/net/Network.h>
+
+#include <decaf/internal/net/http/HttpHandler.h>
+
+using namespace decaf;
+using namespace decaf::internal;
+using namespace decaf::internal::net;
+using namespace decaf::internal::net::http;
+using namespace decaf::net;
+using namespace decaf::lang;
+using namespace decaf::lang::exceptions;
+
+////////////////////////////////////////////////////////////////////////////////
+URLStreamHandlerManager* URLStreamHandlerManager::instance;
+
+////////////////////////////////////////////////////////////////////////////////
+namespace {
+
+    class ShutdownTask : public decaf::lang::Runnable {
+    private:
+
+        URLStreamHandlerManager** defaultRef;
+
+    private:
+
+        ShutdownTask( const ShutdownTask& );
+        ShutdownTask& operator= ( const ShutdownTask& );
+
+    public:
+
+        ShutdownTask( URLStreamHandlerManager** defaultRef ) : defaultRef( defaultRef ) {}
+        virtual ~ShutdownTask() {}
+
+        virtual void run() {
+            *defaultRef = NULL;
+        }
+    };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+namespace decaf {
+namespace internal {
+namespace net {
+
+    class URLStreamHandlerManagerImpl {
+    public:
+
+        URLStreamHandlerFactory* factory;
+
+    public:
+
+        URLStreamHandlerManagerImpl() : factory(NULL) {
+        }
+
+        virtual ~URLStreamHandlerManagerImpl() {
+            try {
+                delete factory;
+            } catch(...) {}
+        }
+
+    };
+
+}}}
+
+////////////////////////////////////////////////////////////////////////////////
+URLStreamHandlerManager::URLStreamHandlerManager() : impl(new URLStreamHandlerManagerImpl) {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+URLStreamHandlerManager::~URLStreamHandlerManager() {
+    try {
+        delete impl;
+    }
+    DECAF_CATCHALL_NOTHROW()
+}
+
+////////////////////////////////////////////////////////////////////////////////
+URLStreamHandlerManager* URLStreamHandlerManager::getInstance() {
+
+    if (instance == NULL) {
+
+        synchronized(Network::getNetworkRuntime()->getRuntimeLock()) {
+
+            if (instance != NULL) {
+                return instance;
+            }
+
+            instance = new URLStreamHandlerManager;
+
+            // Store the default in the Network Runtime, it will be destroyed when the
+            // Application calls the Decaf shutdownLibrary method.
+            Network::getNetworkRuntime()->addAsResource(instance);
+            Network::getNetworkRuntime()->addShutdownTask(new ShutdownTask(&instance));
+        }
+    }
+
+    return instance;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+void URLStreamHandlerManager::setURLStreamHandlerFactory(URLStreamHandlerFactory* factory) {
+
+    synchronized(Network::getNetworkRuntime()->getRuntimeLock()) {
+
+        if (impl->factory != NULL) {
+            throw RuntimeException(
+                __FILE__, __LINE__, "Application already set a URLStreamHandlerFactory");
+        }
+
+        impl->factory = factory;
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+URLStreamHandler* URLStreamHandlerManager::getURLStreamHandler(const decaf::lang::String& protocol) {
+
+    URLStreamHandler* streamHandler = NULL;
+
+    synchronized(Network::getNetworkRuntime()->getRuntimeLock()) {
+
+        // If there is a stream handler factory, then attempt to
+        // use it to create the handler.
+        if (impl->factory != NULL) {
+            streamHandler = impl->factory->createURLStreamHandler(protocol.toString());
+            if (streamHandler != NULL) {
+                return streamHandler;
+            }
+        }
+
+        // No one else has provided a handler, so try our internal one.
+        if (protocol.equalsIgnoreCase("http")) {
+            return new HttpHandler;
+        }
+
+        // TODO we should cache the stream handlers and return the cached version
+        //      we just need to ensure we manage the lifetime from within this object.
+    }
+
+    return streamHandler;
+}
+

http://git-wip-us.apache.org/repos/asf/activemq-cpp/blob/b1746b23/activemq-cpp/src/main/decaf/internal/net/URLStreamHandlerManager.h
----------------------------------------------------------------------
diff --git a/activemq-cpp/src/main/decaf/internal/net/URLStreamHandlerManager.h b/activemq-cpp/src/main/decaf/internal/net/URLStreamHandlerManager.h
new file mode 100644
index 0000000..159e9a1
--- /dev/null
+++ b/activemq-cpp/src/main/decaf/internal/net/URLStreamHandlerManager.h
@@ -0,0 +1,94 @@
+/*
+ * 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_INTERNAL_NET_URLSTREAMHANDLERMANAGER_H_
+#define _DECAF_INTERNAL_NET_URLSTREAMHANDLERMANAGER_H_
+
+#include <decaf/util/Config.h>
+
+#include <decaf/lang/String.h>
+
+namespace decaf {
+namespace net {
+    class URLStreamHandler;
+    class URLStreamHandlerFactory;
+}
+namespace internal {
+namespace net {
+
+    class Network;
+    class URLStreamHandlerManagerImpl;
+
+    class DECAF_API URLStreamHandlerManager {
+    private:
+
+        URLStreamHandlerManagerImpl* impl;
+
+    private:
+
+        static URLStreamHandlerManager* instance;
+
+    private:
+
+        URLStreamHandlerManager();
+
+    public:
+
+        virtual ~URLStreamHandlerManager();
+
+    public:
+
+        /**
+         * Returns the one and only URLStreamHandlerManager instance for this
+         * application.  The returned pointer should never be deleted by the
+         * application.
+         *
+         * @returns a URLStreamHandlerManager instance.
+         */
+        static URLStreamHandlerManager* getInstance();
+
+    public:
+
+        /**
+         * Gets a URLStreamHandler for the specified protocol if one is available.
+         *
+         * @param protocol
+         *      The protocol to return a URL Stream Handler instance for.
+         *
+         * @returns a URLStreamHandler instance for the given protocol.
+         */
+        decaf::net::URLStreamHandler* getURLStreamHandler(const decaf::lang::String& protocol);
+
+        /**
+         * Sets an application's URLStreamHandlerFactory. This method can be called at most once.
+         *
+         * The URLStreamHandlerFactory instance is used to construct a stream protocol handler
+         * from a protocol name.  The provided factory becomes the property of this runtime and
+         * will be deleted at shutdown.
+         *
+         * @param factory
+         *      the desired factory.
+         *
+         * @throws Exception if there is already a set factory.
+         */
+        void setURLStreamHandlerFactory(decaf::net::URLStreamHandlerFactory* factory);
+
+    };
+
+}}}
+
+#endif /* _DECAF_INTERNAL_NET_URLSTREAMHANDLERMANAGER_H_ */

http://git-wip-us.apache.org/repos/asf/activemq-cpp/blob/b1746b23/activemq-cpp/src/main/decaf/internal/net/URLType.h
----------------------------------------------------------------------
diff --git a/activemq-cpp/src/main/decaf/internal/net/URLType.h b/activemq-cpp/src/main/decaf/internal/net/URLType.h
index dc20188..e12eb3a 100644
--- a/activemq-cpp/src/main/decaf/internal/net/URLType.h
+++ b/activemq-cpp/src/main/decaf/internal/net/URLType.h
@@ -18,8 +18,8 @@
 #ifndef _DECAF_INTERNAL_NET_URLTYPE_H_
 #define _DECAF_INTERNAL_NET_URLTYPE_H_
 
-#include <string>
 #include <decaf/util/Config.h>
+#include <decaf/lang/String.h>
 
 namespace decaf {
 namespace internal {
@@ -31,15 +31,15 @@ namespace net {
     class DECAF_API URLType {
     private:
 
-        std::string file;
-        std::string protocol;
-        std::string host;
+        decaf::lang::String file;
+        decaf::lang::String protocol;
+        decaf::lang::String host;
         int port;
-        std::string authority;
-        std::string userInfo;
-        std::string path;
-        std::string query;
-        std::string ref;
+        decaf::lang::String authority;
+        decaf::lang::String userInfo;
+        decaf::lang::String path;
+        decaf::lang::String query;
+        decaf::lang::String ref;
         int hashCode;
 
     public:
@@ -52,7 +52,7 @@ namespace net {
          * Gets the File of the URL.
          * @return File part string.
          */
-        std::string getFile() const {
+        decaf::lang::String getFile() const {
             return file;
         }
 
@@ -60,7 +60,7 @@ namespace net {
          * Sets the File of the URL.
          * @param File Authority part string.
          */
-        void setFile(const std::string& file) {
+        void setFile(const decaf::lang::String& file) {
             this->file = file;
         }
 
@@ -68,7 +68,7 @@ namespace net {
          * Gets the protocol of the URL, e.g. protocol ("http"/"ftp"/...).
          * @return protocol part string.
          */
-        std::string getProtocol() const {
+        decaf::lang::String getProtocol() const {
             return protocol;
         }
 
@@ -76,7 +76,7 @@ namespace net {
          * Sets the protocol of the URL, e.g. protocol ("http"/"ftp"/...).
          * @param protocol - protocol part string.
          */
-        void setProtocol(const std::string& protocol) {
+        void setProtocol(const decaf::lang::String& protocol) {
             this->protocol = protocol;
         }
 
@@ -84,7 +84,7 @@ namespace net {
          * Gets the Authority of the URL.
          * @return Authority part string.
          */
-        std::string getAuthority() const {
+        decaf::lang::String getAuthority() const {
             return authority;
         }
 
@@ -92,7 +92,7 @@ namespace net {
          * Sets the Authority of the URL.
          * @param authority Authority part string.
          */
-        void setAuthority(const std::string& authority) {
+        void setAuthority(const decaf::lang::String& authority) {
             this->authority = authority;
         }
 
@@ -101,7 +101,7 @@ namespace net {
          * http://user:passwd@host:port/
          * @return user info part string.
          */
-        std::string getUserInfo() const {
+        decaf::lang::String getUserInfo() const {
             return userInfo;
         }
 
@@ -111,7 +111,7 @@ namespace net {
          *
          * @param userInfo - user info part string.
          */
-        void setUserInfo(const std::string& userInfo) {
+        void setUserInfo(const decaf::lang::String& userInfo) {
             this->userInfo = userInfo;
         }
 
@@ -119,7 +119,7 @@ namespace net {
          * Gets the Host name part of the URL.
          * @return Host name part string.
          */
-        std::string getHost() const {
+        decaf::lang::String getHost() const {
             return host;
         }
 
@@ -127,7 +127,7 @@ namespace net {
          * Sets the Host name part of the URL.
          * @param host - Host name part string.
          */
-        void setHost(const std::string& host) {
+        void setHost(const decaf::lang::String& host) {
             this->host = host;
         }
 
@@ -151,7 +151,7 @@ namespace net {
          * Gets the Path part of the URL.
          * @return Path part string.
          */
-        std::string getPath() const {
+        decaf::lang::String getPath() const {
             return path;
         }
 
@@ -159,7 +159,7 @@ namespace net {
          * Sets the Path part of the URL.
          * @param path - Path part string.
          */
-        void setPath(const std::string& path) {
+        void setPath(const decaf::lang::String& path) {
             this->path = path;
         }
 
@@ -167,7 +167,7 @@ namespace net {
          * Gets the Query part of the URL.
          * @return Query part string.
          */
-        std::string getQuery() const {
+        decaf::lang::String getQuery() const {
             return query;
         }
 
@@ -175,7 +175,7 @@ namespace net {
          * Sets the Query part of the URL.
          * @param query - Query part string.
          */
-        void setQuery(const std::string& query) {
+        void setQuery(const decaf::lang::String& query) {
             this->query = query;
         }
 
@@ -183,7 +183,7 @@ namespace net {
          * Gets the Ref part of the URL.
          * @return Ref part string.
          */
-        std::string getRef() const {
+        decaf::lang::String getRef() const {
             return ref;
         }
 
@@ -191,7 +191,7 @@ namespace net {
          * Sets the Ref part of the URL.
          * @param ref - Ref part string.
          */
-        void setRef(const std::string& ref) {
+        void setRef(const decaf::lang::String& ref) {
             this->ref = ref;
         }
 

http://git-wip-us.apache.org/repos/asf/activemq-cpp/blob/b1746b23/activemq-cpp/src/main/decaf/internal/net/http/HttpHandler.cpp
----------------------------------------------------------------------
diff --git a/activemq-cpp/src/main/decaf/internal/net/http/HttpHandler.cpp b/activemq-cpp/src/main/decaf/internal/net/http/HttpHandler.cpp
new file mode 100644
index 0000000..1af0bd9
--- /dev/null
+++ b/activemq-cpp/src/main/decaf/internal/net/http/HttpHandler.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+#include <decaf/internal/net/http/HttpHandler.h>
+
+#include <decaf/lang/exceptions/IllegalArgumentException.h>
+
+using namespace decaf;
+using namespace decaf::lang;
+using namespace decaf::lang::exceptions;
+using namespace decaf::internal;
+using namespace decaf::internal::net;
+using namespace decaf::internal::net::http;
+
+////////////////////////////////////////////////////////////////////////////////
+HttpHandler::~HttpHandler() {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+decaf::net::URLConnection* HttpHandler::openConnection(const decaf::net::URL& url) {
+    return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+decaf::net::URLConnection* HttpHandler::openConnection(const decaf::net::URL& url,
+                                                       const decaf::net::Proxy* proxy) {
+
+    if (proxy == NULL) {
+        throw IllegalArgumentException(__FILE__, __LINE__, "proxy object cannot be NULL");
+    }
+
+    return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int HttpHandler::getDefaultPort() const {
+    return 80;
+}

http://git-wip-us.apache.org/repos/asf/activemq-cpp/blob/b1746b23/activemq-cpp/src/main/decaf/internal/net/http/HttpHandler.h
----------------------------------------------------------------------
diff --git a/activemq-cpp/src/main/decaf/internal/net/http/HttpHandler.h b/activemq-cpp/src/main/decaf/internal/net/http/HttpHandler.h
new file mode 100644
index 0000000..1f28be1
--- /dev/null
+++ b/activemq-cpp/src/main/decaf/internal/net/http/HttpHandler.h
@@ -0,0 +1,48 @@
+/*
+ * 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_INTERNAL_NET_HTTP_HTTPHANDLER_H_
+#define _DECAF_INTERNAL_NET_HTTP_HTTPHANDLER_H_
+
+#include <decaf/util/Config.h>
+
+#include <decaf/net/URLStreamHandler.h>
+
+namespace decaf {
+namespace internal {
+namespace net {
+namespace http {
+
+    class DECAF_API HttpHandler : public decaf::net::URLStreamHandler {
+    public:
+
+        virtual ~HttpHandler();
+
+    public:
+
+        virtual decaf::net::URLConnection* openConnection(const decaf::net::URL& url);
+
+        virtual decaf::net::URLConnection* openConnection(const decaf::net::URL& url,
+                                                          const decaf::net::Proxy* proxy);
+
+        virtual int getDefaultPort() const;
+
+    };
+
+}}}}
+
+#endif /* _DECAF_INTERNAL_NET_HTTP_HTTPHANDLER_H_ */

http://git-wip-us.apache.org/repos/asf/activemq-cpp/blob/b1746b23/activemq-cpp/src/main/decaf/internal/util/StringUtils.cpp
----------------------------------------------------------------------
diff --git a/activemq-cpp/src/main/decaf/internal/util/StringUtils.cpp b/activemq-cpp/src/main/decaf/internal/util/StringUtils.cpp
index 95f907a..a5f9724 100644
--- a/activemq-cpp/src/main/decaf/internal/util/StringUtils.cpp
+++ b/activemq-cpp/src/main/decaf/internal/util/StringUtils.cpp
@@ -18,9 +18,14 @@
 #include "StringUtils.h"
 
 #include <decaf/lang/Character.h>
+#include <decaf/lang/Integer.h>
+
+#include <decaf/lang/exceptions/RuntimeException.h>
+#include <decaf/lang/exceptions/NullPointerException.h>
 
 using namespace decaf;
 using namespace decaf::lang;
+using namespace decaf::lang::exceptions;
 using namespace decaf::internal;
 using namespace decaf::internal::util;
 
@@ -134,6 +139,27 @@ namespace {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+int StringUtils::stringLength(const char* string) {
+
+    if (string == NULL) {
+        throw NullPointerException(__FILE__, __LINE__, "Cannot check length of NULL string.");
+    }
+
+    int length = 0;
+    while (*string != '\0') {
+        string++;
+
+        if (length == Integer::MAX_VALUE) {
+            throw RuntimeException(__FILE__, __LINE__, "String length is longer than Integer::MAX_VALUE");
+        }
+
+        length++;
+    }
+
+    return length;
+}
+
+////////////////////////////////////////////////////////////////////////////////
 int StringUtils::compareIgnoreCase(const char* left, const char* right) {
     return doCompare(left, right, true);
 }

http://git-wip-us.apache.org/repos/asf/activemq-cpp/blob/b1746b23/activemq-cpp/src/main/decaf/internal/util/StringUtils.h
----------------------------------------------------------------------
diff --git a/activemq-cpp/src/main/decaf/internal/util/StringUtils.h b/activemq-cpp/src/main/decaf/internal/util/StringUtils.h
index 2373e3b..63d0f60 100644
--- a/activemq-cpp/src/main/decaf/internal/util/StringUtils.h
+++ b/activemq-cpp/src/main/decaf/internal/util/StringUtils.h
@@ -39,6 +39,19 @@ namespace util {
         virtual ~StringUtils() {}
 
         /**
+         * Returns the length of the given C string.
+         *
+         * @param string
+         *      The C style string to check.
+         *
+         * @returns the length of the string if the size is < Integer::MAX_VALUE.
+         *
+         * @throws RuntimeException if the length becomes larger than
+         *         the max value of an int.
+         */
+        static int stringLength(const char* string);
+
+        /**
          * Perform a comparison between two strings using natural ordering and ignoring case.
          *
          * @param left

http://git-wip-us.apache.org/repos/asf/activemq-cpp/blob/b1746b23/activemq-cpp/src/main/decaf/lang/String.cpp
----------------------------------------------------------------------
diff --git a/activemq-cpp/src/main/decaf/lang/String.cpp b/activemq-cpp/src/main/decaf/lang/String.cpp
index 44d6e14..eac8eee 100644
--- a/activemq-cpp/src/main/decaf/lang/String.cpp
+++ b/activemq-cpp/src/main/decaf/lang/String.cpp
@@ -21,20 +21,26 @@
 #include <decaf/lang/System.h>
 #include <decaf/lang/exceptions/NullPointerException.h>
 #include <decaf/lang/exceptions/IndexOutOfBoundsException.h>
+#include <decaf/lang/exceptions/StringIndexOutOfBoundsException.h>
 #include <decaf/lang/Short.h>
 #include <decaf/lang/Integer.h>
 #include <decaf/lang/Long.h>
+#include <decaf/lang/Character.h>
 #include <decaf/lang/Float.h>
 #include <decaf/lang/Double.h>
 
+#include <decaf/internal/util/StringUtils.h>
+
 using namespace std;
 using namespace decaf;
 using namespace decaf::lang;
 using namespace decaf::lang::exceptions;
+using namespace decaf::internal;
+using namespace decaf::internal::util;
 
 ////////////////////////////////////////////////////////////////////////////////
-namespace decaf{
-namespace lang{
+namespace decaf {
+namespace lang {
 
     class Contents {
     public:
@@ -43,35 +49,60 @@ namespace lang{
         int length;
         int offset;
 
-    public:
-
-        Contents() : value(), length(0), offset(0) {
-        }
+        int hashCode;
 
-        Contents( int length ) : value(length), length(length), offset(0) {
-        }
+    public:
 
+        Contents() : value(), length(0), offset(0), hashCode(0) {}
+        Contents(int length) : value(length), length(length), offset(0), hashCode(0) {}
+        Contents(int offset, int length, ArrayPointer<unsigned char> value) :
+            value(value), length(length), offset(offset), hashCode(0) {}
     };
 
 }}
 
 ////////////////////////////////////////////////////////////////////////////////
-String::String() : contents(new Contents()) {
+String::String(Contents* content) :
+    contents(new Contents(0, content->value.length(), content->value)) {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+String::String(int offset, int length, Contents* content) :
+    contents(new Contents(offset, length, content->value)) {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-String::String(const String& source) : contents(new Contents(source.length())) {
+String::String() : contents(new Contents()) {
+}
 
-    // TODO
-    // load the passed string into the contents value.
-    //System::arraycopy( (unsigned char*)source.c_str(), 0, contents->value.get(), 0, source.length() );
+////////////////////////////////////////////////////////////////////////////////
+String::String(const String& source) : contents(new Contents(*source.contents)) {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 String::String(const std::string& source) : contents(new Contents((int)source.length())) {
 
     // load the passed string into the contents value.
-    System::arraycopy( (unsigned char*)source.c_str(), 0, contents->value.get(), 0, source.length() );
+    System::arraycopy((unsigned char*)source.c_str(), 0, contents->value.get(), 0, source.length());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+String::String(const char* array) : contents(new Contents) {
+
+    if (array == NULL) {
+        throw NullPointerException(
+            __FILE__, __LINE__, "Buffer pointer passed was NULL.");
+    }
+
+    int size = StringUtils::stringLength(array);
+
+    if (size > 0) {
+
+        this->contents->value = ArrayPointer<unsigned char>(size);
+        this->contents->length = size;
+
+        System::arraycopy((unsigned char*) array, 0, contents->value.get(), 0, size);
+    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -97,26 +128,55 @@ String::String(const char* array, int size) : contents(new Contents) {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+String::String(const char* array, int offset, int length) : contents(new Contents) {
+
+    int size = StringUtils::stringLength(array);
+
+    if (offset > size || offset < 0) {
+        throw IndexOutOfBoundsException(
+            __FILE__, __LINE__, "offset parameter out of Bounds: %d.", offset);
+    }
+
+    if (length < 0 || length > size - offset) {
+        throw IndexOutOfBoundsException(
+            __FILE__, __LINE__, "length parameter out of Bounds: %d.", length);
+    }
+
+    if (array == NULL) {
+        throw NullPointerException(
+            __FILE__, __LINE__, "Buffer pointer passed was NULL.");
+    }
+
+    if (size > 0) {
+
+        this->contents->value = ArrayPointer<unsigned char>(length);
+        this->contents->length = length;
+
+        System::arraycopy((unsigned char*) array, offset, contents->value.get(), 0, length);
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
 String::String(const char* array, int size, int offset, int length) : contents(new Contents) {
 
     if (size < 0) {
         throw IndexOutOfBoundsException(
-            __FILE__, __LINE__, "size parameter out of Bounds: %d.", size );
+            __FILE__, __LINE__, "size parameter out of Bounds: %d.", size);
     }
 
     if (offset > size || offset < 0) {
         throw IndexOutOfBoundsException(
-            __FILE__, __LINE__, "offset parameter out of Bounds: %d.", offset );
+            __FILE__, __LINE__, "offset parameter out of Bounds: %d.", offset);
     }
 
     if (length < 0 || length > size - offset) {
         throw IndexOutOfBoundsException(
-            __FILE__, __LINE__, "length parameter out of Bounds: %d.", length );
+            __FILE__, __LINE__, "length parameter out of Bounds: %d.", length);
     }
 
     if (array == NULL) {
         throw NullPointerException(
-            __FILE__, __LINE__, "Buffer pointer passed was NULL." );
+            __FILE__, __LINE__, "Buffer pointer passed was NULL.");
     }
 
     if (size > 0) {
@@ -138,28 +198,132 @@ String::~String() {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-int String::length() const {
-    return this->contents->offset + this->contents->length;
+String& String::operator= (const String& other) {
+    contents->value = other.contents->value;
+    contents->length = other.contents->length;
+    contents->offset = other.contents->offset;
+    contents->hashCode = other.contents->hashCode;
+
+    return *this;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-bool String::isEmpty() const {
-    return (this->contents->offset + this->contents->length) == 0;
+String& String::operator= (const std::string& other) {
+
+    if (!other.empty()) {
+        int length = (int) other.length();
+
+        contents->value = ArrayPointer<unsigned char>(length);
+        contents->length = length;
+        contents->hashCode = 0;
+
+        System::arraycopy((unsigned char*)other.c_str(), 0, contents->value.get(), 0, length);
+    }
+
+    return *this;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-String String::trim() const {
-    return String();
+String& String::operator= (const char* other) {
+
+    if (other == NULL) {
+        throw NullPointerException(__FILE__, __LINE__, "Assignment from NULL not supported.");
+    }
+
+    int length = StringUtils::stringLength(other);
+    if (length > 0) {
+        contents->value = ArrayPointer<unsigned char>(length);
+        contents->length = length;
+        contents->hashCode = 0;
+
+        System::arraycopy((unsigned char*)other, 0, contents->value.get(), 0, length);
+    }
+
+    return *this;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::operator==(const String& other) const {
+    return this->equals(other);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::operator==(const std::string& other) const {
+    return this->equals(other);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::operator==(const char* other) const {
+    return this->equals(other);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::operator!=(const String& other) const {
+    return !this->equals(other);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::operator!=(const std::string& other) const {
+    return !this->equals(other);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::operator!=(const char* other) const {
+    return !this->equals(other);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::operator< (const String& other) const {
+    return this->compareTo(other) < 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::operator< (const std::string& other) const {
+    return this->compareTo(other) < 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::operator< (const char* other) const {
+    return this->compareTo(other) < 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+String String::operator+ (const String& other) const {
+    return this->concat(other);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+String String::operator+ (const std::string& other) const {
+    return this->concat(other);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+String String::operator+ (const char* other) const {
+    return this->concat(other);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+const char* String::c_str() const {
+
+    if (contents->length == 0) {
+        return NULL;
+    }
+
+    if (contents->offset == 0 && contents->length == contents->value.length()) {
+        return (const char*) contents->value.get();
+    }
+
+    throw UnsupportedOperationException(__FILE__, __LINE__, "Not yet implemented for offset values");
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 char String::charAt(int index) const {
 
-    try{
+    try {
 
         if (index < 0 || index >= this->length()) {
             throw IndexOutOfBoundsException(
-                __FILE__, __LINE__, "Index given is out of bounds: %d.", index );
+                __FILE__, __LINE__, "Index given is out of bounds: %d.", index);
         }
 
         return this->contents->value[this->contents->offset + index];
@@ -169,72 +333,1025 @@ char String::charAt(int index) const {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-CharSequence* String::subSequence(int start DECAF_UNUSED, int end DECAF_UNUSED) const {
+int String::compareTo(const String& string) const {
 
-    try {
+    int o1 = contents->offset;
+    int o2 = string.contents->offset;
+    int result;
 
-        if (start > end) {
-            throw IndexOutOfBoundsException(
-                __FILE__, __LINE__, "Start index is greater than end index." );
+    int end = contents->offset +
+        (contents->length < string.contents->length ? contents->length : string.contents->length);
+
+    while (o1 < end) {
+        if ((result = contents->value[o1++] - string.contents->value[o2++]) != 0) {
+            return result;
         }
+    }
 
-        if (end - start > this->length()) {
-            throw IndexOutOfBoundsException(
-                __FILE__, __LINE__, "Requested Range is greater than the String length." );
+    return contents->length - string.contents->length;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::compareTo(const std::string& string) const {
+
+    int o1 = contents->offset;
+    int o2 = 0;
+    int result;
+
+    int end = contents->offset +
+        (contents->length < (int) string.length() ? contents->length : (int) string.length());
+
+    while (o1 < end) {
+        if ((result = contents->value[o1++] - string.at(o2++)) != 0) {
+            return result;
         }
+    }
 
-        return NULL;
+    return contents->length - (int)string.length();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::compareTo(const char* string) const {
+
+    if (string == NULL) {
+        throw NullPointerException(__FILE__, __LINE__, "Comparison C String cannot be NULL");
     }
-    DECAF_CATCH_RETHROW(IndexOutOfBoundsException)
-    DECAF_CATCHALL_THROW(IndexOutOfBoundsException)
+
+    int length = StringUtils::stringLength(string);
+
+    int o1 = contents->offset;
+    int o2 = 0;
+    int result;
+
+    int end = contents->offset +
+        (contents->length < length ? contents->length : length);
+
+    while (o1 < end) {
+        if ((result = contents->value[o1++] - string[o2++]) != 0) {
+            return result;
+        }
+    }
+
+    return contents->length - length;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-std::string String::toString() const {
+int String::compareToIgnoreCase(const String& string) const {
 
-    if( this->contents->value == NULL ) {
-        return "null";
+    int o1 = contents->offset;
+    int o2 = string.contents->offset;
+    int result;
+
+    int end = contents->offset +
+        (contents->length < string.contents->length ? contents->length : string.contents->length);
+    char c1, c2;
+
+    while (o1 < end) {
+        if ((c1 = contents->value[o1++]) == (c2 = string.contents->value[o2++])) {
+            continue;
+        }
+        c1 = Character::toLowerCase(c1);
+        c2 = Character::toLowerCase(c2);
+        if ((result = c1 - c2) != 0) {
+            return result;
+        }
     }
 
-    return std::string((const char*) this->contents->value.get(), this->length());
+    return contents->length - string.contents->length;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-String String::valueOf(bool value) {
+int String::compareToIgnoreCase(const std::string& string) const {
 
-    if (value) {
-        return String("true");
+    int o1 = contents->offset;
+    int o2 = 0;
+    int result;
+
+    int end = contents->offset +
+        (contents->length < (int) string.length() ? contents->length : (int) string.length());
+    char c1, c2;
+
+    while (o1 < end) {
+        if ((c1 = contents->value[o1++]) == (c2 = string.at(o2++))) {
+            continue;
+        }
+        c1 = Character::toLowerCase(c1);
+        c2 = Character::toLowerCase(c2);
+        if ((result = c1 - c2) != 0) {
+            return result;
+        }
     }
 
-    return String("false");
+    return contents->length - (int) string.length();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-String String::valueOf(char value) {
-    return String(&value, 1);
+int String::compareToIgnoreCase(const char* string) const {
+
+    if (string == NULL) {
+        throw NullPointerException(__FILE__, __LINE__, "Comparison C String cannot be NULL");
+    }
+
+    int length = StringUtils::stringLength(string);
+
+    int o1 = contents->offset;
+    int o2 = 0;
+    int result;
+
+    int end = contents->offset + (contents->length < length ? contents->length : length);
+    char c1, c2;
+
+    while (o1 < end) {
+        if ((c1 = contents->value[o1++]) == (c2 = string[o2++])) {
+            continue;
+        }
+        c1 = Character::toLowerCase(c1);
+        c2 = Character::toLowerCase(c2);
+        if ((result = c1 - c2) != 0) {
+            return result;
+        }
+    }
+
+    return contents->length - length;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-String String::valueOf(float value) {
-    return String(Float::toString(value));
+String String::copyValueOf(const char* data) {
+    if (data == NULL) {
+        throw NullPointerException(__FILE__, __LINE__, "C String to be copied cannot be NULL");
+    }
+
+    return String(data, 0, StringUtils::stringLength(data));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-String String::valueOf(double value) {
-    return String(Double::toString(value));
+String String::copyValueOf(char* data, int start, int length) {
+    if (data == NULL) {
+        throw NullPointerException(__FILE__, __LINE__, "C String to be copied cannot be NULL");
+    }
+
+    return String(data, start, length);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-String String::valueOf(short value) {
-    return String(Short::toString(value));
+String String::concat(const String& string) const {
+
+    if (string.contents->length == 0) {
+        return *this;
+    }
+
+    Contents buffer(contents->length + string.contents->length);
+
+    if (contents->length > 0) {
+        System::arraycopy(contents->value.get(), contents->offset,
+                          buffer.value.get(), 0, contents->length);
+    }
+
+    System::arraycopy(string.contents->value.get(), string.contents->offset,
+                      buffer.value.get(), contents->length, string.contents->length);
+
+    return String(&buffer);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-String String::valueOf(int value) {
-    return String(Integer::toString(value));
+String String::concat(const std::string& string) const {
+
+    if (string.length() == 0) {
+        return *this;
+    }
+
+    Contents buffer(contents->length + (int) string.length());
+
+    if (contents->length > 0) {
+        System::arraycopy(contents->value.get(), contents->offset,
+                          buffer.value.get(), 0, contents->length);
+    }
+
+    System::arraycopy((const unsigned char*) string.c_str(),
+                      0, buffer.value.get(), contents->length, string.length());
+
+    return String(&buffer);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-String String::valueOf(long long value) {
-    return String(Long::toString(value));
+String String::concat(const char* string) const {
+
+    if (string == NULL) {
+        return *this;
+    }
+
+    int length = StringUtils::stringLength(string);
+
+    if (length == 0) {
+        return *this;
+    }
+
+    Contents buffer(contents->length + length);
+
+    if (contents->length > 0) {
+        System::arraycopy(contents->value.get(), contents->offset,
+                          buffer.value.get(), 0, contents->length);
+    }
+
+    System::arraycopy((const unsigned char*) string, 0,
+                      buffer.value.get(), contents->length, length);
+
+    return String(&buffer);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::contains(const String& string) const {
+    return indexOf(string) >= 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::contains(const std::string& string) const {
+    return indexOf(string) >= 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::contains(const char* string) const {
+    return indexOf(string) >= 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::endsWith(const String& suffix) const {
+    return regionMatches(contents->length - suffix.contents->length, suffix, 0, suffix.contents->length);
 }
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::equals(const String& other) const {
+
+    if (this == &other) {
+        return true;
+    }
+
+    if (other.isEmpty() && this->isEmpty()) {
+        return true;
+    }
+
+    if (other.length() != this->length()) {
+        return false;
+    }
+
+    // Don't force compute hash code on this instance, if not already done
+    // we will just do a straight compare.
+    int hashCode = contents->hashCode;
+    int otherHashCode = other.contents->hashCode;
+
+    if (hashCode != otherHashCode && hashCode != 0 && otherHashCode != 0) {
+        return false;
+    }
+
+    for (int i = 0; i < contents->length; ++i) {
+        if (contents->value[contents->offset + i] != other.contents->value[other.contents->offset + i]) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::equals(const std::string& other) const {
+
+    if (other.empty() && this->isEmpty()) {
+        return true;
+    }
+
+    if (other.length() != (std::size_t) this->length()) {
+        return false;
+    }
+
+    for (int i = 0; i < contents->length; ++i) {
+        if (contents->value[contents->offset + i] != (unsigned char) other.at(i)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::equals(const char* other) const {
+
+    if (other == NULL) {
+        return false;
+    }
+
+    if (StringUtils::stringLength(other) != this->length()) {
+        return false;
+    }
+
+    for (int i = 0; i < contents->length; ++i) {
+        if (contents->value[contents->offset + i] != (unsigned char) other[i]) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::equalsIgnoreCase(const String& string) const {
+    if (this == &string) {
+        return true;
+    }
+
+    if (contents->length != string.contents->length) {
+        return false;
+    }
+
+    int offsetThis = contents->offset;
+    int offsetOther = string.contents->offset;
+    int end = contents->offset + contents->length;
+
+    char c1, c2;
+    ArrayPointer<unsigned char> target = string.contents->value;
+
+    while (offsetThis < end) {
+        if ((c1 = contents->value[offsetThis++]) != (c2 = target[offsetOther++])) {
+            // If we add support for multibyte strings we need to check both cases
+            // toUpperCase and toLowerCase because of Unicode.
+            if (Character::toUpperCase(c1) != Character::toUpperCase(c2)) {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::equalsIgnoreCase(const std::string& string) const {
+
+    if (contents->length != (int) string.length()) {
+        return false;
+    }
+
+    int offsetThis = contents->offset;
+    int end = contents->offset + contents->length;
+
+    int indexOther = 0;
+    char c1, c2;
+
+    while (offsetThis < end) {
+        if ((c1 = contents->value[offsetThis++]) != (c2 = string.at(indexOther++))) {
+            // If we add support for multibyte strings we need to check both cases
+            // toUpperCase and toLowerCase because of Unicode.
+            if (Character::toUpperCase(c1) != Character::toUpperCase(c2)) {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::equalsIgnoreCase(const char* string) const {
+
+    if (string == NULL) {
+        return false;
+    }
+
+    int stringLen = StringUtils::stringLength(string);
+
+    if (contents->length != stringLen) {
+        return false;
+    }
+
+    int indexOther = 0;
+    int offsetThis = contents->offset;
+    int end = contents->offset + contents->length;
+
+    char c1, c2;
+
+    while (offsetThis < end) {
+        if ((c1 = contents->value[offsetThis++]) != (c2 = string[indexOther++])) {
+            // If we add support for multibyte strings we need to check both cases
+            // toUpperCase and toLowerCase because of Unicode.
+            if (Character::toUpperCase(c1) != Character::toUpperCase(c2)) {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::hashCode() const {
+
+    if (contents->hashCode == 0) {
+        if (contents->length == 0) {
+            return 0;
+        }
+
+        int hash = 0;
+
+        for (int i = contents->offset; i < contents->length + contents->offset; i++) {
+            hash = contents->value[i] + ((hash << 5) - hash);
+        }
+        contents->hashCode = hash;
+    }
+    return contents->hashCode;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::isEmpty() const {
+    return this->contents->length == 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::isNullOrEmpty(const char* string) {
+    return string == NULL || StringUtils::stringLength(string) == 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::indexOf(char value) const {
+    return indexOf(value, 0);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::indexOf(char value, int start) const {
+    if (start < contents->length) {
+        if (start < 0) {
+            start = 0;
+        }
+
+        for (int i = contents->offset + start; i < contents->offset + contents->length; i++) {
+            if (contents->value[i] == value) {
+                return i - contents->offset;
+            }
+        }
+    }
+    return -1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::indexOf(const String& string) const {
+    return indexOf(string, 0);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::indexOf(const String& subString, int start) const {
+
+    if (start < 0) {
+        start = 0;
+    }
+
+    int subCount = subString.contents->length;
+    if (subCount > 0) {
+        if (subCount + start > contents->length) {
+            return -1;
+        }
+
+        unsigned char* target = subString.contents->value.get();
+        int subOffset = subString.contents->offset;
+
+        char firstChar = target[subOffset];
+        int end = subOffset + subCount;
+
+        while (true) {
+            int i = indexOf(firstChar, start);
+            if (i == -1 || subCount + i > contents->length) {
+                return -1; // handles subCount > length() || start >= length()
+            }
+
+            int o1 = contents->offset + i;
+            int o2 = subOffset;
+
+            while (++o2 < end && contents->value[++o1] == target[o2]) {
+                // Intentionally empty
+            }
+            if (o2 == end) {
+                return i;
+            }
+            start = i + 1;
+        }
+    }
+
+    return start < contents->length ? start : contents->length;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::indexOf(const std::string& string) const {
+    return indexOf(string, 0);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::indexOf(const std::string& subString, int start) const {
+
+    if (start < 0) {
+        start = 0;
+    }
+
+    int subCount = (int) subString.length();
+    if (subCount > 0) {
+        if (subCount + start > contents->length) {
+            return -1;
+        }
+
+        const char* target = subString.c_str();
+        char firstChar = target[0];
+        int end = subCount;
+
+        while (true) {
+            int i = indexOf(firstChar, start);
+            if (i == -1 || subCount + i > contents->length) {
+                return -1; // handles subCount > length() || start >= length()
+            }
+
+            int o1 = contents->offset + i;
+            int o2 = 0;
+
+            while (++o2 < end && contents->value[++o1] == target[o2]) {
+                // Intentionally empty
+            }
+            if (o2 == end) {
+                return i;
+            }
+            start = i + 1;
+        }
+    }
+
+    return start < contents->length ? start : contents->length;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::indexOf(const char* string) const {
+    return indexOf(string, 0);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::indexOf(const char* subString, int start) const {
+
+    if (start < 0) {
+        start = 0;
+    }
+
+    if (subString == NULL) {
+        return -1;
+    }
+
+    int subCount = StringUtils::stringLength(subString);
+    if (subCount > 0) {
+        if (subCount + start > contents->length) {
+            return -1;
+        }
+
+        char firstChar = subString[0];
+        int end = subCount;
+
+        while (true) {
+            int i = indexOf(firstChar, start);
+            if (i == -1 || subCount + i > contents->length) {
+                return -1; // handles subCount > length() || start >= length()
+            }
+
+            int o1 = contents->offset + i;
+            int o2 = 0;
+
+            while (++o2 < end && contents->value[++o1] == subString[o2]) {
+                // Intentionally empty
+            }
+            if (o2 == end) {
+                return i;
+            }
+            start = i + 1;
+        }
+    }
+
+    return start < contents->length ? start : contents->length;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::lastIndexOf(char value) const {
+    return lastIndexOf(value, contents->length - 1);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::lastIndexOf(char value, int start) const {
+    if (start >= 0) {
+        if (start >= contents->length) {
+            start = contents->length - 1;
+        }
+
+        for (int i = contents->offset + start; i >= contents->offset; --i) {
+            if (contents->value[i] == value) {
+                return i - contents->offset;
+            }
+        }
+    }
+    return -1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::lastIndexOf(const String& string) const {
+    // Use length instead of length - 1 so lastIndexOf("") answers length
+    return lastIndexOf(string, contents->length);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::lastIndexOf(const String& subString, int start) const {
+    int subCount = subString.contents->length;
+
+    if (subCount <= contents->length && start >= 0) {
+        if (subCount > 0) {
+            if (start > contents->length - subCount) {
+                start = contents->length - subCount;
+            }
+
+            // count and subCount are both >= 1
+            unsigned char* target = subString.contents->value.get();
+            int subOffset = subString.contents->offset;
+            char firstChar = target[subOffset];
+            int end = subOffset + subCount;
+
+            while (true) {
+                int i = lastIndexOf(firstChar, start);
+                if (i == -1) {
+                    return -1;
+                }
+
+                int o1 = contents->offset + i;
+                int o2 = subOffset;
+
+                while (++o2 < end && contents->value[++o1] == target[o2]) {
+                    // Intentionally empty
+                }
+
+                if (o2 == end) {
+                    return i;
+                }
+                start = i - 1;
+            }
+        }
+        return start < contents->length ? start : contents->length;
+    }
+    return -1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::lastIndexOf(const std::string& string) const {
+    // Use length instead of length - 1 so lastIndexOf("") answers length
+    return lastIndexOf(string, contents->length);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::lastIndexOf(const std::string& subString, int start) const {
+    int subCount = (int) subString.length();
+
+    if (subCount <= contents->length && start >= 0) {
+        if (subCount > 0) {
+            if (start > contents->length - subCount) {
+                start = contents->length - subCount;
+            }
+
+            // count and subCount are both >= 1
+            const char* target = subString.c_str();
+            char firstChar = target[0];
+            int end = subCount;
+
+            while (true) {
+                int i = lastIndexOf(firstChar, start);
+                if (i == -1) {
+                    return -1;
+                }
+
+                int o1 = contents->offset + i;
+                int o2 = 0;
+
+                while (++o2 < end && contents->value[++o1] == target[o2]) {
+                    // Intentionally empty
+                }
+
+                if (o2 == end) {
+                    return i;
+                }
+                start = i - 1;
+            }
+        }
+        return start < contents->length ? start : contents->length;
+    }
+    return -1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::lastIndexOf(const char* string) const {
+    // Use length instead of length - 1 so lastIndexOf("") answers length
+    return lastIndexOf(string, contents->length);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::lastIndexOf(const char* subString, int start) const {
+
+    if (subString == NULL) {
+        return -1;
+    }
+
+    int subCount = StringUtils::stringLength(subString);
+
+    if (subCount <= contents->length && start >= 0) {
+        if (subCount > 0) {
+            if (start > contents->length - subCount) {
+                start = contents->length - subCount;
+            }
+
+            // count and subCount are both >= 1
+            char firstChar = subString[0];
+            int end = subCount;
+
+            while (true) {
+                int i = lastIndexOf(firstChar, start);
+                if (i == -1) {
+                    return -1;
+                }
+
+                int o1 = contents->offset + i;
+                int o2 = 0;
+
+                while (++o2 < end && contents->value[++o1] == subString[o2]) {
+                    // Intentionally empty
+                }
+
+                if (o2 == end) {
+                    return i;
+                }
+                start = i - 1;
+            }
+        }
+        return start < contents->length ? start : contents->length;
+    }
+    return -1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int String::length() const {
+    return this->contents->length;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::regionMatches(int thisStart, const String& string, int start, int length) const {
+
+    if (string.contents->length - start < length || start < 0) {
+        return false;
+    }
+
+    if (thisStart < 0 || contents->length - thisStart < length) {
+        return false;
+    }
+
+    if (length <= 0) {
+        return true;
+    }
+
+    int o1 = contents->offset + thisStart;
+    int o2 = string.contents->offset + start;
+
+    for (int i = 0; i < length; ++i) {
+        if (contents->value[o1 + i] != string.contents->value[o2 + i]) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::regionMatches(bool ignoreCase, int thisStart, const String& string, int start, int length) const {
+
+    if (!ignoreCase) {
+        return regionMatches(thisStart, string, start, length);
+    }
+
+    if (thisStart < 0 || length > contents->length - thisStart) {
+        return false;
+    }
+    if (start < 0 || length > string.contents->length - start) {
+        return false;
+    }
+
+    thisStart += contents->offset;
+    start += string.contents->offset;
+    int end = thisStart + length;
+    char c1, c2;
+
+    while (thisStart < end) {
+        if ((c1 = contents->value[thisStart++]) != (c2 = string.contents->value[start++])) {
+            // If we add support for multibyte strings we need to check both cases
+            // toUpperCase and toLowerCase because of Unicode.
+            if (Character::toUpperCase(c1) != Character::toUpperCase(c2)) {
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+String String::replace(char oldChar, char newChar) const {
+
+    int index = indexOf(oldChar, 0);
+    if (index == -1) {
+        return *this;
+    }
+
+    Contents buffer(contents->length);
+
+    System::arraycopy(contents->value.get(), contents->offset, buffer.value.get(), 0, contents->length);
+
+    do {
+        buffer.value[index++] = newChar;
+    } while ((index = indexOf(oldChar, index)) != -1);
+
+    return String(&buffer);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::startsWith(const String& prefix) const {
+    return regionMatches(0, prefix, 0, prefix.contents->length);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool String::startsWith(const String& prefix, int start) const {
+    return regionMatches(start, prefix, 0, prefix.contents->length);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+String String::substring(int start) const {
+
+    if (start == 0) {
+        return *this;
+    }
+
+    if (0 <= start && start <= contents->length) {
+        return String(contents->offset + start, contents->length - start, contents);
+    }
+
+    throw StringIndexOutOfBoundsException(__FILE__, __LINE__, start);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+String String::substring(int start, int end) const {
+
+    if (start == 0 && end == contents->length) {
+        return *this;
+    }
+
+    if (start < 0) {
+        throw StringIndexOutOfBoundsException(__FILE__, __LINE__, start);
+    } else if (start > end) {
+        throw StringIndexOutOfBoundsException(__FILE__, __LINE__, end - start);
+    } else if (end > contents->length) {
+        throw StringIndexOutOfBoundsException(__FILE__, __LINE__, end);
+    }
+
+    // NOTE last character not copied!
+    return String(contents->offset + start, end - start, contents);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+CharSequence* String::subSequence(int start DECAF_UNUSED, int end DECAF_UNUSED) const {
+
+    try {
+
+        if (start > end) {
+            throw IndexOutOfBoundsException(
+                __FILE__, __LINE__, "Start index is greater than end index.");
+        }
+
+        if (end - start > this->length()) {
+            throw IndexOutOfBoundsException(
+                __FILE__, __LINE__, "Requested Range is greater than the String length.");
+        }
+
+        return NULL;
+    }
+    DECAF_CATCH_RETHROW(IndexOutOfBoundsException)
+    DECAF_CATCHALL_THROW(IndexOutOfBoundsException)
+}
+
+////////////////////////////////////////////////////////////////////////////////
+char* String::toCharArray() const {
+    char* buffer = new char[contents->length];
+    System::arraycopy((const char*)contents->value.get(), contents->offset, buffer, 0, contents->length);
+    return buffer;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+String String::toLowerCase() const {
+
+    Contents newContents(contents->length);
+    int offset = contents->offset;
+
+    for (int i = 0; i < contents->length; ++i) {
+        newContents.value[i] = Character::toLowerCase(contents->value[offset + i]);
+    }
+
+    return String(&newContents);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+String String::toUpperCase() const {
+
+    Contents newContents(contents->length);
+    int offset = contents->offset;
+
+    for (int i = 0; i < contents->length; ++i) {
+        newContents.value[i] = Character::toUpperCase(contents->value[offset + i]);
+    }
+
+    return String(&newContents);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+std::string String::toString() const {
+
+    if (this->contents->value == NULL) {
+        return "null";
+    }
+
+    return std::string((const char*) contents->value.get() + contents->offset, this->length());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+String String::trim() const {
+
+    int start = contents->offset;
+    int last = contents->offset + contents->length - 1;
+
+    int end = last;
+
+    while ((start <= end) && (contents->value[start] <= 0x20)) {
+        start++;
+    }
+
+    while ((end >= start) && (contents->value[end] <= 0x20)) {
+        end--;
+    }
+
+    if (start == contents->offset && end == last) {
+        return *this;
+    }
+
+    return String(start, end - start + 1, contents);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+String String::valueOf(bool value) {
+
+    if (value) {
+        return String("true");
+    }
+
+    return String("false");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+String String::valueOf(char value) {
+    return String(&value, 1);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+String String::valueOf(float value) {
+    return String(Float::toString(value));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+String String::valueOf(double value) {
+    return String(Double::toString(value));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+String String::valueOf(short value) {
+    return String(Short::toString(value));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+String String::valueOf(int value) {
+    return String(Integer::toString(value));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+String String::valueOf(long long value) {
+    return String(Long::toString(value));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+namespace decaf {
+namespace lang {
+
+    std::ostream& operator<<(std::ostream &out, const String& target) {
+
+        if (target.isEmpty()) {
+            out << "NULL";
+        }
+
+        for (int i = 0; i < target.length(); ++i) {
+            out << target.charAt(i);
+        }
+
+        return out;
+    }
+
+}}


Mime
View raw message