changeset 6571:e2f976a73afb

6206780: (str) Forwarding append methods in String{Buffer,Builder} are inconsistent Summary: update StringBuilder & StringBuffer to consistently handle forwarding to AbstractStringBuilder. Some additional cleanup (removal of refs to sub-classes from AbstractStringBuilder) Reviewed-by: chegar, alanb, mduigou
author jgish
date Mon, 29 Oct 2012 16:51:59 -0700
parents 7fa45c455034
children ac97b1cfc0ea
files src/share/classes/java/lang/AbstractStringBuilder.java src/share/classes/java/lang/StringBuffer.java src/share/classes/java/lang/StringBuilder.java test/java/lang/StringBuffer/AppendStringBuilder.java test/java/lang/StringBuffer/BufferForwarding.java test/java/lang/StringBuffer/TestSynchronization.java test/java/lang/StringBuilder/AppendStringBuffer.java test/java/lang/StringBuilder/BuilderForwarding.java
diffstat 8 files changed, 1134 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/lang/AbstractStringBuilder.java	Mon Oct 29 10:42:41 2012 -0700
+++ b/src/share/classes/java/lang/AbstractStringBuilder.java	Mon Oct 29 16:51:59 2012 -0700
@@ -70,6 +70,7 @@
      * @return  the length of the sequence of characters currently
      *          represented by this object
      */
+    @Override
     public int length() {
         return count;
     }
@@ -200,6 +201,7 @@
      * @throws     IndexOutOfBoundsException  if {@code index} is
      *             negative or greater than or equal to {@code length()}.
      */
+    @Override
     public char charAt(int index) {
         if ((index < 0) || (index >= count))
             throw new StringIndexOutOfBoundsException(index);
@@ -431,14 +433,29 @@
         return this;
     }
 
+    /**
+     * @since 1.8
+     */
+    AbstractStringBuilder append(AbstractStringBuilder asb) {
+        if (asb == null)
+            return append("null");
+        int len = asb.length();
+        ensureCapacityInternal(count + len);
+        asb.getChars(0, len, value, count);
+        count += len;
+        return this;
+    }
+
     // Documentation in subclasses because of synchro difference
+    @Override
     public AbstractStringBuilder append(CharSequence s) {
         if (s == null)
             s = "null";
         if (s instanceof String)
             return this.append((String)s);
-        if (s instanceof StringBuffer)
-            return this.append((StringBuffer)s);
+        if (s instanceof AbstractStringBuilder)
+            return this.append((AbstractStringBuilder)s);
+
         return this.append(s, 0, s.length());
     }
 
@@ -471,6 +488,7 @@
      *             {@code start} is greater than {@code end} or
      *             {@code end} is greater than {@code s.length()}
      */
