Dead code/cruft removal in the collation code.

I've also renamed ScopedUtfChars::data to ScopedUtfChars::c_str, by analogy
with std::string (since this method has always been more like c_str than data).

This also fixes a few leaks on error paths.

The old code used to go all the way into native code to return a constant hash
code of 1, so I've removed all that and switched to the idiomatic bogo hash
code (with the idiomatic comment).

Change-Id: I25da8c422155860b5ab348786d369c6c7598135c
diff --git a/libcore/icu/src/main/java/com/ibm/icu4jni/text/Collator.java b/libcore/icu/src/main/java/com/ibm/icu4jni/text/Collator.java
index 7883d30..9eb85ea 100644
--- a/libcore/icu/src/main/java/com/ibm/icu4jni/text/Collator.java
+++ b/libcore/icu/src/main/java/com/ibm/icu4jni/text/Collator.java
@@ -13,64 +13,6 @@
 import com.ibm.icu4jni.text.RuleBasedCollator;
 import java.util.Locale;
 
-/**
-* Abstract class handling locale specific collation via JNI and ICU.
-* Subclasses implement specific collation strategies. One subclass,
-* com.ibm.icu4jni.text.RuleBasedCollator, is currently provided and is
-* applicable to a wide set of languages. Other subclasses may be created to
-* handle more specialized needs.
-* You can use the static factory method, getInstance(), to obtain the
-* appropriate Collator object for a given locale.
-*
-* <pre>
-* // Compare two strings in the default locale
-* Collator myCollator = Collator.getInstance();
-* if (myCollator.compare("abc", "ABC") < 0) {
-*   System.out.println("abc is less than ABC");
-* }
-* else {
-*   System.out.println("abc is greater than or equal to ABC");
-* }
-* </pre>
-*
-* You can set a Collator's strength property to determine the level of
-* difference considered significant in comparisons.
-* Five strengths in CollationAttribute are provided: VALUE_PRIMARY,
-* VALUE_SECONDARY, VALUE_TERTIARY, VALUE_QUATERNARY and VALUE_IDENTICAL.
-* The exact assignment of strengths to language features is locale-dependent.
-* For example, in Czech, "e" and "f" are considered primary differences, while
-* "e" and "?" latin small letter e with circumflex are secondary differences,
-* "e" and "E" are tertiary differences and "e" and "e" are identical.
-*
-* <p>
-* The following shows how both case and accents could be ignored for US
-* English.
-* <pre>
-* //Get the Collator for US English and set its strength to PRIMARY
-* Collator usCollator = Collator.getInstance(Locale.US);
-* usCollator.setStrength(Collator.PRIMARY);
-* if (usCollator.compare("abc", "ABC") == 0) {
-*   System.out.println("Strings are equivalent");
-* }
-* </pre>
-* For comparing Strings exactly once, the compare method provides the best
-* performance.
-* When sorting a list of Strings however, it is generally necessary to compare
-* each String multiple times.
-* In this case, com.ibm.icu4jni.text.CollationKey provide better performance.
-* The CollationKey class converts a String to a series of bits that can be
-* compared bitwise against other CollationKeys.
-* A CollationKey is created by a Collator object for a given String.
-* Note: CollationKeys from different Collators can not be compared.
-* </p>
-*
-* Considerations :
-* 1) ErrorCode not returned to user throw exceptions instead
-* 2) Similar API to java.text.Collator
-* @author syn wee quek
-* @stable ICU 2.4
-*/
-
 public abstract class Collator implements Cloneable {
     /**
      * Strongest collator strength value. Typically used to denote differences
@@ -164,28 +106,8 @@
      */
     public final static int CANONICAL_DECOMPOSITION = CollationAttribute.VALUE_ON;
 
-    public static Collator getInstance() {
-        return getInstance(null);
-    }
-
-    /**
-     * Factory method to create an appropriate Collator which uses the given
-     * locale's collation rules.<br>
-     * Current implementation createInstance() returns a RuleBasedCollator(Locale)
-     * instance. The RuleBasedCollator will be created in the following order,
-     * <ul>
-     * <li> Data from argument locale resource bundle if found, otherwise
-     * <li> Data from parent locale resource bundle of given locale if found, otherwise
-     * <li> Data from built-in default collation rules if found, other
-     * <li> null is returned
-     * </ul>
-     * @param locale to be used for collation
-     * @return an instance of Collator
-     * @stable ICU 2.4
-     */
     public static Collator getInstance(Locale locale) {
-        RuleBasedCollator result = new RuleBasedCollator(locale);
-        return result;
+        return new RuleBasedCollator(locale);
     }
 
     public boolean equals(String source, String target) {
diff --git a/libcore/icu/src/main/java/com/ibm/icu4jni/text/NativeCollation.java b/libcore/icu/src/main/java/com/ibm/icu4jni/text/NativeCollation.java
index fbdcf93..d481790 100644
--- a/libcore/icu/src/main/java/com/ibm/icu4jni/text/NativeCollation.java
+++ b/libcore/icu/src/main/java/com/ibm/icu4jni/text/NativeCollation.java
@@ -23,14 +23,7 @@
   public NativeCollation() {
       
   }
-    
-  /**
-  * Method to create a new C Collator using the default locale rules.
-  * @return new c collator
-  * @internal ICU 2.4
-  */
-  static native int openCollator();
-  
+
   /**
   * Method to create a new C Collator using the argument locale rules.
   * @param locale locale name
@@ -160,14 +153,6 @@
   */
   static native int getCollationElementIterator(int collatoraddress, 
                                                  String source);
-                                                 
-  /**
-  * Returns a hash of this collation object
-  * @param collatoraddress address of C collator
-  * @return hash of this collation object
-  * @internal ICU 2.4
-  */
-  static native int hashCode(int collatoraddress);
 
     
   // collationelementiterator methods -------------------------------------
diff --git a/libcore/icu/src/main/java/com/ibm/icu4jni/text/RuleBasedCollator.java b/libcore/icu/src/main/java/com/ibm/icu4jni/text/RuleBasedCollator.java
index 3135daa..8e048dd 100644
--- a/libcore/icu/src/main/java/com/ibm/icu4jni/text/RuleBasedCollator.java
+++ b/libcore/icu/src/main/java/com/ibm/icu4jni/text/RuleBasedCollator.java
@@ -454,20 +454,6 @@
         return NativeCollation.getAttribute(m_collator_, type);
     }
 
-    /**
-     * Get the sort key as an CollationKey object from the argument string.
-     * To retrieve sort key in terms of byte arrays, use the method as below<br>
-     * <br>
-     * <code>
-     * Collator collator = Collator.getInstance();
-     * byte[] array = collator.getSortKey(source);
-     * </code><br>
-     * Byte array result are zero-terminated and can be compared using
-     * java.util.Arrays.equals();
-     * @param source string to be processed.
-     * @return the sort key
-     * @stable ICU 2.4
-     */
     public CollationKey getCollationKey(String source) {
         if (source == null) {
             return null;
@@ -480,17 +466,6 @@
     }
 
     /**
-     * Get a sort key for the argument string
-     * Sort keys may be compared using java.util.Arrays.equals
-     * @param source string for key to be generated
-     * @return sort key
-     * @stable ICU 2.4
-     */
-    public byte[] getSortKey(String source) {
-        return NativeCollation.getSortKey(m_collator_, source);
-    }
-
-    /**
      * Get the collation rules of this Collation object
      * The rules will follow the rule syntax.
      * @return collation rules.
@@ -529,21 +504,9 @@
         return result.toString();
     }
 
-    /**
-     * Returns a hash of this collation object
-     * Note this method is not complete, it only returns 0 at the moment.
-     * @return hash of this collation object
-     * @stable ICU 2.4
-     */
+    @Override
     public int hashCode() {
-        // since rules do not change once it is created, we can cache the hash
-        if (m_hashcode_ == 0) {
-            m_hashcode_ = NativeCollation.hashCode(m_collator_);
-            if (m_hashcode_ == 0) {
-                m_hashcode_ = 1;
-            }
-        }
-        return m_hashcode_;
+        return 42; // No-one uses RuleBasedCollator as a hash key.
     }
 
     /**
@@ -565,50 +528,16 @@
                 getDecomposition() == rhs.getDecomposition();
     }
 
-    /**
-     * RuleBasedCollator default constructor. This constructor takes the default
-     * locale. The only caller of this class should be Collator.getInstance().
-     * Current implementation createInstance() returns a RuleBasedCollator(Locale)
-     * instance. The RuleBasedCollator will be created in the following order,
-     * <ul>
-     * <li> Data from argument locale resource bundle if found, otherwise
-     * <li> Data from parent locale resource bundle of arguemtn locale if found,
-     *      otherwise
-     * <li> Data from built-in default collation rules if found, other
-     * <li> null is returned
-     * </ul>
-     */
-    RuleBasedCollator() {
-        m_collator_ = NativeCollation.openCollator();
-    }
-
-    /**
-     * RuleBasedCollator constructor. This constructor takes a locale. The
-     * only caller of this class should be Collator.createInstance().
-     * Current implementation createInstance() returns a RuleBasedCollator(Locale)
-     * instance. The RuleBasedCollator will be created in the following order,
-     * <ul>
-     * <li> Data from argument locale resource bundle if found, otherwise
-     * <li> Data from parent locale resource bundle of arguemtn locale if found,
-     *      otherwise
-     * <li> Data from built-in default collation rules if found, other
-     * <li> null is returned
-     * </ul>
-     * @param locale locale used
-     */
     RuleBasedCollator(Locale locale) {
-        if (locale == null) {
-            m_collator_ = NativeCollation.openCollator();
-        } else {
-            m_collator_ = NativeCollation.openCollator(locale.toString());
-        }
+        m_collator_ = NativeCollation.openCollator(locale.toString());
     }
 
+    @Override
     protected void finalize() {
         NativeCollation.closeCollator(m_collator_);
     }
 
-    private RuleBasedCollator(int collatoraddress) {
-        m_collator_ = collatoraddress;
+    private RuleBasedCollator(int addr) {
+        m_collator_ = addr;
     }
 }
diff --git a/libcore/icu/src/main/native/ICU.cpp b/libcore/icu/src/main/native/ICU.cpp
index 1517932..4f08513 100644
--- a/libcore/icu/src/main/native/ICU.cpp
+++ b/libcore/icu/src/main/native/ICU.cpp
@@ -70,7 +70,7 @@
 };
 
 static Locale getLocale(JNIEnv* env, jstring localeName) {
-    return Locale::createFromName(ScopedUtfChars(env, localeName).data());
+    return Locale::createFromName(ScopedUtfChars(env, localeName).c_str());
 }
 
 static jint getCurrencyFractionDigitsNative(JNIEnv* env, jclass, jstring currencyCode) {
@@ -528,7 +528,7 @@
     ScopedUtfChars localeChars(env, locale);
 
     // Extract the 2-character country name.
-    if (strlen(localeChars.data()) < 5) {
+    if (strlen(localeChars.c_str()) < 5) {
         return NULL;
     }
     if (localeChars[3] < 'A' || localeChars[3] > 'Z' || localeChars[4] < 'A' || localeChars[4] > 'Z') {
diff --git a/libcore/icu/src/main/native/NativeBreakIterator.cpp b/libcore/icu/src/main/native/NativeBreakIterator.cpp
index 85ada2d..0be7630 100644
--- a/libcore/icu/src/main/native/NativeBreakIterator.cpp
+++ b/libcore/icu/src/main/native/NativeBreakIterator.cpp
@@ -26,10 +26,10 @@
 static jint getIterator(JNIEnv* env, jstring locale, UBreakIteratorType type) {
     UErrorCode status = U_ZERO_ERROR;
     ScopedUtfChars localeChars(env, locale);
-    if (!localeChars.data()) {
+    if (!localeChars.c_str()) {
         return 0;
     }
-    UBreakIterator* it = ubrk_open(type, localeChars.data(), NULL, 0, &status);
+    UBreakIterator* it = ubrk_open(type, localeChars.c_str(), NULL, 0, &status);
     icu4jni_error(env, status);
     return reinterpret_cast<uintptr_t>(it);
 }
diff --git a/libcore/icu/src/main/native/NativeCollation.cpp b/libcore/icu/src/main/native/NativeCollation.cpp
index 263a525..9a092e8 100644
--- a/libcore/icu/src/main/native/NativeCollation.cpp
+++ b/libcore/icu/src/main/native/NativeCollation.cpp
@@ -9,497 +9,170 @@
 
 #define LOG_TAG "NativeCollation"
 
-#include "JNIHelp.h"
 #include "ErrorCode.h"
+#include "JNIHelp.h"
+#include "ScopedJavaUnicodeString.h"
+#include "ScopedUtfChars.h"
+#include "UniquePtr.h"
+#include "ucol_imp.h"
 #include "unicode/ucol.h"
 #include "unicode/ucoleitr.h"
-#include "ucol_imp.h"
 
-
-/**
-* Closing a C UCollator with the argument locale rules.
-* Note determining if a collator currently exist for the caller is to be handled
-* by the caller. Hence if the caller has a existing collator, it is his 
-* responsibility to delete first before calling this method.
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @param address of the C UCollator
-*/
-static void closeCollator(JNIEnv *env, jclass obj,
-        jint address) { 
-
-  UCollator *collator = (UCollator *)(int)address;
-  ucol_close(collator);
+static UCollator* toCollator(jint address) {
+    return reinterpret_cast<UCollator*>(static_cast<uintptr_t>(address));
 }
 
-
-/**
-* Close a C collation element iterator.
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @param address of C collation element iterator to close.
-*/
-static void closeElements(JNIEnv *env, jclass obj,
-        jint address) {
-
-  UCollationElements *iterator = (UCollationElements *)(int)address;
-  ucol_closeElements(iterator);
+static UCollationElements* toCollationElements(jint address) {
+    return reinterpret_cast<UCollationElements*>(static_cast<uintptr_t>(address));
 }
 
-/**
-* Compare two strings.
-* The strings will be compared using the normalization mode and options
-* specified in openCollator or openCollatorFromRules
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @param address address of the c collator
-* @param source The source string.
-* @param target The target string.
-* @return result of the comparison, UCOL_EQUAL, UCOL_GREATER or UCOL_LESS
-*/
-static jint compare(JNIEnv *env, jclass obj, jint address,
-        jstring source, jstring target) {
+static void closeCollator(JNIEnv* env, jclass, jint address) {
+    ucol_close(toCollator(address));
+}
 
-    const UCollator *collator  = (const UCollator *)(int)address;
-    jint result = -2;
-    if(collator){
-        jsize       srcLength = env->GetStringLength(source);
-        const UChar *chars   = (const UChar *) env->GetStringCritical(source,0);
-        if(chars){
-            jsize       tgtlength = env->GetStringLength(target);
-            const UChar *tgtstr    = (const UChar *) env->GetStringCritical(target,0);
-            if(tgtstr){ 
-                  result = ucol_strcoll(collator, chars, srcLength, tgtstr, tgtlength);
-                  env->ReleaseStringCritical(source, chars);
-                  env->ReleaseStringCritical(target, tgtstr);
-                  return result;
-            }else{
-                icu4jni_error(env,U_ILLEGAL_ARGUMENT_ERROR);
-            }
-        }else{
-            icu4jni_error(env,U_ILLEGAL_ARGUMENT_ERROR);
-        }
-    }else{
-        icu4jni_error(env,U_ILLEGAL_ARGUMENT_ERROR);
+static void closeElements(JNIEnv* env, jclass, jint address) {
+    ucol_closeElements(toCollationElements(address));
+}
+
+static jint compare(JNIEnv* env, jclass, jint address, jstring lhs0, jstring rhs0) {
+    ScopedJavaUnicodeString lhs(env, lhs0);
+    ScopedJavaUnicodeString rhs(env, rhs0);
+    return ucol_strcoll(toCollator(address),
+            lhs.unicodeString().getBuffer(), lhs.unicodeString().length(),
+            rhs.unicodeString().getBuffer(), rhs.unicodeString().length());
+}
+
+static jint getAttribute(JNIEnv* env, jclass, jint address, jint type) {
+    UErrorCode status = U_ZERO_ERROR;
+    jint result = ucol_getAttribute(toCollator(address), (UColAttribute) type, &status);
+    icu4jni_error(env, status);
+    return result;
+}
+
+static jint getCollationElementIterator(JNIEnv* env, jclass, jint address, jstring source0) {
+    ScopedJavaUnicodeString source(env, source0);
+    UErrorCode status = U_ZERO_ERROR;
+    UCollationElements* result = ucol_openElements(toCollator(address),
+            source.unicodeString().getBuffer(), source.unicodeString().length(), &status);
+    icu4jni_error(env, status);
+    return static_cast<jint>(reinterpret_cast<uintptr_t>(result));
+}
+
+static jint getMaxExpansion(JNIEnv* env, jclass, jint address, jint order) {
+    return ucol_getMaxExpansion(toCollationElements(address), order);
+}
+
+static jint getNormalization(JNIEnv* env, jclass, jint address) {
+    UErrorCode status = U_ZERO_ERROR;
+    jint result = ucol_getAttribute(toCollator(address), UCOL_NORMALIZATION_MODE, &status);
+    icu4jni_error(env, status);
+    return result;
+}
+
+static void setNormalization(JNIEnv* env, jclass, jint address, jint mode) {
+    UErrorCode status = U_ZERO_ERROR;
+    ucol_setAttribute(toCollator(address), UCOL_NORMALIZATION_MODE, UColAttributeValue(mode), &status);
+    icu4jni_error(env, status);
+}
+
+static jint getOffset(JNIEnv* env, jclass, jint address) {
+    return ucol_getOffset(toCollationElements(address));
+}
+
+static jstring getRules(JNIEnv* env, jclass, jint address) {
+    int32_t length = 0;
+    const UChar* rules = ucol_getRules(toCollator(address), &length);
+    return env->NewString(rules, length);
+}
+
+static jbyteArray getSortKey(JNIEnv* env, jclass, jint address, jstring source0) {
+    ScopedJavaUnicodeString source(env, source0);
+    const UCollator* collator  = toCollator(address);
+    uint8_t byteArray[UCOL_MAX_BUFFER * 2];
+    UniquePtr<uint8_t[]> largerByteArray;
+    uint8_t *usedByteArray = byteArray;
+    const UChar* chars = source.unicodeString().getBuffer();
+    size_t charCount = source.unicodeString().length();
+    size_t byteArraySize = ucol_getSortKey(collator, chars, charCount, usedByteArray, sizeof(byteArray) - 1);
+    if (byteArraySize > sizeof(byteArray) - 1) {
+        // didn't fit, try again with a larger buffer.
+        largerByteArray.reset(new uint8_t[byteArraySize + 1]);
+        usedByteArray = largerByteArray.get();
+        byteArraySize = ucol_getSortKey(collator, chars, charCount, usedByteArray, byteArraySize);
     }
-    return result;
-}
-
-static jint getAttribute(JNIEnv *env, jclass, jint address, jint type) {
-    const UCollator *collator = (const UCollator *)(int)address;
-    if (!collator) {
-        icu4jni_error(env, U_ILLEGAL_ARGUMENT_ERROR);
-        return 0;
+    if (byteArraySize == 0) {
+        return NULL;
     }
+    jbyteArray result = env->NewByteArray(byteArraySize);
+    env->SetByteArrayRegion(result, 0, byteArraySize, reinterpret_cast<jbyte*>(usedByteArray));
+    return result;
+}
+
+static jint next(JNIEnv* env, jclass, jint address) {
     UErrorCode status = U_ZERO_ERROR;
-    jint result = (jint)ucol_getAttribute(collator, (UColAttribute)type, &status);
+    jint result = ucol_next(toCollationElements(address), &status);
     icu4jni_error(env, status);
     return result;
 }
 
-/** 
-* Create a CollationElementIterator object that will iterator over the elements 
-* in a string, using the collation rules defined in this RuleBasedCollatorJNI
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @param address address of C collator
-* @param source string to iterate over
-* @return address of C collationelement
-*/
-static jint getCollationElementIterator(JNIEnv *env,
-        jclass obj, jint address, jstring source) {
-
-    UErrorCode status    = U_ZERO_ERROR;
-    UCollator *collator  = (UCollator *)(int)address;
-    jint       result=0;
-    if(collator){
-        jsize srcLength     = env->GetStringLength(source);
-        const UChar *chars = (const UChar *) env->GetStringCritical(source,0);
-        if(chars){
-            result = (jint)(ucol_openElements(collator, chars, srcLength, &status));
-
-            env->ReleaseStringCritical(source, chars);
-            icu4jni_error(env, status);
-        }else{
-            icu4jni_error(env, U_ILLEGAL_ARGUMENT_ERROR);
-        }
-    }else{
-        icu4jni_error(env, U_ILLEGAL_ARGUMENT_ERROR);
-    }
-    return result;
-}
-
-/**
-* Get the maximum length of any expansion sequences that end with the specified 
-* comparison order.
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @param address of the C collation element iterator containing the text.
-* @param order collation order returned by previous or next.
-* @return maximum length of any expansion sequences ending with the specified 
-*         order or 1 if collation order does not occur at the end of any 
-*         expansion sequence.
-*/
-static jint getMaxExpansion(JNIEnv *env, jclass obj,
-        jint address, jint order) {
-
-  UCollationElements *iterator = (UCollationElements *)(int)address;
-  return ucol_getMaxExpansion(iterator, order);
-}
-
-/**
-* Get the normalization mode for this object.
-* The normalization mode influences how strings are compared.
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @param address of C collator
-* @return normalization mode; one of the values from NormalizerEnum
-*/
-static jint getNormalization(JNIEnv *env, jclass obj,
-        jint address) {
-
-    const UCollator* collator = (const UCollator*) address;
+static jint openCollator(JNIEnv* env, jclass, jstring localeName) {
+    ScopedUtfChars localeChars(env, localeName);
     UErrorCode status = U_ZERO_ERROR;
-    jint result = ucol_getAttribute(collator, UCOL_NORMALIZATION_MODE, &status);
+    UCollator* c = ucol_open(localeChars.c_str(), &status);
+    icu4jni_error(env, status);
+    return static_cast<jint>(reinterpret_cast<uintptr_t>(c));
+}
+
+static jint openCollatorFromRules(JNIEnv* env, jclass, jstring rules0, jint mode, jint strength) {
+    ScopedJavaUnicodeString rules(env, rules0);
+    UErrorCode status = U_ZERO_ERROR;
+    UCollator* c = ucol_openRules(rules.unicodeString().getBuffer(), rules.unicodeString().length(),
+            UColAttributeValue(mode), UCollationStrength(strength), NULL, &status);
+    icu4jni_error(env, status);
+    return static_cast<jint>(reinterpret_cast<uintptr_t>(c));
+}
+
+static jint previous(JNIEnv* env, jclass, jint address) {
+    UErrorCode status = U_ZERO_ERROR;
+    jint result = ucol_previous(toCollationElements(address), &status);
     icu4jni_error(env, status);
     return result;
 }
 
-/**
-* Set the normalization mode for this object.
-* The normalization mode influences how strings are compared.
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @param address of C collator
-* @param mode the normalization mode
-*/
-static void setNormalization(JNIEnv *env, jclass, jint address, jint mode) {
-    UCollator* collator = reinterpret_cast<UCollator*>(static_cast<uintptr_t>(address));
+static void reset(JNIEnv* env, jclass, jint address) {
+    ucol_reset(toCollationElements(address));
+}
+
+static jint safeClone(JNIEnv* env, jclass, jint address) {
     UErrorCode status = U_ZERO_ERROR;
-    ucol_setAttribute(collator, UCOL_NORMALIZATION_MODE, UColAttributeValue(mode), &status);
+    jint bufferSize = U_COL_SAFECLONE_BUFFERSIZE;
+    UCollator* c = ucol_safeClone(toCollator(address), NULL, &bufferSize, &status);
+    icu4jni_error(env, status);
+    return static_cast<jint>(reinterpret_cast<uintptr_t>(c));
+}
+
+static void setAttribute(JNIEnv* env, jclass, jint address, jint type, jint value) {
+    UErrorCode status = U_ZERO_ERROR;
+    ucol_setAttribute(toCollator(address), (UColAttribute)type, (UColAttributeValue)value, &status);
     icu4jni_error(env, status);
 }
 
-
-/**
-* Get the offset of the current source character.
-* This is an offset into the text of the character containing the current
-* collation elements.
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @param addresss of the C collation elements iterator to query.
-* @return offset of the current source character.
-*/
-static jint getOffset(JNIEnv *env, jclass obj, jint address) {
-
-  UCollationElements *iterator = (UCollationElements *)(int)address;
-  return ucol_getOffset(iterator);
-}
-
-/**
-* Get the collation rules from a UCollator.
-* The rules will follow the rule syntax.
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @param address the address of the C collator
-* @return collation rules.
-*/
-static jstring getRules(JNIEnv *env, jclass obj,
-        jint address) {
-
-  const UCollator *collator = (const UCollator *)(int)address;
-  int32_t length=0;
-  const UChar *rules = ucol_getRules(collator, &length);
-  return env->NewString(rules, length);
-}
-
-/**
-* Get a sort key for the argument string
-* Sort keys may be compared using java.util.Arrays.equals
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @param address address of the C collator
-* @param source string for key to be generated
-* @return sort key
-*/
-static jbyteArray getSortKey(JNIEnv *env, jclass obj,
-        jint address, jstring source) {
-
-  const UCollator *collator  = (const UCollator *)(int)address;
-  jbyteArray result = NULL;
-  if(collator && source){
-      // BEGIN android-added
-      if(!source) {
-          return NULL;
-      }
-      // END android-added
-      jsize srcLength = env->GetStringLength(source);
-      const UChar *chars = (const UChar *) env->GetStringCritical(source, 0);
-      if (chars){
-// BEGIN android-changed
-          uint8_t byteArray[UCOL_MAX_BUFFER * 2];
-          uint8_t *largerByteArray = NULL;
-          uint8_t *usedByteArray = byteArray;
-  
-          size_t byteArraySize = ucol_getSortKey(collator, chars, srcLength, byteArray,
-                  sizeof(byteArray) - 1);
- 
-          if (byteArraySize > sizeof(byteArray) - 1) {
-              // didn't fit, try again with a larger buffer.
-              largerByteArray = new uint8_t[byteArraySize + 1];
-              usedByteArray = largerByteArray;
-              byteArraySize = ucol_getSortKey(collator, chars, srcLength, largerByteArray,
-                      byteArraySize);
-          }
- 
-          env->ReleaseStringCritical(source, chars);
-
-          if (byteArraySize == 0) {
-              delete[] largerByteArray;
-              return NULL;
-          }
-  
-          /* no problem converting uint8_t to int8_t, gives back the correct value
-           * tried and tested
-           */
-          result = env->NewByteArray(byteArraySize);
-          env->SetByteArrayRegion(result, 0, byteArraySize, reinterpret_cast<jbyte*>(usedByteArray));
-          delete[] largerByteArray;
-// END android-changed
-      }else{
-          icu4jni_error(env,U_ILLEGAL_ARGUMENT_ERROR);
-      }
-  }else{
-    icu4jni_error(env,U_ILLEGAL_ARGUMENT_ERROR);
-  }
-  return result;
-}
-
-/**
-* Returns a hash of this collation object
-* Note this method is not complete, it only returns 0 at the moment.
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @param address address of C collator
-* @return hash of this collation object
-*/
-static jint hashCode(JNIEnv *env, jclass obj, jint address) {
-	
-  UCollator *collator = (UCollator *)(int)address;
-  int32_t length=0;
-  const UChar *rules = ucol_getRules(collator, &length);
-  /* temporary commented out
-   * return uhash_hashUCharsN(rules, length);
-   */
-  return 0;
-}
-
-/**
-* Get the ordering priority of the next collation element in the text.
-* A single character may contain more than one collation element.
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @param address if C collation elements containing the text.
-* @return next collation elements ordering, otherwise returns NULLORDER if an 
-*         error has occured or if the end of string has been reached
-*/
-static jint next(JNIEnv *env, jclass obj, jint address) {
-    UCollationElements *iterator = (UCollationElements *) address;
+static void setOffset(JNIEnv* env, jclass, jint address, jint offset) {
     UErrorCode status = U_ZERO_ERROR;
-    jint result = ucol_next(iterator, &status);
-    icu4jni_error(env, status);
-    return result;
-}
-
-/**
-* Opening a new C UCollator with the default locale.
-* Note determining if a collator currently exist for the caller is to be handled
-* by the caller. Hence if the caller has a existing collator, it is his 
-* responsibility to delete first before calling this method.
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @return address of the new C UCollator
-* @exception thrown if creation of the UCollator fails
-*/
-static jint openCollator__(JNIEnv *env, jclass obj) {
-    UErrorCode status = U_ZERO_ERROR;
-    UCollator* result = ucol_open(NULL, &status);
-    icu4jni_error(env, status);
-    return reinterpret_cast<uintptr_t>(result);
-}
-
-
-/**
-* Opening a new C UCollator with the argument locale rules.
-* Note determining if a collator currently exist for the caller is to be handled
-* by the caller. Hence if the caller has a existing collator, it is his 
-* responsibility to delete first before calling this method.
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @param locale name
-* @return address of the new C UCollator
-* @exception thrown if creation of the UCollator fails
-*/
-static jint openCollator__Ljava_lang_String_2(JNIEnv *env,
-        jclass obj, jstring locale) {
-
-    /* this will be null terminated */
-    const char* localeStr = env->GetStringUTFChars(locale, NULL);
-    if (localeStr == NULL) {
-        icu4jni_error(env, U_ILLEGAL_ARGUMENT_ERROR);
-        return 0;
-    }
-
-    UErrorCode status = U_ZERO_ERROR;
-    UCollator* result = ucol_open(localeStr, &status);
-    env->ReleaseStringUTFChars(locale, localeStr);
-    icu4jni_error(env, status);
-    return reinterpret_cast<uintptr_t>(result);
-}
-
-/**
-* Opening a new C UCollator with the argument locale rules.
-* Note determining if a collator currently exist for the caller is to be 
-* handled by the caller. Hence if the caller has a existing collator, it is his 
-* responsibility to delete first before calling this method.
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @param rules set of collation rules
-* @param normalizationmode normalization mode
-* @param strength collation strength
-* @return address of the new C UCollator
-* @exception thrown if creation of the UCollator fails
-*/
-static jint openCollatorFromRules(JNIEnv *env, jclass obj,
-        jstring rules, jint normalizationmode, jint strength) {
-
-  jsize  ruleslength    = env->GetStringLength(rules);
-  const UChar *rulestr  = (const UChar *) env->GetStringCritical(rules, 0);
-  UErrorCode status     = U_ZERO_ERROR;
-  jint   result        = 0;
-  if(rulestr){
-      result = (jint)ucol_openRules(rulestr, ruleslength, 
-                                   (UColAttributeValue)normalizationmode,
-                                   (UCollationStrength)strength, NULL, &status);
-
-      env->ReleaseStringCritical(rules, rulestr);
-      icu4jni_error(env, status);
-  }else{
-      icu4jni_error(env,U_ILLEGAL_ARGUMENT_ERROR);
-  }
-
-  return result;
-}
-
-/**
-* Get the ordering priority of the previous collation element in the text.
-* A single character may contain more than one collation element.
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @param address of the C collation element iterator containing the text.
-* @return previous collation element ordering, otherwise returns NULLORDER if 
-*         an error has occured or if the start of string has been reached
-* @exception thrown when retrieval of previous collation element fails.
-*/
-static jint previous(JNIEnv *env, jclass obj, jint address) {
-
-  UCollationElements *iterator = (UCollationElements *)(int)address;
-  UErrorCode status = U_ZERO_ERROR;
-  jint result = ucol_previous(iterator, &status);
-
-   icu4jni_error(env, status);
-  return result;
-}
-
-
-/**
-* Reset the collation elements to their initial state.
-* This will move the 'cursor' to the beginning of the text.
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @param address of C collation element iterator to reset.
-*/
-static void reset(JNIEnv *env, jclass obj, jint address) {
-
-  UCollationElements *iterator = (UCollationElements *)(int)address;
-  ucol_reset(iterator);
-}
-
-/**
-* Thread safe cloning operation
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @param address address of C collator to be cloned
-* @return address of the new clone
-* @exception thrown when error occurs while cloning
-*/
-static jint safeClone(JNIEnv *env, jclass obj, jint address) {
-
-  const UCollator *collator = (const UCollator *)(int)address;
-  UErrorCode status = U_ZERO_ERROR;
-  jint result;
-  jint buffersize = U_COL_SAFECLONE_BUFFERSIZE;
-
-  result = (jint)ucol_safeClone(collator, NULL, &buffersize, &status);
-
-  if ( icu4jni_error(env, status) != FALSE) {
-    return 0;
-  }
- 
-  return result;
-}
-
-static void setAttribute(JNIEnv *env, jclass, jint address, jint type, jint value) {
-    UCollator *collator = (UCollator *)(int)address;
-    UErrorCode status = U_ZERO_ERROR;
-    ucol_setAttribute(collator, (UColAttribute)type, (UColAttributeValue)value, &status);
+    ucol_setOffset(toCollationElements(address), offset, &status);
     icu4jni_error(env, status);
 }
 
-/**
-* Set the offset of the current source character.
-* This is an offset into the text of the character to be processed.
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @param address of the C collation element iterator to set.
-* @param offset The desired character offset.
-* @exception thrown when offset setting fails
-*/
-static void setOffset(JNIEnv *env, jclass obj, jint address,
-        jint offset) {
-
-  UCollationElements *iterator = (UCollationElements *)(int)address;
-  UErrorCode status = U_ZERO_ERROR;
-
-  ucol_setOffset(iterator, offset, &status);
-   icu4jni_error(env, status);
-}
-
-/**
-* Set the text containing the collation elements.
-* @param env JNI environment
-* @param obj RuleBasedCollatorJNI object
-* @param address of the C collation element iterator to be set
-* @param source text containing the collation elements.
-* @exception thrown when error occurs while setting offset
-*/
-static void setText(JNIEnv *env, jclass obj, jint address,
-        jstring source) {
-
-  UCollationElements *iterator = (UCollationElements *)(int)address;
-  UErrorCode status = U_ZERO_ERROR;
-  int strlength = env->GetStringLength(source);
-  const UChar *str = (const UChar *) env->GetStringCritical(source, 0);
-  
-  ucol_setText(iterator, str, strlength, &status);
-  env->ReleaseStringCritical(source, str);
-
-   icu4jni_error(env, status);
+static void setText(JNIEnv* env, jclass, jint address, jstring source0) {
+    ScopedJavaUnicodeString source(env, source0);
+    UErrorCode status = U_ZERO_ERROR;
+    ucol_setText(toCollationElements(address),
+            source.unicodeString().getBuffer(), source.unicodeString().length(), &status);
+    icu4jni_error(env, status);
 }
 
 static JNINativeMethod gMethods[] = {
-    { "openCollator", "()I", (void*) openCollator__ },
-    { "openCollator", "(Ljava/lang/String;)I", (void*) openCollator__Ljava_lang_String_2 },
+    { "openCollator", "(Ljava/lang/String;)I", (void*) openCollator },
     { "openCollatorFromRules", "(Ljava/lang/String;II)I", (void*) openCollatorFromRules },
     { "closeCollator", "(I)V", (void*) closeCollator },
     { "compare", "(ILjava/lang/String;Ljava/lang/String;)I", (void*) compare },
@@ -511,7 +184,6 @@
     { "getAttribute", "(II)I", (void*) getAttribute },
     { "safeClone", "(I)I", (void*) safeClone },
     { "getCollationElementIterator", "(ILjava/lang/String;)I", (void*) getCollationElementIterator },
-    { "hashCode", "(I)I", (void*) hashCode },
     { "closeElements", "(I)V", (void*) closeElements },
     { "reset", "(I)V", (void*) reset },
     { "next", "(I)I", (void*) next },
@@ -521,7 +193,7 @@
     { "getOffset", "(I)I", (void*) getOffset },
     { "setOffset", "(II)V", (void*) setOffset }
 };
-int register_com_ibm_icu4jni_text_NativeCollator(JNIEnv *_env) { 
-    return jniRegisterNativeMethods(_env, "com/ibm/icu4jni/text/NativeCollation",
+int register_com_ibm_icu4jni_text_NativeCollator(JNIEnv* env) { 
+    return jniRegisterNativeMethods(env, "com/ibm/icu4jni/text/NativeCollation",
                 gMethods, NELEM(gMethods));
 }
diff --git a/libcore/icu/src/main/native/NativeConverter.cpp b/libcore/icu/src/main/native/NativeConverter.cpp
index 3f5a186..8b3952e 100644
--- a/libcore/icu/src/main/native/NativeConverter.cpp
+++ b/libcore/icu/src/main/native/NativeConverter.cpp
@@ -39,11 +39,11 @@
 
 static jlong openConverter(JNIEnv* env, jclass, jstring converterName) {
     ScopedUtfChars converterNameChars(env, converterName);
-    if (!converterNameChars.data()) {
+    if (!converterNameChars.c_str()) {
         return 0;
     }
     UErrorCode errorCode = U_ZERO_ERROR;
-    UConverter* conv = ucnv_open(converterNameChars.data(), &errorCode);
+    UConverter* conv = ucnv_open(converterNameChars.c_str(), &errorCode);
     icu4jni_error(env, errorCode);
     return (jlong) conv;
 }
@@ -945,11 +945,11 @@
 
 static jobject charsetForName(JNIEnv* env, jclass, jstring charsetName) {
     ScopedUtfChars charsetNameChars(env, charsetName);
-    if (!charsetNameChars.data()) {
+    if (!charsetNameChars.c_str()) {
         return NULL;
     }
     // Get ICU's canonical name for this charset.
-    const char* icuCanonicalName = getICUCanonicalName(charsetNameChars.data());
+    const char* icuCanonicalName = getICUCanonicalName(charsetNameChars.c_str());
     if (icuCanonicalName == NULL) {
         return NULL;
     }
diff --git a/libcore/icu/src/main/native/UCharacter.cpp b/libcore/icu/src/main/native/UCharacter.cpp
index 1c5af48..abad16a 100644
--- a/libcore/icu/src/main/native/UCharacter.cpp
+++ b/libcore/icu/src/main/native/UCharacter.cpp
@@ -136,7 +136,7 @@
     ScopedJavaUnicodeString scopedString(env, javaString);
     UnicodeString& s(scopedString.unicodeString());
     UnicodeString original(s);
-    s.toLower(Locale::createFromName(ScopedUtfChars(env, localeName).data()));
+    s.toLower(Locale::createFromName(ScopedUtfChars(env, localeName).c_str()));
     return s == original ? javaString : env->NewString(s.getBuffer(), s.length());
 }
 
@@ -144,7 +144,7 @@
     ScopedJavaUnicodeString scopedString(env, javaString);
     UnicodeString& s(scopedString.unicodeString());
     UnicodeString original(s);
-    s.toUpper(Locale::createFromName(ScopedUtfChars(env, localeName).data()));
+    s.toUpper(Locale::createFromName(ScopedUtfChars(env, localeName).c_str()));
     return s == original ? javaString : env->NewString(s.getBuffer(), s.length());
 }
 
diff --git a/libcore/include/ScopedUtfChars.h b/libcore/include/ScopedUtfChars.h
index 8bc3e66..bfe9bb9 100644
--- a/libcore/include/ScopedUtfChars.h
+++ b/libcore/include/ScopedUtfChars.h
@@ -34,7 +34,7 @@
         }
     }
 
-    const char* data() const {
+    const char* c_str() const {
         return mUtfChars;
     }
 
diff --git a/libcore/text/src/main/java/java/text/Collator.java b/libcore/text/src/main/java/java/text/Collator.java
index dba931c..3495d2d 100644
--- a/libcore/text/src/main/java/java/text/Collator.java
+++ b/libcore/text/src/main/java/java/text/Collator.java
@@ -291,9 +291,10 @@
      * Returns a {@code Collator} instance which is appropriate for {@code locale}.
      */
     public static Collator getInstance(Locale locale) {
-        // BEGIN android-changed: removed non-functional cache.
+        if (locale == null) {
+            throw new NullPointerException();
+        }
         return new RuleBasedCollator(com.ibm.icu4jni.text.Collator.getInstance(locale));
-        // END android-changed
     }
 
     /**