+    @Override
     public AbstractStringBuilder append(CharSequence s, int start, int end) {
         if (s == null)
             s = "null";
@@ -585,6 +603,7 @@
      * @param   c   a {@code char}.
      * @return  a reference to this object.
      */
+    @Override
     public AbstractStringBuilder append(char c) {
         ensureCapacityInternal(count + 1);
         value[count++] = c;
@@ -847,6 +866,7 @@
      *          or if <tt>start</tt> is greater than <tt>end</tt>
      * @spec JSR-51
      */
+    @Override
     public CharSequence subSequence(int start, int end) {
         return substring(start, end);
     }
@@ -1397,6 +1417,7 @@
      *
      * @return  a string representation of this sequence of characters.
      */
+    @Override
     public abstract String toString();
 
     /**
--- a/src/share/classes/java/lang/StringBuffer.java	Mon Oct 29 10:42:41 2012 -0700
+++ b/src/share/classes/java/lang/StringBuffer.java	Mon Oct 29 16:51:59 2012 -0700
@@ -149,15 +149,18 @@
         append(seq);
     }
 
+    @Override
     public synchronized int length() {
         return count;
     }
 
+    @Override
     public synchronized int capacity() {
         return value.length;
     }
 
 
+    @Override
     public synchronized void ensureCapacity(int minimumCapacity) {
         if (minimumCapacity > value.length) {
             expandCapacity(minimumCapacity);
@@ -167,6 +170,7 @@
     /**
      * @since      1.5
      */
+    @Override
     public synchronized void trimToSize() {
         super.trimToSize();
     }
@@ -175,6 +179,7 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      * @see        #length()
      */
+    @Override
     public synchronized void setLength(int newLength) {
         super.setLength(newLength);
     }
@@ -183,6 +188,7 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      * @see        #length()
      */
+    @Override
     public synchronized char charAt(int index) {
         if ((index < 0) || (index >= count))
             throw new StringIndexOutOfBoundsException(index);
@@ -192,6 +198,7 @@
     /**
      * @since      1.5
      */
+    @Override
     public synchronized int codePointAt(int index) {
         return super.codePointAt(index);
     }
@@ -199,6 +206,7 @@
     /**
      * @since     1.5
      */
+    @Override
     public synchronized int codePointBefore(int index) {
         return super.codePointBefore(index);
     }
@@ -206,6 +214,7 @@
     /**
      * @since     1.5
      */
+    @Override
     public synchronized int codePointCount(int beginIndex, int endIndex) {
         return super.codePointCount(beginIndex, endIndex);
     }
@@ -213,6 +222,7 @@
     /**
      * @since     1.5
      */
+    @Override
     public synchronized int offsetByCodePoints(int index, int codePointOffset) {
         return super.offsetByCodePoints(index, codePointOffset);
     }
@@ -221,6 +231,7 @@
      * @throws NullPointerException {@inheritDoc}
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public synchronized void getChars(int srcBegin, int srcEnd, char[] dst,
                                       int dstBegin)
     {
@@ -231,17 +242,20 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      * @see        #length()
      */
+    @Override
     public synchronized void setCharAt(int index, char ch) {
         if ((index < 0) || (index >= count))
             throw new StringIndexOutOfBoundsException(index);
         value[index] = ch;
     }
 
+    @Override
     public synchronized StringBuffer append(Object obj) {
         super.append(String.valueOf(obj));
         return this;
     }
 
+    @Override
     public synchronized StringBuffer append(String str) {
         super.append(str);
         return this;
@@ -276,6 +290,14 @@
         return this;
     }
 
+    /**
+     * @since 1.8
+     */
+    @Override
+    synchronized StringBuffer append(AbstractStringBuilder asb) {
+        super.append(asb);
+        return this;
+    }
 
     /**
      * Appends the specified {@code CharSequence} to this
@@ -298,27 +320,26 @@
      * @return  a reference to this object.
      * @since 1.5
      */
+    @Override
     public StringBuffer append(CharSequence s) {
-        // Note, synchronization achieved via other invocations
-        if (s == null)
-            s = "null";
-        if (s instanceof String)
-            return this.append((String)s);
-        if (s instanceof StringBuffer)
-            return this.append((StringBuffer)s);
-        return this.append(s, 0, s.length());
+        // Note, synchronization achieved via invocations of other StringBuffer methods after
+        // narrowing of s to specific type
+        super.append(s);
+        return this;
     }
 
     /**
      * @throws IndexOutOfBoundsException {@inheritDoc}
      * @since      1.5
      */
+    @Override
     public synchronized StringBuffer append(CharSequence s, int start, int end)
     {
         super.append(s, start, end);
         return this;
     }
 
+    @Override
     public synchronized StringBuffer append(char[] str) {
         super.append(str);
         return this;
@@ -327,21 +348,25 @@
     /**
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public synchronized StringBuffer append(char[] str, int offset, int len) {
         super.append(str, offset, len);
         return this;
     }
 
+    @Override
     public synchronized StringBuffer append(boolean b) {
         super.append(b);
         return this;
     }
 
+    @Override
     public synchronized StringBuffer append(char c) {
         super.append(c);
         return this;
     }
 
+    @Override
     public synchronized StringBuffer append(int i) {
         super.append(i);
         return this;
@@ -350,21 +375,25 @@
     /**
      * @since 1.5
      */
+    @Override
     public synchronized StringBuffer appendCodePoint(int codePoint) {
         super.appendCodePoint(codePoint);
         return this;
     }
 
+    @Override
     public synchronized StringBuffer append(long lng) {
         super.append(lng);
         return this;
     }
 
+    @Override
     public synchronized StringBuffer append(float f) {
         super.append(f);
         return this;
     }
 
+    @Override
     public synchronized StringBuffer append(double d) {
         super.append(d);
         return this;
@@ -374,6 +403,7 @@
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      * @since      1.2
      */
+    @Override
     public synchronized StringBuffer delete(int start, int end) {
         super.delete(start, end);
         return this;
@@ -383,6 +413,7 @@
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      * @since      1.2
      */
+    @Override
     public synchronized StringBuffer deleteCharAt(int index) {
         super.deleteCharAt(index);
         return this;
@@ -392,6 +423,7 @@
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      * @since      1.2
      */
+    @Override
     public synchronized StringBuffer replace(int start, int end, String str) {
         super.replace(start, end, str);
         return this;
@@ -401,6 +433,7 @@
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      * @since      1.2
      */
+    @Override
     public synchronized String substring(int start) {
         return substring(start, count);
     }
@@ -409,6 +442,7 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      * @since      1.4
      */
+    @Override
     public synchronized CharSequence subSequence(int start, int end) {
         return super.substring(start, end);
     }
@@ -417,6 +451,7 @@
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      * @since      1.2
      */
+    @Override
     public synchronized String substring(int start, int end) {
         return super.substring(start, end);
     }
@@ -425,6 +460,7 @@
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      * @since      1.2
      */
+    @Override
     public synchronized StringBuffer insert(int index, char[] str, int offset,
                                             int len)
     {
@@ -435,6 +471,7 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public synchronized StringBuffer insert(int offset, Object obj) {
         super.insert(offset, String.valueOf(obj));
         return this;
@@ -443,6 +480,7 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public synchronized StringBuffer insert(int offset, String str) {
         super.insert(offset, str);
         return this;
@@ -451,6 +489,7 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public synchronized StringBuffer insert(int offset, char[] str) {
         super.insert(offset, str);
         return this;
@@ -460,21 +499,21 @@
      * @throws IndexOutOfBoundsException {@inheritDoc}
      * @since      1.5
      */
+    @Override
     public StringBuffer insert(int dstOffset, CharSequence s) {
-        // Note, synchronization achieved via other invocations
-        if (s == null)
-            s = "null";
-        if (s instanceof String)
-            return this.insert(dstOffset, (String)s);
-        return this.insert(dstOffset, s, 0, s.length());
+        // Note, synchronization achieved via invocations of other StringBuffer methods
+        // after narrowing of s to specific type
+        super.insert(dstOffset, s);
+        return this;
     }
 
     /**
      * @throws IndexOutOfBoundsException {@inheritDoc}
      * @since      1.5
      */
+    @Override
     public synchronized StringBuffer insert(int dstOffset, CharSequence s,
-                                            int start, int end)
+            int start, int end)
     {
         super.insert(dstOffset, s, start, end);
         return this;
@@ -483,13 +522,18 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
-    public StringBuffer insert(int offset, boolean b) {
-        return insert(offset, String.valueOf(b));
+    @Override
+    public  StringBuffer insert(int offset, boolean b) {
+        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
+        // after conversion of b to String by super class method
+        super.insert(offset, b);
+        return this;
     }
 
     /**
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public synchronized StringBuffer insert(int offset, char c) {
         super.insert(offset, c);
         return this;
@@ -498,54 +542,73 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuffer insert(int offset, int i) {
-        return insert(offset, String.valueOf(i));
+        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
+        // after conversion of i to String by super class method
+        super.insert(offset, i);
+        return this;
     }
 
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuffer insert(int offset, long l) {
-        return insert(offset, String.valueOf(l));
+        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
+        // after conversion of l to String by super class method
+        super.insert(offset, l);
+        return this;
     }
 
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuffer insert(int offset, float f) {
-        return insert(offset, String.valueOf(f));
+        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
+        // after conversion of f to String by super class method
+        super.insert(offset, f);
+        return this;
     }
 
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuffer insert(int offset, double d) {
-        return insert(offset, String.valueOf(d));
+        // Note, synchronization achieved via invocation of StringBuffer insert(int, String)
+        // after conversion of d to String by super class method
+        super.insert(offset, d);
+        return this;
     }
 
     /**
      * @throws NullPointerException {@inheritDoc}
      * @since      1.4
      */
+    @Override
     public int indexOf(String str) {
-        return indexOf(str, 0);
+        // Note, synchronization achieved via invocations of other StringBuffer methods
+        return super.indexOf(str);
     }
 
     /**
      * @throws NullPointerException {@inheritDoc}
      * @since      1.4
      */
+    @Override
     public synchronized int indexOf(String str, int fromIndex) {
-        return String.indexOf(value, 0, count,
-                              str.toCharArray(), 0, str.length(), fromIndex);
+        return super.indexOf(str, fromIndex);
     }
 
     /**
      * @throws NullPointerException {@inheritDoc}
      * @since      1.4
      */
+    @Override
     public int lastIndexOf(String str) {
-        // Note, synchronization achieved via other invocations
+        // Note, synchronization achieved via invocations of other StringBuffer methods
         return lastIndexOf(str, count);
     }
 
@@ -553,19 +616,21 @@
      * @throws NullPointerException {@inheritDoc}
      * @since      1.4
      */
+    @Override
     public synchronized int lastIndexOf(String str, int fromIndex) {
-        return String.lastIndexOf(value, 0, count,
-                              str.toCharArray(), 0, str.length(), fromIndex);
+        return super.lastIndexOf(str, fromIndex);
     }
 
     /**
      * @since   JDK1.0.2
      */
+    @Override
     public synchronized StringBuffer reverse() {
         super.reverse();
         return this;
     }
 
+    @Override
     public synchronized String toString() {
         return new String(value, 0, count);
     }
--- a/src/share/classes/java/lang/StringBuilder.java	Mon Oct 29 10:42:41 2012 -0700
+++ b/src/share/classes/java/lang/StringBuilder.java	Mon Oct 29 16:51:59 2012 -0700
@@ -124,28 +124,17 @@
         append(seq);
     }
 
+    @Override
     public StringBuilder append(Object obj) {
         return append(String.valueOf(obj));
     }
 
+    @Override
     public StringBuilder append(String str) {
         super.append(str);
         return this;
     }
 
-    // Appends the specified string builder to this sequence.
-    private StringBuilder append(StringBuilder sb) {
-        if (sb == null)
-            return append("null");
-        int len = sb.length();
-        int newcount = count + len;
-        if (newcount > value.length)
-            expandCapacity(newcount);
-        sb.getChars(0, len, value, count);
-        count = newcount;
-        return this;
-    }
-
     /**
      * Appends the specified <tt>StringBuffer</tt> to this sequence.
      * <p>
@@ -170,28 +159,22 @@
         return this;
     }
 
-    /**
-     */
+    @Override
     public StringBuilder append(CharSequence s) {
-        if (s == null)
-            s = "null";
-        if (s instanceof String)
-            return this.append((String)s);
-        if (s instanceof StringBuffer)
-            return this.append((StringBuffer)s);
-        if (s instanceof StringBuilder)
-            return this.append((StringBuilder)s);
-        return this.append(s, 0, s.length());
+        super.append(s);
+        return this;
     }
 
     /**
      * @throws     IndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder append(CharSequence s, int start, int end) {
         super.append(s, start, end);
         return this;
     }
 
+    @Override
     public StringBuilder append(char[] str) {
         super.append(str);
         return this;
@@ -200,36 +183,43 @@
     /**
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder append(char[] str, int offset, int len) {
         super.append(str, offset, len);
         return this;
     }
 
+    @Override
     public StringBuilder append(boolean b) {
         super.append(b);
         return this;
     }
 
+    @Override
     public StringBuilder append(char c) {
         super.append(c);
         return this;
     }
 
+    @Override
     public StringBuilder append(int i) {
         super.append(i);
         return this;
     }
 
+    @Override
     public StringBuilder append(long lng) {
         super.append(lng);
         return this;
     }
 
+    @Override
     public StringBuilder append(float f) {
         super.append(f);
         return this;
     }
 
+    @Override
     public StringBuilder append(double d) {
         super.append(d);
         return this;
@@ -238,6 +228,7 @@
     /**
      * @since 1.5
      */
+    @Override
     public StringBuilder appendCodePoint(int codePoint) {
         super.appendCodePoint(codePoint);
         return this;
@@ -246,6 +237,7 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder delete(int start, int end) {
         super.delete(start, end);
         return this;
@@ -254,6 +246,7 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder deleteCharAt(int index) {
         super.deleteCharAt(index);
         return this;
@@ -262,6 +255,7 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder replace(int start, int end, String str) {
         super.replace(start, end, str);
         return this;
@@ -270,6 +264,7 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int index, char[] str, int offset,
                                 int len)
     {
@@ -280,13 +275,16 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int offset, Object obj) {
-        return insert(offset, String.valueOf(obj));
+            super.insert(offset, obj);
+            return this;
     }
 
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int offset, String str) {
         super.insert(offset, str);
         return this;
@@ -295,6 +293,7 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int offset, char[] str) {
         super.insert(offset, str);
         return this;
@@ -303,17 +302,16 @@
     /**
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int dstOffset, CharSequence s) {
-        if (s == null)
-            s = "null";
-        if (s instanceof String)
-            return this.insert(dstOffset, (String)s);
-        return this.insert(dstOffset, s, 0, s.length());
+            super.insert(dstOffset, s);
+            return this;
     }
 
     /**
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int dstOffset, CharSequence s,
                                 int start, int end)
     {
@@ -324,6 +322,7 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int offset, boolean b) {
         super.insert(offset, b);
         return this;
@@ -332,6 +331,7 @@
     /**
      * @throws IndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int offset, char c) {
         super.insert(offset, c);
         return this;
@@ -340,66 +340,78 @@
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int offset, int i) {
-        return insert(offset, String.valueOf(i));
+        super.insert(offset, i);
+        return this;
     }
 
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int offset, long l) {
-        return insert(offset, String.valueOf(l));
+        super.insert(offset, l);
+        return this;
     }
 
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int offset, float f) {
-        return insert(offset, String.valueOf(f));
+        super.insert(offset, f);
+        return this;
     }
 
     /**
      * @throws StringIndexOutOfBoundsException {@inheritDoc}
      */
+    @Override
     public StringBuilder insert(int offset, double d) {
-        return insert(offset, String.valueOf(d));
+        super.insert(offset, d);
+        return this;
     }
 
     /**
      * @throws NullPointerException {@inheritDoc}
      */
+    @Override
     public int indexOf(String str) {
-        return indexOf(str, 0);
+        return super.indexOf(str);
     }
 
     /**
      * @throws NullPointerException {@inheritDoc}
      */
+    @Override
     public int indexOf(String str, int fromIndex) {
-        return String.indexOf(value, 0, count,
-                              str.toCharArray(), 0, str.length(), fromIndex);
+        return super.indexOf(str, fromIndex);
     }
 
     /**
      * @throws NullPointerException {@inheritDoc}
      */
+    @Override
     public int lastIndexOf(String str) {
-        return lastIndexOf(str, count);
+        return super.lastIndexOf(str);
     }
 
     /**
      * @throws NullPointerException {@inheritDoc}
      */
+    @Override
     public int lastIndexOf(String str, int fromIndex) {
-        return String.lastIndexOf(value, 0, count,
-                              str.toCharArray(), 0, str.length(), fromIndex);
+        return super.lastIndexOf(str, fromIndex);
     }
 
+    @Override
     public StringBuilder reverse() {
         super.reverse();
         return this;
     }
 
+    @Override
     public String toString() {
         // Create a copy, don't share the array
         return new String(value, 0, count);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/StringBuffer/AppendStringBuilder.java	Mon Oct 29 16:51:59 2012 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/* @test
+ * @bug 6206780
+ * @summary Test StringBuffer.append(StringBuilder);
+ */
+
+import java.util.Random;
+
+public class AppendStringBuilder {
+    private static Random generator = new Random();
+
+    public static void main(String[] args) throws Exception {
+        for (int i=0; i<1000; i++) {
+            StringBuilder sb1 = generateTestBuilder(10, 100);
+            StringBuilder sb2 = generateTestBuilder(10, 100);
+            StringBuilder sb3 = generateTestBuilder(10, 100);
+            String s1 = sb1.toString();
+            String s2 = sb2.toString();
+            String s3 = sb3.toString();
+
+            String concatResult = new String(s1+s2+s3);
+
+            StringBuffer test = new StringBuffer();
+            test.append(sb1);
+            test.append(sb2);
+            test.append(sb3);
+
+            if (!test.toString().equals(concatResult))
+                throw new RuntimeException("StringBuffer.append failure");
+        }
+    }
+
+    private static int getRandomIndex(int constraint1, int constraint2) {
+        int range = constraint2 - constraint1;
+        int x = generator.nextInt(range);
+        return constraint1 + x;
+    }
+
+    private static StringBuilder generateTestBuilder(int min, int max) {
+        StringBuilder aNewStringBuilder = new StringBuilder(120);
+        int aNewLength = getRandomIndex(min, max);
+        for(int y=0; y<aNewLength; y++) {
+            int achar = generator.nextInt(30)+30;
+            char test = (char)(achar);
+            aNewStringBuilder.append(test);
+        }
+        return aNewStringBuilder;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/StringBuffer/BufferForwarding.java	Mon Oct 29 16:51:59 2012 -0700
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 6206780
+ * @summary  Test forwarding of methods to super in StringBuffer
+ * @author Jim Gish <jim.gish@oracle.com>
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class BufferForwarding {
+    private final static String A_STRING_BUFFER_VAL = "aStringBuffer";
+    private final static String A_STRING_BUILDER_VAL = "aStringBuilder";
+    private final static String A_STRING_VAL = "aString";
+    private final static String NON_EMPTY_VAL = "NonEmpty";
+
+    public BufferForwarding() {
+        System.out.println( "Starting BufferForwarding");
+    }
+
+    public static void main(String... args) {
+        new BufferForwarding().executeTestMethods();
+    }
+
+    public void executeTestMethods() {
+        appendCharSequence();
+        indexOfString();
+        indexOfStringIntNull();
+        indexOfStringNull();
+        indexOfStringint();
+        insertintCharSequence();
+        insertintObject();
+        insertintboolean();
+        insertintchar();
+        insertintdouble();
+        insertintfloat();
+        insertintint();
+        insertintlong();
+        lastIndexOfString();
+        lastIndexOfStringint();
+    }
+
+    public void appendCharSequence() {
+        // three different flavors of CharSequence
+        CharSequence aString = A_STRING_VAL;
+        CharSequence aStringBuilder = new StringBuilder(A_STRING_BUILDER_VAL);
+        CharSequence aStringBuffer = new StringBuffer(A_STRING_BUFFER_VAL);
+
+        assertEquals( /*actual*/ new StringBuilder().append(aString).toString(), /*expected*/ A_STRING_VAL );
+        assertEquals( new StringBuilder().append(aStringBuilder).toString(), A_STRING_BUILDER_VAL );
+        assertEquals( new StringBuilder().append(aStringBuffer).toString(), A_STRING_BUFFER_VAL );
+
+        assertEquals( /*actual*/ new StringBuilder(NON_EMPTY_VAL).append(aString).toString(), NON_EMPTY_VAL+A_STRING_VAL );
+        assertEquals( new StringBuilder(NON_EMPTY_VAL).append(aStringBuilder).toString(), NON_EMPTY_VAL+A_STRING_BUILDER_VAL );
+        assertEquals( new StringBuilder(NON_EMPTY_VAL).append(aStringBuffer).toString(), NON_EMPTY_VAL+A_STRING_BUFFER_VAL );
+    }
+
+    void indexOfString() {
+        StringBuffer sb = new StringBuffer("xyz");
+        assertEquals( sb.indexOf("y"), 1 );
+        assertEquals( sb.indexOf("not found"), -1 );
+    }
+
+
+    public void indexOfStringint() {
+        StringBuffer sb = new StringBuffer("xyyz");
+        assertEquals( sb.indexOf("y",0), 1 );
+        assertEquals( sb.indexOf("y",1), 1 );
+        assertEquals( sb.indexOf("y",2), 2 );
+        assertEquals( sb.indexOf("not found"), -1 );
+    }
+
+
+    public void indexOfStringIntNull() {
+        StringBuffer sb = new StringBuffer();
+        // should be NPE if null passed
+        try {
+            sb.indexOf(null,1);
+            throw new RuntimeException("Test failed: should have thrown NPE");
+        } catch (NullPointerException npe) {
+            // expected: passed
+        } catch (Throwable t) {
+            throw new RuntimeException("Test failed: should have thrown NPE. Instead threw "
+                    + t);
+        }
+    }
+
+
+    public void indexOfStringNull() {
+        StringBuffer sb = new StringBuffer();
+
+        // should be NPE if null passed
+        try {
+            sb.indexOf(null);
+            throw new RuntimeException("Test failed: should have thrown NPE");
+        } catch (NullPointerException npe) {
+            // expected: passed
+        } catch (Throwable t) {
+            throw new RuntimeException("Test failed: should have thrown NPE. Instead threw "
+                    + t);
+        }
+    }
+
+
+    public void insertintboolean() {
+        boolean b = true;
+        StringBuffer sb = new StringBuffer("012345");
+        assertEquals( sb.insert( 2, b).toString(), "01true2345");
+    }
+
+
+    public void insertintchar() {
+        char c = 'C';
+        StringBuffer sb = new StringBuffer("012345");
+        assertEquals( sb.insert( 2, c ).toString(), "01C2345");
+    }
+
+
+    public void insertintCharSequence() {
+        final String initString = "012345";
+        // three different flavors of CharSequence
+        CharSequence aString = A_STRING_VAL;
+        CharSequence aStringBuilder = new StringBuilder(A_STRING_BUILDER_VAL);
+        CharSequence aStringBuffer = new StringBuffer(A_STRING_BUFFER_VAL);
+
+        assertEquals( new StringBuffer(initString).insert(2, aString).toString(), "01"+A_STRING_VAL+"2345" );
+
+        assertEquals( new StringBuffer(initString).insert(2, aStringBuilder).toString(), "01"+A_STRING_BUILDER_VAL+"2345" );
+
+        assertEquals( new StringBuffer(initString).insert(2, aStringBuffer).toString(), "01"+A_STRING_BUFFER_VAL+"2345" );
+
+        try {
+            new StringBuffer(initString).insert(7, aString);
+            throw new RuntimeException("Test failed: should have thrown IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException soob) {
+            // expected: passed
+        } catch (Throwable t) {
+            throw new RuntimeException("Test failed: should have thrown IndexOutOfBoundsException, but instead threw " + t.getMessage());
+
+        }
+    }
+
+    public void insertintdouble() {
+        double d = 99d;
+        StringBuffer sb = new StringBuffer("012345");
+        assertEquals( sb.insert( 2, d ).toString(), "0199.02345");    }
+
+
+    public void insertintfloat() {
+        float f = 99.0f;
+        StringBuffer sb = new StringBuffer("012345");
+        assertEquals( sb.insert( 2, f ).toString(), "0199.02345");    }
+
+
+    public void insertintint() {
+        int i = 99;
+        StringBuffer sb = new StringBuffer("012345");
+        assertEquals( sb.insert( 2, i ).toString(), "01992345");
+    }
+
+
+    public void insertintlong() {
+        long l = 99;
+        StringBuffer sb = new StringBuffer("012345");
+        assertEquals( sb.insert( 2, l ).toString(), "01992345");    }
+
+    public void insertintObject() {
+        StringBuffer sb = new StringBuffer("012345");
+        List<String> ls = new ArrayList<String>();
+        ls.add("A"); ls.add("B");
+        String lsString = ls.toString();
+        assertEquals( sb.insert(2, ls).toString(), "01"+lsString+"2345");
+
+        try {
+            sb.insert(sb.length()+1, ls);
+            throw new RuntimeException("Test failed: should have thrown StringIndexOutOfBoundsException");
+        } catch (StringIndexOutOfBoundsException soob) {
+            // expected: passed
+        } catch (Throwable t) {
+            throw new RuntimeException("Test failed: should have thrown StringIndexOutOfBoundsException, but instead threw:"
+                    + t);
+
+        }
+    }
+
+
+
+    public void lastIndexOfString() {
+        String xyz = "xyz";
+        String xyz3 = "xyzxyzxyz";
+        StringBuffer sb = new StringBuffer(xyz3);
+        int pos = sb.lastIndexOf("xyz");
+        assertEquals( pos, 2*xyz.length() );
+    }
+
+    public void lastIndexOfStringint() {
+        StringBuffer sb = new StringBuffer("xyzxyzxyz");
+        int pos = sb.lastIndexOf("xyz",5);
+        assertEquals( pos, 3 );
+        pos = sb.lastIndexOf("xyz", 6);
+        assertEquals( pos, 6 );
+    }
+
+    public void assertEquals( String actual, String expected) {
+        if (!actual.equals( expected )) {
+            throw new RuntimeException( "Test failed: actual = '" + actual +
+                    "', expected = '" + expected + "'");
+        }
+    }
+
+    public void assertEquals( int actual, int expected) {
+        if (actual != expected) {
+            throw new RuntimeException( "Test failed: actual = '" + actual +
+                    "', expected = '" + expected + "'");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/StringBuffer/TestSynchronization.java	Mon Oct 29 16:51:59 2012 -0700
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 6206780
+ * @summary Test that all public unsynchronized methods of StringBuffer are either directly or indirectly synchronized
+ */
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * TestSynchronization tests whether synchronized methods calls on an object
+ * result in synchronized calls. Note that this may not test all cases desired.
+ * It only tests whether some synchronization has occurred on the object during
+ * the call chain, and can't tell whether the object was locked across all
+ * operations that have been performed on the object.
+ */
+public class TestSynchronization {
+
+    /**
+     * Define parameters used in methods of StringBuffer - admittedly a bit of
+     * hack but 'purpose-built' for StringBuffer. Something more general could
+     * probably be developed if the test needs to be more widely adopted.
+     * <p/>
+     * boolean char char[] int double float long Object CharSequence String
+     * StringBuffer StringBuilder
+     * <p/>
+     */
+    private static final boolean BOOLEAN_VAL = true;
+    private static final char CHAR_VAL = 'x';
+    private static final char[] CHAR_ARRAY_VAL = {'c', 'h', 'a', 'r', 'a', 'r',
+        'r', 'a', 'y'};
+    private static final int INT_VAL = 1;
+    private static final double DOUBLE_VAL = 1.0d;
+    private static final float FLOAT_VAL = 1.0f;
+    private static final long LONG_VAL = 1L;
+    private static final Object OBJECT_VAL = new Object();
+    private static final String STRING_VAL = "String value";
+    private static final StringBuilder STRING_BUILDER_VAL =
+            new StringBuilder("StringBuilder value");
+    private static final StringBuffer STRING_BUFFER_VAL =
+            new StringBuffer("StringBuffer value");
+    private static final CharSequence[] CHAR_SEQUENCE_VAL = {STRING_VAL,
+        STRING_BUILDER_VAL, STRING_BUFFER_VAL};
+
+    public static void main(String... args) throws Exception {
+        // First, test the tester
+        testClass(MyTestClass.class, /*
+                 * self-test
+                 */ true);
+        // Finally, test StringBuffer
+        testClass(StringBuffer.class, /*
+                 * self-test
+                 */ false);
+    }
+
+    /**
+     * Test all the public, unsynchronized methods of the given class. If
+     * isSelfTest is true, this is a self-test to ensure that the test program
+     * itself is working correctly. Should help ensure correctness of this
+     * program if it changes.
+     * <p/>
+     * @param aClass - the class to test
+     * @param isSelfTest - true if this is the special self-test class
+     * @throws SecurityException
+     */
+    private static void testClass(Class<?> aClass, boolean isSelfTest) throws
+            Exception {
+        // Get all unsynchronized public methods via reflection.  We don't need
+        // to test synchronized methods.  By definition. they are already doing
+        // the right thing.
+        List<Method> methods = Arrays.asList(aClass.getDeclaredMethods());
+        for (Method m : methods) {
+            int modifiers = m.getModifiers();
+            if (Modifier.isPublic(modifiers)
+                    && !Modifier.isSynchronized(modifiers)) {
+                try {
+                    testMethod(aClass, m);
+                } catch (TestFailedException e) {
+                    if (isSelfTest) {
+                        String methodName = e.getMethod().getName();
+                        switch (methodName) {
+                            case "should_pass":
+                                throw new RuntimeException(
+                                        "Test failed: self-test failed.  The 'should_pass' method did not pass the synchronization test. Check the test code.");
+                            case "should_fail":
+                                break;
+                            default:
+                                throw new RuntimeException(
+                                        "Test failed: something is amiss with the test. A TestFailedException was generated on a call to "
+                                        + methodName + " which we didn't expect to test in the first place.");
+                        }
+                    } else {
+                        throw new RuntimeException("Test failed: the method "
+                                + e.getMethod().toString()
+                                + " should be synchronized, but isn't.");
+                    }
+                }
+            }
+        }
+    }
+
+    private static void invokeMethod(Class<?> aClass, final Method m,
+            final Object[] args) throws TestFailedException, Exception {
+        //System.out.println( "Invoking " + m.toString() + " with parameters " + Arrays.toString(args));
+        final Constructor<?> objConstructor;
+        Object obj = null;
+
+        objConstructor = aClass.getConstructor(String.class);
+        obj = objConstructor.newInstance("LeftPalindrome-emordnilaP-thgiR");
+
+        // test method m for synchronization
+        if (!isSynchronized(m, obj, args)) {
+            throw new TestFailedException(m);
+        }
+    }
+
+    private static void testMethod(Class<?> aClass, Method m) throws
+            Exception {
+        /*
+         * Construct call with arguments of the correct type. Note that the
+         * values are somewhat irrelevant. If the call actually succeeds, it
+         * means we aren't synchronized and the test has failed.
+         */
+        Class<?>[] pTypes = m.getParameterTypes();
+        List<Integer> charSequenceArgs = new ArrayList<>();
+        Object[] args = new Object[pTypes.length];
+        for (int i = 0; i < pTypes.length; i++) {
+            // determine the type and create the corresponding actual argument
+            Class<?> pType = pTypes[i];
+            if (pType.equals(boolean.class)) {
+                args[i] = BOOLEAN_VAL;
+            } else if (pType.equals(char.class)) {
+                args[i] = CHAR_VAL;
+            } else if (pType.equals(int.class)) {
+                args[i] = INT_VAL;
+            } else if (pType.equals(double.class)) {
+                args[i] = DOUBLE_VAL;
+            } else if (pType.equals(float.class)) {
+                args[i] = FLOAT_VAL;
+            } else if (pType.equals(long.class)) {
+                args[i] = LONG_VAL;
+            } else if (pType.equals(Object.class)) {
+                args[i] = OBJECT_VAL;
+            } else if (pType.equals(StringBuilder.class)) {
+                args[i] = STRING_BUILDER_VAL;
+            } else if (pType.equals(StringBuffer.class)) {
+                args[i] = STRING_BUFFER_VAL;
+            } else if (pType.equals(String.class)) {
+                args[i] = STRING_VAL;
+            } else if (pType.isArray() && pType.getComponentType().equals(char.class)) {
+                args[i] = CHAR_ARRAY_VAL;
+            } else if (pType.equals(CharSequence.class)) {
+                charSequenceArgs.add(new Integer(i));
+            } else {
+                throw new RuntimeException("Test Failed: not accounting for method call with parameter type of " + pType.getName() + " You must update the test.");
+            }
+        }
+        /*
+         * If there are no CharSequence args, we can simply invoke our method
+         * and test it
+         */
+        if (charSequenceArgs.isEmpty()) {
+            invokeMethod(aClass, m, args);
+        } else {
+            /*
+             * Iterate through the different CharSequence types and invoke the
+             * method for each type.
+             */
+            if (charSequenceArgs.size() > 1) {
+                throw new RuntimeException("Test Failed: the test cannot handle a method with multiple CharSequence arguments.  You must update the test to handle the method "
+                        + m.toString());
+            }
+            for (int j = 0; j < CHAR_SEQUENCE_VAL.length; j++) {
+                args[charSequenceArgs.get(0)] = CHAR_SEQUENCE_VAL[j];
+                invokeMethod(aClass, m, args);
+            }
+        }
+    }
+
+    @SuppressWarnings("serial")
+    private static class TestFailedException extends Exception {
+
+        final Method m;
+
+        public Method getMethod() {
+            return m;
+        }
+
+        public TestFailedException(Method m) {
+            this.m = m;
+        }
+    }
+
+    static class InvokeTask implements Runnable {
+
+        private final Method m;
+        private final Object target;
+        private final Object[] args;
+
+        InvokeTask(Method m, Object target, Object... args) {
+            this.m = m;
+            this.target = target;
+            this.args = args;
+        }
+
+        @Override
+        public void run() {
+            try {
+                m.invoke(target, args);
+            } catch (IllegalAccessException | IllegalArgumentException |
+                    InvocationTargetException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * isSynchronized tests whether the given method is synchronized or not by
+     * invoking it in a thread and testing the thread state after starting the
+     * thread
+     * <p/>
+     * @param m the method to test
+     * @param target the object the method is executed on
+     * @param args the arguments passed to the method
+     * @return true iff the method is synchronized
+     */
+    private static boolean isSynchronized(Method m, Object target,
+            Object... args) {
+        Thread t = new Thread(new InvokeTask(m, target, args));
+
+        Boolean isSynchronized = null;
+
+        synchronized (target) {
+            t.start();
+
+            while (isSynchronized == null) {
+                switch (t.getState()) {
+                    case NEW:
+                    case RUNNABLE:
+                    case WAITING:
+                    case TIMED_WAITING:
+                        Thread.yield();
+                        break;
+                    case BLOCKED:
+                        isSynchronized = true;
+                        break;
+                    case TERMINATED:
+                        isSynchronized = false;
+                        break;
+                }
+            }
+        }
+
+        try {
+            t.join();
+        } catch (InterruptedException ex) {
+            ex.printStackTrace();
+        }
+
+        return isSynchronized;
+    }
+
+    /*
+     * This class is used to test the synchronization tester above. It has a
+     * method, should_pass, that is unsynchronized but calls a synchronized
+     * method. It has another method, should_fail, which isn't synchronized and
+     * doesn't call a synchronized method. The former should pass and the latter
+     * should fail.
+     */
+    private static class MyTestClass {
+
+        @SuppressWarnings("unused")
+        public MyTestClass(String s) {
+        }
+
+        @SuppressWarnings("unused")
+        public void should_pass() {
+            // call sync method
+            sync_shouldnt_be_tested();
+        }
+
+        @SuppressWarnings("unused")
+        public void should_fail() {
+        }
+
+        public synchronized void sync_shouldnt_be_tested() {
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/StringBuilder/AppendStringBuffer.java	Mon Oct 29 16:51:59 2012 -0700
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 6206780
+ * @summary Test StringBuilder.append(StringBuffer);
+ */
+
+import java.util.Random;
+
+public class AppendStringBuffer {
+    private static Random generator = new Random();
+
+    public static void main(String[] args) throws Exception {
+        for (int i=0; i<1000; i++) {
+            StringBuffer sb1 = generateTestBuffer(10, 100);
+            StringBuffer sb2 = generateTestBuffer(10, 100);
+            StringBuffer sb3 = generateTestBuffer(10, 100);
+            String s1 = sb1.toString();
+            String s2 = sb2.toString();
+            String s3 = sb3.toString();
+
+            String concatResult = new String(s1+s2+s3);
+
+            StringBuilder test = new StringBuilder();
+            test.append(sb1);
+            test.append(sb2);
+            test.append(sb3);
+
+            if (!test.toString().equals(concatResult))
+                throw new RuntimeException("StringBuffer.append failure");
+        }
+    }
+
+    private static int getRandomIndex(int constraint1, int constraint2) {
+        int range = constraint2 - constraint1;
+        int x = generator.nextInt(range);
+        return constraint1 + x;
+    }
+
+    private static StringBuffer generateTestBuffer(int min, int max) {
+        StringBuffer aNewStringBuffer = new StringBuffer(120);
+        int aNewLength = getRandomIndex(min, max);
+        for(int y=0; y<aNewLength; y++) {
+            int achar = generator.nextInt(30)+30;
+            char test = (char)(achar);
+            aNewStringBuffer.append(test);
+        }
+        return aNewStringBuffer;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/StringBuilder/BuilderForwarding.java	Mon Oct 29 16:51:59 2012 -0700
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 6206780
+ * @summary  Test forwarding of methods to super in StringBuilder
+ * @author Jim Gish <jim.gish@oracle.com>
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class BuilderForwarding {
+    private final static String A_STRING_BUFFER_VAL = "aStringBuffer";
+    private final static String A_STRING_BUILDER_VAL = "aStringBuilder";
+    private final static String A_STRING_VAL = "aString";
+    private final static String NON_EMPTY_VAL = "NonEmpty";
+
+    public BuilderForwarding() {
+        System.out.println( "Starting BuilderForwarding");
+    }
+
+    public static void main(String... args) {
+        new BuilderForwarding().executeTestMethods();
+    }
+
+    public void executeTestMethods() {
+        appendCharSequence();
+        indexOfString();
+        indexOfStringIntNull();
+        indexOfStringNull();
+        indexOfStringint();
+        insertintCharSequence();
+        insertintObject();
+        insertintboolean();
+        insertintchar();
+        insertintdouble();
+        insertintfloat();
+        insertintint();
+        insertintlong();
+        lastIndexOfString();
+        lastIndexOfStringint();
+    }
+
+    public void appendCharSequence() {
+        // three different flavors of CharSequence
+        CharSequence aString = A_STRING_VAL;
+        CharSequence aStringBuilder = new StringBuilder(A_STRING_BUILDER_VAL);
+        CharSequence aStringBuffer = new StringBuffer(A_STRING_BUFFER_VAL);
+
+        assertEquals( /*actual*/ new StringBuilder().append(aString).toString(), /*expected*/ A_STRING_VAL );
+        assertEquals( new StringBuilder().append(aStringBuilder).toString(), A_STRING_BUILDER_VAL );
+        assertEquals( new StringBuilder().append(aStringBuffer).toString(), A_STRING_BUFFER_VAL );
+
+        assertEquals( /*actual*/ new StringBuilder(NON_EMPTY_VAL).append(aString).toString(), NON_EMPTY_VAL+A_STRING_VAL );
+        assertEquals( new StringBuilder(NON_EMPTY_VAL).append(aStringBuilder).toString(), NON_EMPTY_VAL+A_STRING_BUILDER_VAL );
+        assertEquals( new StringBuilder(NON_EMPTY_VAL).append(aStringBuffer).toString(), NON_EMPTY_VAL+A_STRING_BUFFER_VAL );
+    }
+
+
+    public void indexOfString() {
+        StringBuilder sb = new StringBuilder();
+        // should be NPE if null passed
+        try {
+
+            sb.indexOf(null);
+            throw new RuntimeException("Test failed: should have thrown NPE");
+
+
+        } catch (NullPointerException npe) {
+            // expected: passed
+        } catch (Throwable t) {
+            throw new RuntimeException("Test failed: should have thrown NPE. Instead threw "
+                    + t);
+        }
+        sb = new StringBuilder("xyz");
+        assertEquals( sb.indexOf("y"), 1 );
+        assertEquals( sb.indexOf("not found"), -1 );
+    }
+
+
+    public void indexOfStringint() {
+        StringBuilder sb = new StringBuilder();
+        // should be NPE if null passed
+        try {
+            sb.indexOf(null,1);
+            throw new RuntimeException("Test failed: should have thrown NPE");
+        } catch (NullPointerException npe) {
+            // expected: passed
+        } catch (Throwable t) {
+            throw new RuntimeException("Test failed: should have thrown NPE");
+        }
+        sb = new StringBuilder("xyyz");
+        assertEquals( sb.indexOf("y",0), 1 );
+        assertEquals( sb.indexOf("y",1), 1 );
+        assertEquals( sb.indexOf("y",2), 2 );
+        assertEquals( sb.indexOf("not found"), -1 );
+    }
+
+
+    public void indexOfStringIntNull() {
+        StringBuffer sb = new StringBuffer();
+        // should be NPE if null passed
+        try {
+            sb.indexOf(null,1);
+            throw new RuntimeException("Test failed: should have thrown NPE");
+        } catch (NullPointerException npe) {
+            // expected: passed
+        } catch (Throwable t) {
+            throw new RuntimeException("Test failed: should have thrown NPE. Instead threw "
+                    + t);
+        }
+    }
+
+
+    public void indexOfStringNull() {
+        StringBuilder sb = new StringBuilder();
+
+        // should be NPE if null passed
+        try {
+            sb.indexOf(null);
+            throw new RuntimeException("Test failed: should have thrown NPE");
+        } catch (NullPointerException npe) {
+            // expected: passed
+        } catch (Throwable t) {
+            throw new RuntimeException("Test failed: should have thrown NPE. Instead threw "
+                    + t);
+        }
+    }
+
+
+    public void insertintboolean() {
+        boolean b = true;
+        StringBuilder sb = new StringBuilder("012345");
+        assertEquals( sb.insert( 2, b).toString(), "01true2345");
+    }
+
+
+    public void insertintchar() {
+        char c = 'C';
+        StringBuilder sb = new StringBuilder("012345");
+        assertEquals( sb.insert( 2, c ).toString(), "01C2345");
+    }
+
+
+    public void insertintCharSequence() {
+        final String initString = "012345";
+        // three different flavors of CharSequence
+        CharSequence aString = A_STRING_VAL;
+        CharSequence aStringBuilder = new StringBuilder(A_STRING_BUILDER_VAL);
+        CharSequence aStringBuffer = new StringBuffer(A_STRING_BUFFER_VAL);
+
+        assertEquals( new StringBuilder(initString).insert(2, aString).toString(), "01"+A_STRING_VAL+"2345" );
+
+        assertEquals( new StringBuilder(initString).insert(2, aStringBuilder).toString(), "01"+A_STRING_BUILDER_VAL+"2345" );
+
+        assertEquals( new StringBuilder(initString).insert(2, aStringBuffer).toString(), "01"+A_STRING_BUFFER_VAL+"2345" );
+
+        try {
+            new StringBuilder(initString).insert(7, aString);
+            throw new RuntimeException("Test failed: should have thrown IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException soob) {
+            // expected: passed
+        } catch (Throwable t) {
+            throw new RuntimeException("Test failed: should have thrown IndexOutOfBoundsException, but instead threw " + t.getMessage());
+
+        }
+    }
+
+
+    public void insertintdouble() {
+        double d = 99d;
+        StringBuilder sb = new StringBuilder("012345");
+        assertEquals( sb.insert( 2, d ).toString(), "0199.02345");    }
+
+
+    public void insertintfloat() {
+        float f = 99.0f;
+        StringBuilder sb = new StringBuilder("012345");
+        assertEquals( sb.insert( 2, f ).toString(), "0199.02345");    }
+
+
+    public void insertintint() {
+        int i = 99;
+        StringBuilder sb = new StringBuilder("012345");
+        assertEquals( sb.insert( 2, i ).toString(), "01992345");
+    }
+
+
+    public void insertintlong() {
+        long l = 99;
+        StringBuilder sb = new StringBuilder("012345");
+        assertEquals( sb.insert( 2, l ).toString(), "01992345");    }
+
+
+    public void insertintObject() {
+        StringBuilder sb = new StringBuilder("012345");
+        List<String> ls = new ArrayList<String>();
+        ls.add("A"); ls.add("B");
+        String lsString = ls.toString();
+        assertEquals( sb.insert(2, ls).toString(), "01"+lsString+"2345");
+
+        try {
+            sb.insert(sb.length()+1, ls);
+            throw new RuntimeException("Test failed: should have thrown StringIndexOutOfBoundsException");
+        } catch (StringIndexOutOfBoundsException soob) {
+            // expected: passed
+        } catch (Throwable t) {
+            throw new RuntimeException("Test failed: should have thrown StringIndexOutOfBoundsException, but instead threw:"
+                    + t);
+        }
+    }
+
+
+    public void lastIndexOfString() {
+        String xyz = "xyz";
+        String xyz3 = "xyzxyzxyz";
+        StringBuilder sb = new StringBuilder(xyz3);
+        int pos = sb.lastIndexOf("xyz");
+        assertEquals( pos, 2*xyz.length() );
+    }
+
+
+    public void lastIndexOfStringint() {
+        StringBuilder sb = new StringBuilder("xyzxyzxyz");
+        int pos = sb.lastIndexOf("xyz",5);
+        assertEquals( pos, 3 );
+        pos = sb.lastIndexOf("xyz", 6);
+        assertEquals( pos, 6 );
+    }
+
+    public void assertEquals( String actual, String expected) {
+        if (!actual.equals( expected )) {
+            throw new RuntimeException( "Test failed: actual = '" + actual +
+                    "', expected = '" + expected + "'");
+        }
+    }
+
+    public void assertEquals( int actual, int expected) {
+        if (actual != expected) {
+            throw new RuntimeException( "Test failed: actual = '" + actual +
+                    "', expected = '" + expected + "'");
+        }
+    }
+}
+