OSDN Git Service

Update Luni to Harmony r802921.
authorJesse Wilson <jessewilson@google.com>
Tue, 11 Aug 2009 01:43:30 +0000 (18:43 -0700)
committerJesse Wilson <jessewilson@google.com>
Tue, 11 Aug 2009 23:49:12 +0000 (16:49 -0700)
Notable changes:
 - replaced StringBuffer with StringBuilder in several places
 - fixed a problem with BufferedInputStream's newline characters (EBCDIC)
 - cleanup Timer's finalizer helper object
 - new cache for the canonical path of a file
 - fixed concurrency issue with ArrayList
 - floating point parsing now trims length for very small numbers
 - encoding specified "UTF-8" when converting some byte[]s to strings (JarURLConnection, Util, OSFileSystem)
 - Harmony now implements floor and ceil in Java. We continue to use native code.

46 files changed:
libcore/luni/src/main/java/java/io/BufferedReader.java
libcore/luni/src/main/java/java/io/DataInputStream.java
libcore/luni/src/main/java/java/io/File.java
libcore/luni/src/main/java/java/io/PipedInputStream.java
libcore/luni/src/main/java/java/io/PushbackInputStream.java
libcore/luni/src/main/java/java/io/StreamTokenizer.java
libcore/luni/src/main/java/java/lang/AbstractStringBuilder.java
libcore/luni/src/main/java/java/lang/Math.java
libcore/luni/src/main/java/java/lang/String.java
libcore/luni/src/main/java/java/lang/reflect/Modifier.java
libcore/luni/src/main/java/java/net/ServerSocket.java
libcore/luni/src/main/java/java/net/SocketImpl.java
libcore/luni/src/main/java/java/net/SocketPermission.java
libcore/luni/src/main/java/java/net/URI.java
libcore/luni/src/main/java/java/net/URIEncoderDecoder.java
libcore/luni/src/main/java/java/net/URLClassLoader.java
libcore/luni/src/main/java/java/net/URLConnection.java
libcore/luni/src/main/java/java/net/URLEncoder.java
libcore/luni/src/main/java/java/net/URLStreamHandler.java
libcore/luni/src/main/java/java/util/AbstractList.java
libcore/luni/src/main/java/java/util/ArrayList.java
libcore/luni/src/main/java/java/util/BitSet.java
libcore/luni/src/main/java/java/util/Calendar.java
libcore/luni/src/main/java/java/util/Date.java
libcore/luni/src/main/java/java/util/HashMap.java
libcore/luni/src/main/java/java/util/Hashtable.java
libcore/luni/src/main/java/java/util/IdentityHashMap.java
libcore/luni/src/main/java/java/util/Locale.java
libcore/luni/src/main/java/java/util/Properties.java
libcore/luni/src/main/java/java/util/TimeZone.java
libcore/luni/src/main/java/java/util/Timer.java
libcore/luni/src/main/java/java/util/Vector.java
libcore/luni/src/main/java/org/apache/harmony/luni/internal/io/FileCanonPathCache.java [new file with mode: 0644]
libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/ftp/FtpURLConnection.java
libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java
libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/Handler.java
libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/jar/JarURLConnection.java
libcore/luni/src/main/java/org/apache/harmony/luni/platform/IMemorySystem.java
libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java
libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
libcore/luni/src/main/java/org/apache/harmony/luni/util/ExternalMessages.properties
libcore/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java
libcore/luni/src/main/java/org/apache/harmony/luni/util/Util.java
libcore/luni/src/main/native/cbigint.c
libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/AllTests.java
libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileCanonPathCacheTest.java [new file with mode: 0644]

index 875840c..77f1975 100644 (file)
@@ -30,13 +30,13 @@ import java.util.logging.Logger;
  * some extra space is required to hold the buffer and that copying takes place
  * when filling that buffer, but this is usually outweighed by the performance
  * benefits.
- *
+ * 
  * <p/>A typical application pattern for the class looks like this:<p/>
  *
  * <pre>
  * BufferedReader buf = new BufferedReader(new FileReader(&quot;file.java&quot;));
  * </pre>
- *
+ * 
  * @see BufferedWriter
  * @since 1.1
  */
@@ -57,7 +57,7 @@ public class BufferedReader extends Reader {
     /**
      * Constructs a new BufferedReader on the Reader {@code in}. The
      * buffer gets the default size (8 KB).
-     *
+     * 
      * @param in
      *            the Reader that is buffered.
      */
@@ -85,7 +85,7 @@ public class BufferedReader extends Reader {
     /**
      * Constructs a new BufferedReader on the Reader {@code in}. The buffer
      * size is specified by the parameter {@code size}.
-     *
+     * 
      * @param in
      *            the Reader that is buffered.
      * @param size
@@ -106,7 +106,7 @@ public class BufferedReader extends Reader {
      * Closes this reader. This implementation closes the buffered source reader
      * and releases the buffer. Nothing is done if this reader has already been
      * closed.
-     *
+     * 
      * @throws IOException
      *             if an error occurs while closing this reader.
      */
@@ -154,7 +154,7 @@ public class BufferedReader extends Reader {
 
     /**
      * Indicates whether or not this reader is closed.
-     *
+     * 
      * @return {@code true} if this reader is closed, {@code false}
      *         otherwise.
      */
@@ -167,7 +167,7 @@ public class BufferedReader extends Reader {
      * indicates how many characters can be read before the mark is invalidated.
      * Calling {@code reset()} will reposition the reader back to the marked
      * position if {@code readlimit} has not been surpassed.
-     *
+     * 
      * @param readlimit
      *            the number of characters that can be read before the mark is
      *            invalidated.
@@ -195,7 +195,7 @@ public class BufferedReader extends Reader {
     /**
      * Indicates whether this reader supports the {@code mark()} and
      * {@code reset()} methods. This implementation returns {@code true}.
-     *
+     * 
      * @return {@code true} for {@code BufferedReader}.
      * @see #mark(int)
      * @see #reset()
@@ -240,7 +240,7 @@ public class BufferedReader extends Reader {
      * has not been set and the requested number of characters is larger than
      * this readers buffer size, BufferedReader bypasses the buffer and simply
      * places the results directly into {@code buffer}.
-     *
+     * 
      * @param buffer
      *            the character array to store the characters read.
      * @param offset
@@ -329,9 +329,8 @@ public class BufferedReader extends Reader {
      * Returns the next line of text available from this reader. A line is
      * represented by zero or more characters followed by {@code '\n'},
      * {@code '\r'}, {@code "\r\n"} or the end of the reader. The string does
-     * not include the newline sequence. In EBCDIC systems, a new line can also
-     * be represented by the {@code &#92;u0085} (NEL) character.
-     *
+     * not include the newline sequence.
+     * 
      * @return the contents of the line or {@code null} if no characters were
      *         read before the end of the reader has been reached.
      * @throws IOException
@@ -351,7 +350,7 @@ public class BufferedReader extends Reader {
                 // BEGIN android-note
                 // a switch statement may be more efficient
                 // END android-note
-                if ((ch > '\r') && (ch != '\u0085')) {
+                if (ch > '\r') {
                     continue;
                 }
                 if (ch == '\n') {
@@ -366,11 +365,6 @@ public class BufferedReader extends Reader {
                         pos++;
                     }
                     return res;
-                } else if (ch == '\u0085') {
-                    /* Also handle the EBCDIC NEL character */
-                    String res = new String(buf, pos, charPos - pos);
-                    pos = charPos + 1;
-                    return res;
                 }
             }
 
@@ -398,7 +392,7 @@ public class BufferedReader extends Reader {
                     // use a local variable for buf[charPos] and a switch statement
                     // END android-note
                     if (eol == '\0') {
-                        if ((buf[charPos] == '\n' || buf[charPos] == '\r') || (buf[charPos] == '\u0085')) {
+                        if ((buf[charPos] == '\n' || buf[charPos] == '\r')) {
                             eol = buf[charPos];
                         }
                     } else if (eol == '\r' && (buf[charPos] == '\n')) {
@@ -407,7 +401,7 @@ public class BufferedReader extends Reader {
                         }
                         pos = charPos + 1;
                         return result.toString();
-                    } else if (eol != '\0') {
+                    } else {
                         if (charPos > pos) {
                             result.append(buf, pos, charPos - pos - 1);
                         }
@@ -451,7 +445,7 @@ public class BufferedReader extends Reader {
      * Resets this reader's position to the last {@code mark()} location.
      * Invocations of {@code read()} and {@code skip()} will occur from this new
      * location.
-     *
+     * 
      * @throws IOException
      *             if this reader is closed or no mark has been set.
      * @see #mark(int)
@@ -475,7 +469,7 @@ public class BufferedReader extends Reader {
      * {@code read()}s will not return these characters unless {@code reset()}
      * is used. Skipping characters may invalidate a mark if {@code readlimit}
      * is surpassed.
-     *
+     * 
      * @param amount
      *            the maximum number of characters to skip.
      * @return the number of characters actually skipped.
index 42e38a2..cb21986 100644 (file)
@@ -303,7 +303,7 @@ public class DataInputStream extends FilterInputStream implements DataInput {
      */
     @Deprecated
     public final String readLine() throws IOException {
-        StringBuffer line = new StringBuffer(80); // Typical line length
+        StringBuilder line = new StringBuilder(80); // Typical line length
         boolean foundTerminator = false;
         while (true) {
             int nextByte = in.read();
index e34ab18..c802995 100644 (file)
@@ -25,6 +25,7 @@ import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.harmony.luni.internal.io.FileCanonPathCache;
 import org.apache.harmony.luni.util.DeleteOnExit;
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.PriviAction;
@@ -495,6 +496,12 @@ public class File implements Serializable, Comparable<File> {
      */
     public String getCanonicalPath() throws IOException {
         byte[] result = properPath(false);
+        String absPath = Util.toUTF8String(result);
+        String canonPath = FileCanonPathCache.get(absPath);
+
+        if (canonPath != null) {
+            return canonPath;
+        }
         if(separatorChar == '/') {
             // resolve the full path first
             result = resolveLink(result, result.length, false);
@@ -566,7 +573,9 @@ public class File implements Serializable, Comparable<File> {
         newResult[newLength] = 0;
         newResult = getCanonImpl(newResult);
         newLength = newResult.length;
-        return Util.toUTF8String(newResult, 0, newLength);
+        canonPath = Util.toUTF8String(newResult, 0, newLength);
+        FileCanonPathCache.put(absPath, canonPath);
+        return canonPath;
     }
 
     /*
index d06143d..83987ec 100644 (file)
@@ -150,11 +150,18 @@ public class PipedInputStream extends InputStream {
     @Override
     public synchronized int read() throws IOException {
         if (!isConnected) {
+            // K0074=Not connected
             throw new IOException(Msg.getString("K0074")); //$NON-NLS-1$
         }
         if (buffer == null) {
+            // K0075=InputStream is closed
             throw new IOException(Msg.getString("K0075")); //$NON-NLS-1$
         }
+
+        if (lastWriter != null && !lastWriter.isAlive() && (in < 0)) {
+            // KA030=Write end dead
+            throw new IOException(Msg.getString("KA030")); //$NON-NLS-1$
+        }
         /**
          * Set the last thread to be reading on this PipedInputStream. If
          * lastReader dies while someone is waiting to write an IOException of
@@ -169,6 +176,7 @@ public class PipedInputStream extends InputStream {
                     return -1;
                 }
                 if ((attempts-- <= 0) && lastWriter != null && !lastWriter.isAlive()) {
+                    // K0076=Pipe broken
                     throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
                 }
                 // Notify callers of receive()
@@ -244,13 +252,20 @@ public class PipedInputStream extends InputStream {
         }
 
         if (!isConnected) {
+            // K0074=Not connected
             throw new IOException(Msg.getString("K0074")); //$NON-NLS-1$
         }
 
         if (buffer == null) {
+            // K0075=InputStream is closed
             throw new IOException(Msg.getString("K0075")); //$NON-NLS-1$
         }
 
+        if (lastWriter != null && !lastWriter.isAlive() && (in < 0)) {
+            // KA030=Write end dead
+            throw new IOException(Msg.getString("KA030")); //$NON-NLS-1$
+        }
+
         /**
          * Set the last thread to be reading on this PipedInputStream. If
          * lastReader dies while someone is waiting to write an IOException of
@@ -265,6 +280,7 @@ public class PipedInputStream extends InputStream {
                     return -1;
                 }
                 if ((attempts-- <= 0) && lastWriter != null && !lastWriter.isAlive()) {
+                    // K0076=Pipe broken
                     throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
                 }
                 // Notify callers of receive()
index 1784012..4600fa2 100644 (file)
@@ -314,9 +314,11 @@ public class PushbackInputStream extends FilterInputStream {
         }
         // END android-changed
 
-        for (int i = offset + length - 1; i >= offset; i--) {
-            unread(buffer[i]);
+        if (buf == null) {
+            throw new IOException();
         }
+        System.arraycopy(buffer, offset, buf, pos - length, length);
+        pos = pos - length;
     }
 
     /**
index d39e5a8..c87a053 100644 (file)
@@ -336,7 +336,7 @@ public class StreamTokenizer {
         }
         // Check for words
         if ((currentType & TOKEN_WORD) != 0) {
-            StringBuffer word = new StringBuffer(20);
+            StringBuilder word = new StringBuilder(20);
             while (true) {
                 word.append((char) currentChar);
                 currentChar = read();
@@ -353,7 +353,7 @@ public class StreamTokenizer {
         // Check for quoted character
         if (currentType == TOKEN_QUOTE) {
             int matchQuote = currentChar;
-            StringBuffer quoteString = new StringBuffer();
+            StringBuilder quoteString = new StringBuilder();
             int peekOne = read();
             while (peekOne >= 0 && peekOne != matchQuote && peekOne != '\r'
                     && peekOne != '\n') {
index 06f8c50..c481e11 100644 (file)
@@ -231,7 +231,7 @@ abstract class AbstractStringBuilder {
             }
             if (end > start) {
                 int length = count - end;
-                if (length > 0) {
+                if (length >= 0) {
                     if (!shared) {
                         System.arraycopy(value, end, value, start, length);
                     } else {
index 998856a..d06e6e4 100644 (file)
@@ -17,7 +17,6 @@
 
 package java.lang;
 
-
 /**
  * Class Math provides basic math constants and operations such as trigonometric
  * functions, hyperbolic functions, exponential, logarithms, etc.
@@ -53,16 +52,16 @@ public final class Math {
      * <li>{@code abs(-infinity) = +infinity}</li>
      * <li>{@code abs(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the value whose absolute value has to be computed.
      * @return the absolute value of the argument.
      */
-       public static double abs(double d) {
-               long bits = Double.doubleToLongBits(d);
-               bits &= 0x7fffffffffffffffL;
-               return Double.longBitsToDouble(bits);
-       }
+    public static double abs(double d) {
+        long bits = Double.doubleToLongBits(d);
+        bits &= 0x7fffffffffffffffL;
+        return Double.longBitsToDouble(bits);
+    }
 
     /**
      * Returns the absolute value of the argument.
@@ -74,45 +73,45 @@ public final class Math {
      * <li>{@code abs(-infinity) = +infinity}</li>
      * <li>{@code abs(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param f
      *            the value whose absolute value has to be computed.
      * @return the argument if it is positive, otherwise the negation of the
      *         argument.
      */
-       public static float abs(float f) {
-               int bits = Float.floatToIntBits(f);
-               bits &= 0x7fffffff;
-               return Float.intBitsToFloat(bits);
-       }
+    public static float abs(float f) {
+        int bits = Float.floatToIntBits(f);
+        bits &= 0x7fffffff;
+        return Float.intBitsToFloat(bits);
+    }
 
     /**
      * Returns the absolute value of the argument.
      * <p>
      * If the argument is {@code Integer.MIN_VALUE}, {@code Integer.MIN_VALUE}
      * is returned.
-     *
+     * 
      * @param i
      *            the value whose absolute value has to be computed.
      * @return the argument if it is positive, otherwise the negation of the
      *         argument.
      */
-       public static int abs(int i) {
-               return i >= 0 ? i : -i;
-       }
+    public static int abs(int i) {
+        return i >= 0 ? i : -i;
+    }
 
     /**
      * Returns the absolute value of the argument. If the argument is {@code
      * Long.MIN_VALUE}, {@code Long.MIN_VALUE} is returned.
-     *
+     * 
      * @param l
      *            the value whose absolute value has to be computed.
      * @return the argument if it is positive, otherwise the negation of the
      *         argument.
      */
-       public static long abs(long l) {
-               return l >= 0 ? l : -l;
-       }
+    public static long abs(long l) {
+        return l >= 0 ? l : -l;
+    }
 
     /**
      * Returns the closest double approximation of the arc cosine of the
@@ -125,12 +124,12 @@ public final class Math {
      * <li>{@code acos((anything < -1) = NaN}</li>
      * <li>{@code acos(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the value to compute arc cosine of.
      * @return the arc cosine of the argument.
      */
-       public static native double acos(double d);
+    public static native double acos(double d);
 
     /**
      * Returns the closest double approximation of the arc sine of the argument
@@ -143,12 +142,12 @@ public final class Math {
      * <li>{@code asin((anything < -1)) = NaN}</li>
      * <li>{@code asin(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the value whose arc sine has to be computed.
      * @return the arc sine of the argument.
      */
-       public static native double asin(double d);
+    public static native double asin(double d);
 
     /**
      * Returns the closest double approximation of the arc tangent of the
@@ -163,7 +162,7 @@ public final class Math {
      * <li>{@code atan(-infinity) = -pi/2}</li>
      * <li>{@code atan(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the value whose arc tangent has to be computed.
      * @return the arc tangent of the argument.
@@ -171,10 +170,10 @@ public final class Math {
     public static native double atan(double d);
 
     /**
-     * Returns the closest double approximation of the arc tangent of
-     * {@code y/x} within the range {@code [-pi..pi]}. This is the angle of the
-     * polar representation of the rectangular coordinates (x,y). The returned
-     * result is within 2 ulps (units in the last place) of the real result.
+     * Returns the closest double approximation of the arc tangent of {@code
+     * y/x} within the range {@code [-pi..pi]}. This is the angle of the polar
+     * representation of the rectangular coordinates (x,y). The returned result
+     * is within 2 ulps (units in the last place) of the real result.
      * <p>
      * Special cases:
      * <ul>
@@ -196,12 +195,12 @@ public final class Math {
      * <li>{@code atan2(-infinity, +infinity ) = -pi/4}</li>
      * <li>{@code atan2(+infinity, -infinity ) = +3pi/4}</li>
      * <li>{@code atan2(-infinity, -infinity ) = -3pi/4}</li>
-     * <li>{@code atan2(+infinity, (anything but,0, NaN, and infinity))}
-     * {@code =} {@code +pi/2}</li>
-     * <li>{@code atan2(-infinity, (anything but,0, NaN, and infinity))}
-     * {@code =} {@code -pi/2}</li>
+     * <li>{@code atan2(+infinity, (anything but,0, NaN, and infinity))} {@code
+     * =} {@code +pi/2}</li>
+     * <li>{@code atan2(-infinity, (anything but,0, NaN, and infinity))} {@code
+     * =} {@code -pi/2}</li>
      * </ul>
-     *
+     * 
      * @param y
      *            the numerator of the value whose atan has to be computed.
      * @param x
@@ -222,7 +221,7 @@ public final class Math {
      * <li>{@code cbrt(-infinity) = -infinity}</li>
      * <li>{@code cbrt(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the value whose cube root has to be computed.
      * @return the cube root of the argument.
@@ -230,8 +229,8 @@ public final class Math {
     public static native double cbrt(double d);
 
     /**
-     * Returns the double conversion of the most negative (closest to
-     * negative infinity) integer value which is greater than the argument.
+     * Returns the double conversion of the most negative (closest to negative
+     * infinity) integer value which is greater than the argument.
      * <p>
      * Special cases:
      * <ul>
@@ -242,14 +241,16 @@ public final class Math {
      * <li>{@code ceil(-infinity) = -infinity}</li>
      * <li>{@code ceil(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the value whose closest integer value has to be computed.
      * @return the ceiling of the argument.
      */
+    // BEGIN android-changed
     public static native double ceil(double d);
+    // END android-changed
 
-       /**
+    /**
      * Returns the closest double approximation of the cosine of the argument.
      * The returned result is within 1 ulp (unit in the last place) of the real
      * result.
@@ -260,7 +261,7 @@ public final class Math {
      * <li>{@code cos(-infinity) = NaN}</li>
      * <li>{@code cos(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the angle whose cosine has to be computed, in radians.
      * @return the cosine of the argument.
@@ -278,7 +279,7 @@ public final class Math {
      * <li>{@code cosh(-infinity) = +infinity}</li>
      * <li>{@code cosh(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the value whose hyperbolic cosine has to be computed.
      * @return the hyperbolic cosine of the argument.
@@ -296,7 +297,7 @@ public final class Math {
      * <li>{@code exp(-infinity) = +0.0}</li>
      * <li>{@code exp(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the value whose exponential has to be computed.
      * @return the exponential of the argument.
@@ -304,9 +305,9 @@ public final class Math {
     public static native double exp(double d);
 
     /**
-     * Returns the closest double approximation of <i>{@code e}</i><sup>
-     * {@code d}</sup>{@code - 1}. If the argument is very close to 0, it is
-     * much more accurate to use {@code expm1(d)+1} than {@code exp(d)} (due to
+     * Returns the closest double approximation of <i>{@code e}</i><sup> {@code
+     * d}</sup>{@code - 1}. If the argument is very close to 0, it is much more
+     * accurate to use {@code expm1(d)+1} than {@code exp(d)} (due to
      * cancellation of significant digits). The returned result is within 1 ulp
      * (unit in the last place) of the real result.
      * <p>
@@ -321,12 +322,12 @@ public final class Math {
      * <li>{@code expm1(-infinity) = -1.0}</li>
      * <li>{@code expm1(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
-     *            the value to compute the <i>{@code e}</i><sup>{@code d}
-     *            </sup>{@code - 1} of.
-     * @return the <i>{@code e}</i><sup>{@code d}</sup>{@code - 1} value
-     *         of the argument.
+     *            the value to compute the <i>{@code e}</i><sup>{@code d} </sup>
+     *            {@code - 1} of.
+     * @return the <i>{@code e}</i><sup>{@code d}</sup>{@code - 1} value of the
+     *         argument.
      */
     public static native double expm1(double d);
 
@@ -342,19 +343,21 @@ public final class Math {
      * <li>{@code floor(-infinity) = -infinity}</li>
      * <li>{@code floor(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the value whose closest integer value has to be computed.
      * @return the floor of the argument.
      */
+    // BEGIN android-changed
     public static native double floor(double d);
+    // END android-changed
 
     /**
-     * Returns {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +}
-     * <i> {@code y}</i><sup>{@code 2}</sup>{@code )}. The final result is
-     * without medium underflow or overflow. The returned result is within 1 ulp
-     * (unit in the last place) of the real result. If one parameter remains
-     * constant, the result should be semi-monotonic.
+     * Returns {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +} <i>
+     * {@code y}</i><sup>{@code 2}</sup>{@code )}. The final result is without
+     * medium underflow or overflow. The returned result is within 1 ulp (unit
+     * in the last place) of the real result. If one parameter remains constant,
+     * the result should be semi-monotonic.
      * <p>
      * Special cases:
      * <ul>
@@ -364,7 +367,7 @@ public final class Math {
      * <li>{@code hypot((anything including NaN), -infinity) = +infinity}</li>
      * <li>{@code hypot(NaN, NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param x
      *            a double number.
      * @param y
@@ -393,7 +396,7 @@ public final class Math {
      * <li>{@code IEEEremainder(x, -infinity) = x } where x is anything but
      * +/-infinity</li>
      * </ul>
-     *
+     * 
      * @param x
      *            the numerator of the operation.
      * @param y
@@ -416,7 +419,7 @@ public final class Math {
      * <li>{@code log(-infinity) = NaN}</li>
      * <li>{@code log(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the value whose log has to be computed.
      * @return the natural logarithm of the argument.
@@ -437,7 +440,7 @@ public final class Math {
      * <li>{@code log10(-infinity) = NaN}</li>
      * <li>{@code log10(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the value whose base 10 log has to be computed.
      * @return the natural logarithm of the argument.
@@ -461,7 +464,7 @@ public final class Math {
      * <li>{@code log1p(-infinity) = NaN}</li>
      * <li>{@code log1p(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the value to compute the {@code ln(1+d)} of.
      * @return the natural logarithm of the sum of the argument and 1.
@@ -479,16 +482,14 @@ public final class Math {
      * <li>{@code max(+0.0, -0.0) = +0.0}</li>
      * <li>{@code max(-0.0, +0.0) = +0.0}</li>
      * </ul>
-     *
+     * 
      * @param d1
      *            the first argument.
      * @param d2
      *            the second argument.
      * @return the larger of {@code d1} and {@code d2}.
      */
-       public static double max(double d1, double d2) {
-        // BEGIN android-changed
-        // copied from a newer version of Harmony
+    public static double max(double d1, double d2) {
         if (d1 > d2) {
             return d1;
         }
@@ -505,8 +506,7 @@ public final class Math {
             return d2;
         }
         return 0.0d;
-        // END android-changed
-       }
+    }
 
     /**
      * Returns the most positive (closest to positive infinity) of the two
@@ -519,16 +519,14 @@ public final class Math {
      * <li>{@code max(+0.0, -0.0) = +0.0}</li>
      * <li>{@code max(-0.0, +0.0) = +0.0}</li>
      * </ul>
-     *
+     * 
      * @param f1
      *            the first argument.
      * @param f2
      *            the second argument.
      * @return the larger of {@code f1} and {@code f2}.
      */
-       public static float max(float f1, float f2) {
-        // BEGIN android-changed
-        // copied from a newer version of Harmony
+    public static float max(float f1, float f2) {
         if (f1 > f2) {
             return f1;
         }
@@ -545,36 +543,35 @@ public final class Math {
             return f2;
         }
         return 0.0f;
-        // END android-changed
-       }
+    }
 
     /**
      * Returns the most positive (closest to positive infinity) of the two
      * arguments.
-     *
+     * 
      * @param i1
      *            the first argument.
      * @param i2
      *            the second argument.
      * @return the larger of {@code i1} and {@code i2}.
      */
-       public static int max(int i1, int i2) {
-               return i1 > i2 ? i1 : i2;
-       }
+    public static int max(int i1, int i2) {
+        return i1 > i2 ? i1 : i2;
+    }
 
     /**
      * Returns the most positive (closest to positive infinity) of the two
      * arguments.
-     *
+     * 
      * @param l1
      *            the first argument.
      * @param l2
      *            the second argument.
      * @return the larger of {@code l1} and {@code l2}.
      */
-       public static long max(long l1, long l2) {
-               return l1 > l2 ? l1 : l2;
-       }
+    public static long max(long l1, long l2) {
+        return l1 > l2 ? l1 : l2;
+    }
 
     /**
      * Returns the most negative (closest to negative infinity) of the two
@@ -587,16 +584,14 @@ public final class Math {
      * <li>{@code min(+0.0, -0.0) = -0.0}</li>
      * <li>{@code min(-0.0, +0.0) = -0.0}</li>
      * </ul>
-     *
+     * 
      * @param d1
      *            the first argument.
      * @param d2
      *            the second argument.
      * @return the smaller of {@code d1} and {@code d2}.
      */
-       public static double min(double d1, double d2) {
-        // BEGIN android-changed
-        // copied from a newer version of Harmony
+    public static double min(double d1, double d2) {
         if (d1 > d2) {
             return d2;
         }
@@ -613,8 +608,7 @@ public final class Math {
             return -0.0d;
         }
         return d2;
-        // END android-changed
-       }
+    }
 
     /**
      * Returns the most negative (closest to negative infinity) of the two
@@ -627,16 +621,14 @@ public final class Math {
      * <li>{@code min(+0.0, -0.0) = -0.0}</li>
      * <li>{@code min(-0.0, +0.0) = -0.0}</li>
      * </ul>
-     *
+     * 
      * @param f1
      *            the first argument.
      * @param f2
      *            the second argument.
      * @return the smaller of {@code f1} and {@code f2}.
      */
-       public static float min(float f1, float f2) {
-        // BEGIN android-changed
-        // copied from a newer version of Harmony
+    public static float min(float f1, float f2) {
         if (f1 > f2) {
             return f2;
         }
@@ -653,40 +645,39 @@ public final class Math {
             return -0.0f;
         }
         return f2;
-        // END android-changed
-       }
+    }
 
     /**
      * Returns the most negative (closest to negative infinity) of the two
      * arguments.
-     *
+     * 
      * @param i1
      *            the first argument.
      * @param i2
      *            the second argument.
      * @return the smaller of {@code i1} and {@code i2}.
      */
-       public static int min(int i1, int i2) {
-               return i1 < i2 ? i1 : i2;
-       }
+    public static int min(int i1, int i2) {
+        return i1 < i2 ? i1 : i2;
+    }
 
     /**
      * Returns the most negative (closest to negative infinity) of the two
      * arguments.
-     *
+     * 
      * @param l1
      *            the first argument.
      * @param l2
      *            the second argument.
      * @return the smaller of {@code l1} and {@code l2}.
      */
-       public static long min(long l1, long l2) {
-               return l1 < l2 ? l1 : l2;
-       }
+    public static long min(long l1, long l2) {
+        return l1 < l2 ? l1 : l2;
+    }
 
     /**
-     * Returns the closest double approximation of the result of raising
-     * {@code x} to the power of {@code y}.
+     * Returns the closest double approximation of the result of raising {@code
+     * x} to the power of {@code y}.
      * <p>
      * Special cases:
      * <ul>
@@ -710,11 +701,11 @@ public final class Math {
      * <li>{@code pow(+infinity, (+anything except 0, NaN)) = +infinity}</li>
      * <li>{@code pow(+infinity, (-anything except 0, NaN)) = +0.0}</li>
      * <li>{@code pow(-infinity, (anything)) = -pow(0, (-anything))}</li>
-     * <li>{@code pow((-anything), (integer))} {@code =}
-     * {@code pow(-1,(integer))*pow(+anything,integer) }</li>
+     * <li>{@code pow((-anything), (integer))} {@code =} {@code
+     * pow(-1,(integer))*pow(+anything,integer) }</li>
      * <li>{@code pow((-anything except 0 and inf), (non-integer)) = NAN}</li>
      * </ul>
-     *
+     * 
      * @param x
      *            the base of the operation.
      * @param y
@@ -735,14 +726,16 @@ public final class Math {
      * <li>{@code rint(-infinity) = -infinity}</li>
      * <li>{@code rint(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the value to be rounded.
      * @return the closest integer to the argument (as a double).
      */
+    // BEGIN android-changed
     public static native double rint(double d);
+    // END android-changed
 
-       /**
+    /**
      * Returns the result of rounding the argument to an integer. The result is
      * equivalent to {@code (long) Math.floor(d+0.5)}.
      * <p>
@@ -756,17 +749,18 @@ public final class Math {
      * <li>{@code round(-infintiy) = Long.MIN_VALUE}</li>
      * <li>{@code round(NaN) = +0.0}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the value to be rounded.
      * @return the closest integer to the argument.
      */
-       public static long round(double d) {
-               // check for NaN
-               if (d != d)
-                       return 0L;
-               return (long) floor(d + 0.5d);
-       }
+    public static long round(double d) {
+        // check for NaN
+        if (d != d) {
+            return 0L;
+        }
+        return (long) floor(d + 0.5d);
+    }
 
     /**
      * Returns the result of rounding the argument to an integer. The result is
@@ -782,17 +776,18 @@ public final class Math {
      * <li>{@code round(-infintiy) = Integer.MIN_VALUE}</li>
      * <li>{@code round(NaN) = +0.0}</li>
      * </ul>
-     *
+     * 
      * @param f
      *            the value to be rounded.
      * @return the closest integer to the argument.
      */
-       public static int round(float f) {
-               // check for NaN
-               if (f != f)
-                       return 0;
-               return (int) floor(f + 0.5f);
-       }
+    public static int round(float f) {
+        // check for NaN
+        if (f != f) {
+            return 0;
+        }
+        return (int) floor(f + 0.5f);
+    }
 
     /**
      * Returns the signum function of the argument. If the argument is less than
@@ -808,7 +803,7 @@ public final class Math {
      * <li>{@code signum(-infinity) = -1.0}</li>
      * <li>{@code signum(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the value whose signum has to be computed.
      * @return the value of the signum function.
@@ -831,7 +826,7 @@ public final class Math {
      * <li>{@code signum(-infinity) = -1.0}</li>
      * <li>{@code signum(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param f
      *            the value whose signum has to be computed.
      * @return the value of the signum function.
@@ -853,7 +848,7 @@ public final class Math {
      * <li>{@code sin(-infinity) = NaN}</li>
      * <li>{@code sin(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the angle whose sin has to be computed, in radians.
      * @return the sine of the argument.
@@ -873,7 +868,7 @@ public final class Math {
      * <li>{@code sinh(-infinity) = -infinity}</li>
      * <li>{@code sinh(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the value whose hyperbolic sine has to be computed.
      * @return the hyperbolic sine of the argument.
@@ -892,7 +887,7 @@ public final class Math {
      * <li>{@code sqrt(+infinity) = +infinity}</li>
      * <li>{@code sqrt(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the value whose square root has to be computed.
      * @return the square root of the argument.
@@ -912,7 +907,7 @@ public final class Math {
      * <li>{@code tan(-infinity) = NaN}</li>
      * <li>{@code tan(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the angle whose tangens has to be computed, in radians.
      * @return the tangent of the argument.
@@ -934,7 +929,7 @@ public final class Math {
      * <li>{@code tanh(-infinity) = -1.0}</li>
      * <li>{@code tanh(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the value whose hyperbolic tangent has to be computed.
      * @return the hyperbolic tangent of the argument.
@@ -944,15 +939,15 @@ public final class Math {
     /**
      * Returns a pseudo-random number between 0.0 (inclusive) and 1.0
      * (exclusive).
-     *
+     * 
      * @return a pseudo-random number.
      */
-       public static double random() {
-               if (random == null) {
-                       random = new java.util.Random();
-               }
-               return random.nextDouble();
-       }
+    public static double random() {
+        if (random == null) {
+            random = new java.util.Random();
+        }
+        return random.nextDouble();
+    }
 
     /**
      * Returns the measure in radians of the supplied degree angle. The result
@@ -966,14 +961,14 @@ public final class Math {
      * <li>{@code toRadians(-infinity) = -infinity}</li>
      * <li>{@code toRadians(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param angdeg
      *            an angle in degrees.
      * @return the radian measure of the angle.
      */
-       public static double toRadians(double angdeg) {
-               return angdeg / 180d * PI;
-       }
+    public static double toRadians(double angdeg) {
+        return angdeg / 180d * PI;
+    }
 
     /**
      * Returns the measure in degrees of the supplied radian angle. The result
@@ -987,20 +982,20 @@ public final class Math {
      * <li>{@code toDegrees(-infinity) = -infinity}</li>
      * <li>{@code toDegrees(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param angrad
      *            an angle in radians.
      * @return the degree measure of the angle.
      */
-       public static double toDegrees(double angrad) {
-               return angrad * 180d / PI;
-       }
+    public static double toDegrees(double angrad) {
+        return angrad * 180d / PI;
+    }
 
-       /**
+    /**
      * Returns the argument's ulp (unit in the last place). The size of a ulp of
      * a double value is the positive distance between this value and the double
-     * value next larger in magnitude. For non-NaN {@code x},
-     * {@code ulp(-x) == ulp(x)}.
+     * value next larger in magnitude. For non-NaN {@code x}, {@code ulp(-x) ==
+     * ulp(x)}.
      * <p>
      * Special cases:
      * <ul>
@@ -1010,7 +1005,7 @@ public final class Math {
      * <li>{@code ulp(-infintiy) = infinity}</li>
      * <li>{@code ulp(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param d
      *            the floating-point value to compute ulp of.
      * @return the size of a ulp of the argument.
@@ -1029,8 +1024,8 @@ public final class Math {
     /**
      * Returns the argument's ulp (unit in the last place). The size of a ulp of
      * a float value is the positive distance between this value and the float
-     * value next larger in magnitude. For non-NaN {@code x},
-     * {@code ulp(-x) == ulp(x)}.
+     * value next larger in magnitude. For non-NaN {@code x}, {@code ulp(-x) ==
+     * ulp(x)}.
      * <p>
      * Special cases:
      * <ul>
@@ -1040,7 +1035,7 @@ public final class Math {
      * <li>{@code ulp(-infintiy) = infinity}</li>
      * <li>{@code ulp(NaN) = NaN}</li>
      * </ul>
-     *
+     * 
      * @param f
      *            the floating-point value to compute ulp of.
      * @return the size of a ulp of the argument.
@@ -1060,5 +1055,5 @@ public final class Math {
 
     private native static double nextafter(double x, double y);
 
-    private native static float nextafterf(float x, float y); 
+    private native static float nextafterf(float x, float y);
 }
index 22f72cb..6d53357 100644 (file)
@@ -77,7 +77,7 @@ public final class String implements Serializable, Comparable<String>,
         /**
          * Create a ConsolePrintStream on the specified OutputStream, usually
          * System.out.
-         *
+         * 
          * @param out
          *            the console OutputStream
          */
@@ -168,6 +168,9 @@ public final class String implements Serializable, Comparable<String>,
         count = 0;
     }
 
+    /*
+     * Private constructor used for JIT optimization.
+     */
     @SuppressWarnings("unused")
     private String(String s, char c) {
         offset = 0;
@@ -182,7 +185,7 @@ public final class String implements Serializable, Comparable<String>,
      * specified by the file.encoding system property. If the system property is
      * not defined, the default encoding is ISO8859_1 (ISO-Latin-1). If 8859-1
      * is not available, an ASCII encoding is used.
-     *
+     * 
      * @param data
      *            the byte array to convert to a string.
      */
@@ -193,7 +196,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Converts the byte array to a string, setting the high byte of every
      * character to the specified value.
-     *
+     * 
      * @param data
      *            the byte array to convert to a string.
      * @param high
@@ -213,7 +216,7 @@ public final class String implements Serializable, Comparable<String>,
      * specified by the file.encoding system property. If the system property is
      * not defined, the default encoding is ISO8859_1 (ISO-Latin-1). If 8859-1
      * is not available, an ASCII encoding is used.
-     *
+     * 
      * @param data
      *            the byte array to convert to a string.
      * @param start
@@ -288,7 +291,7 @@ public final class String implements Serializable, Comparable<String>,
 
     /**
      * Converts the byte array to a string using the specified encoding.
-     *
+     * 
      * @param data
      *            the byte array to convert to a string.
      * @param start
@@ -457,7 +460,7 @@ public final class String implements Serializable, Comparable<String>,
 
     /**
      * Converts the byte array to a string using the specified encoding.
-     *
+     * 
      * @param data
      *            the byte array to convert to a string.
      * @param encoding
@@ -475,7 +478,7 @@ public final class String implements Serializable, Comparable<String>,
      * Initializes this string to contain the characters in the specified
      * character array. Modifying the character array after creating the string
      * has no effect on the string.
-     *
+     * 
      * @param data
      *            the array of characters.
      * @throws NullPointerException
@@ -489,7 +492,7 @@ public final class String implements Serializable, Comparable<String>,
      * Initializes this string to contain the specified characters in the
      * character array. Modifying the character array after creating the string
      * has no effect on the string.
-     *
+     * 
      * @param data
      *            the array of characters.
      * @param start
@@ -527,7 +530,7 @@ public final class String implements Serializable, Comparable<String>,
 
     /**
      * Creates a {@code String} that is a copy of the specified string.
-     *
+     * 
      * @param string
      *            the string to copy.
      */
@@ -537,10 +540,51 @@ public final class String implements Serializable, Comparable<String>,
         count = string.count;
     }
 
+    /*
+     * Private constructor useful for JIT optimization.
+     */
+    @SuppressWarnings( { "unused", "nls" })
+    private String(String s1, String s2) {
+        if (s1 == null) {
+            s1 = "null";
+        }
+        if (s2 == null) {
+            s2 = "null";
+        }
+        count = s1.count + s2.count;
+        value = new char[count];
+        offset = 0;
+        System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
+        System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
+    }
+
+    /*
+     * Private constructor useful for JIT optimization.
+     */
+    @SuppressWarnings( { "unused", "nls" })
+    private String(String s1, String s2, String s3) {
+        if (s1 == null) {
+            s1 = "null";
+        }
+        if (s2 == null) {
+            s2 = "null";
+        }
+        if (s3 == null) {
+            s3 = "null";
+        }
+        count = s1.count + s2.count + s3.count;
+        value = new char[count];
+        offset = 0;
+        System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
+        System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
+        System.arraycopy(s3.value, s3.offset, value, s1.count + s2.count,
+                s3.count);
+    }
+
     /**
      * Creates a {@code String} from the contents of the specified
      * {@code StringBuffer}.
-     *
+     * 
      * @param stringbuffer
      *            the buffer to get the contents from.
      */
@@ -594,7 +638,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Creates a {@code String} from the contents of the specified {@code
      * StringBuilder}.
-     *
+     * 
      * @param sb
      *            the {@code StringBuilder} to copy the contents from.
      * @throws NullPointerException
@@ -630,7 +674,7 @@ public final class String implements Serializable, Comparable<String>,
 
     /**
      * Returns the character at the specified offset in this string.
-     *
+     * 
      * @param index
      *            the zero-based index in this string.
      * @return the character at the index.
@@ -688,7 +732,7 @@ public final class String implements Serializable, Comparable<String>,
      * Unicode value which is greater than the Unicode value of the character at
      * the same position in the specified string, or if the specified string is
      * a prefix of this string.
-     *
+     * 
      * @param string
      *            the string to compare.
      * @return 0 if the strings are equal, a negative integer if this string is
@@ -721,7 +765,7 @@ public final class String implements Serializable, Comparable<String>,
      * this string has a Unicode value which is greater than the Unicode value
      * of the character at the same position in the specified string, or if the
      * specified string is a prefix of this string.
-     *
+     * 
      * @param string
      *            the string to compare.
      * @return 0 if the strings are equal, a negative integer if this string is
@@ -750,7 +794,7 @@ public final class String implements Serializable, Comparable<String>,
 
     /**
      * Concatenates this string and the specified string.
-     *
+     * 
      * @param string
      *            the string to concatenate
      * @return a new string which is the concatenation of this string and the
@@ -771,7 +815,7 @@ public final class String implements Serializable, Comparable<String>,
      * Creates a new string containing the characters in the specified character
      * array. Modifying the character array after creating the string has no
      * effect on the string.
-     *
+     * 
      * @param data
      *            the array of characters.
      * @return the new string.
@@ -786,7 +830,7 @@ public final class String implements Serializable, Comparable<String>,
      * Creates a new string containing the specified characters in the character
      * array. Modifying the character array after creating the string has no
      * effect on the string.
-     *
+     * 
      * @param data
      *            the array of characters.
      * @param start
@@ -829,7 +873,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Compares the specified string to this string to determine if the
      * specified string is a suffix.
-     *
+     * 
      * @param suffix
      *            the suffix to look for.
      * @return {@code true} if the specified string is a suffix of this string,
@@ -845,7 +889,7 @@ public final class String implements Serializable, Comparable<String>,
      * Compares the specified object to this string and returns true if they are
      * equal. The object must be an instance of string with the same characters
      * in the same order.
-     *
+     * 
      * @param object
      *            the object to compare.
      * @return {@code true} if the specified object is equal to this string,
@@ -885,7 +929,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Compares the specified string to this string ignoring the case of the
      * characters and returns true if they are equal.
-     *
+     * 
      * @param string
      *            the string to compare.
      * @return {@code true} if the specified string is equal to this string,
@@ -919,7 +963,7 @@ public final class String implements Serializable, Comparable<String>,
      * specified by the file.encoding system property. If the system property is
      * not defined, the default encoding is ISO8859_1 (ISO-Latin-1). If 8859-1
      * is not available, an ASCII encoding is used.
-     *
+     * 
      * @return the byte array encoding of this string.
      */
     public byte[] getBytes() {
@@ -933,7 +977,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Converts this string to a byte array, ignoring the high order bits of
      * each character.
-     *
+     * 
      * @param start
      *            the starting offset of characters to copy.
      * @param end
@@ -967,7 +1011,7 @@ public final class String implements Serializable, Comparable<String>,
 
     /**
      * Converts this string to a byte array using the specified encoding.
-     *
+     * 
      * @param encoding
      *            the encoding to use.
      * @return the encoded byte array of this string.
@@ -1003,7 +1047,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Copies the specified characters in this string to the character array
      * starting at the specified offset in the character array.
-     *
+     * 
      * @param start
      *            the starting offset of characters to copy.
      * @param end
@@ -1065,7 +1109,7 @@ public final class String implements Serializable, Comparable<String>,
      * Searches in this string for the first index of the specified character.
      * The search for the character starts at the beginning and moves towards
      * the end of this string.
-     *
+     * 
      * @param c
      *            the character to find.
      * @return the index in this string of the specified character, -1 if the
@@ -1092,7 +1136,7 @@ public final class String implements Serializable, Comparable<String>,
      * Searches in this string for the index of the specified character. The
      * search for the character starts at the specified offset and moves towards
      * the end of this string.
-     *
+     * 
      * @param c
      *            the character to find.
      * @param start
@@ -1124,7 +1168,7 @@ public final class String implements Serializable, Comparable<String>,
      * Searches in this string for the first index of the specified string. The
      * search for the string starts at the beginning and moves towards the end
      * of this string.
-     *
+     * 
      * @param string
      *            the string to find.
      * @return the index of the first character of the specified string in this
@@ -1169,7 +1213,7 @@ public final class String implements Serializable, Comparable<String>,
      * Searches in this string for the index of the specified string. The search
      * for the string starts at the specified offset and moves towards the end
      * of this string.
-     *
+     * 
      * @param subString
      *            the string to find.
      * @param start
@@ -1219,17 +1263,16 @@ public final class String implements Serializable, Comparable<String>,
      * If the string is not in the table, it is added. Returns the string
      * contained in the table which is equal to this string. The same string
      * object is always returned for strings which are equal.
-     *
+     * 
      * @return the interned string equal to this string.
      */
     native public String intern();
 
-
     /**
      * Searches in this string for the last index of the specified character.
      * The search for the character starts at the end and moves towards the
      * beginning of this string.
-     *
+     * 
      * @param c
      *            the character to find.
      * @return the index in this string of the specified character, -1 if the
@@ -1253,7 +1296,7 @@ public final class String implements Serializable, Comparable<String>,
      * Searches in this string for the index of the specified character. The
      * search for the character starts at the specified offset and moves towards
      * the beginning of this string.
-     *
+     * 
      * @param c
      *            the character to find.
      * @param start
@@ -1284,7 +1327,7 @@ public final class String implements Serializable, Comparable<String>,
      * Searches in this string for the last index of the specified string. The
      * search for the string starts at the end and moves towards the beginning
      * of this string.
-     *
+     * 
      * @param string
      *            the string to find.
      * @return the index of the first character of the specified string in this
@@ -1301,7 +1344,7 @@ public final class String implements Serializable, Comparable<String>,
      * Searches in this string for the index of the specified string. The search
      * for the string starts at the specified offset and moves towards the
      * beginning of this string.
-     *
+     * 
      * @param subString
      *            the string to find.
      * @param start
@@ -1345,7 +1388,7 @@ public final class String implements Serializable, Comparable<String>,
 
     /**
      * Returns the size of this string.
-     *
+     * 
      * @return the number of characters in this string.
      */
     public int length() {
@@ -1355,7 +1398,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Compares the specified string to this string and compares the specified
      * range of characters to determine if they are the same.
-     *
+     * 
      * @param thisStart
      *            the starting offset in this string.
      * @param string
@@ -1400,7 +1443,7 @@ public final class String implements Serializable, Comparable<String>,
      * Compares the specified string to this string and compares the specified
      * range of characters to determine if they are the same. When ignoreCase is
      * true, the case of the characters is ignored during the comparison.
-     *
+     * 
      * @param ignoreCase
      *            specifies if case should be ignored.
      * @param thisStart
@@ -1451,7 +1494,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Copies this string replacing occurrences of the specified character with
      * another character.
-     *
+     * 
      * @param oldChar
      *            the character to replace.
      * @param newChar
@@ -1485,12 +1528,12 @@ public final class String implements Serializable, Comparable<String>,
         return copied ? new String(0, count, buffer) : this;
         // END android-changed
     }
-
+    
     /**
      * Copies this string replacing occurrences of the specified target sequence
      * with another sequence. The string is processed from the beginning to the
      * end.
-     *
+     * 
      * @param target
      *            the sequence to replace.
      * @param replacement
@@ -1530,7 +1573,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Compares the specified string to this string to determine if the
      * specified string is a prefix.
-     *
+     * 
      * @param prefix
      *            the string to look for.
      * @return {@code true} if the specified string is a prefix of this string,
@@ -1545,7 +1588,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Compares the specified string to this string, starting at the specified
      * offset, to determine if the specified string is a prefix.
-     *
+     * 
      * @param prefix
      *            the string to look for.
      * @param start
@@ -1561,7 +1604,7 @@ public final class String implements Serializable, Comparable<String>,
 
     /**
      * Copies a range of characters into a new string.
-     *
+     * 
      * @param start
      *            the offset of the first character.
      * @return a new string containing the characters from start to the end of
@@ -1581,7 +1624,7 @@ public final class String implements Serializable, Comparable<String>,
 
     /**
      * Copies a range of characters into a new string.
-     *
+     * 
      * @param start
      *            the offset of the first character.
      * @param end
@@ -1605,7 +1648,7 @@ public final class String implements Serializable, Comparable<String>,
 
     /**
      * Copies the characters in this string to a character array.
-     *
+     * 
      * @return a character array containing the characters of this string.
      */
     public char[] toCharArray() {
@@ -1617,7 +1660,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Converts the characters in this string to lowercase, using the default
      * Locale.
-     *
+     * 
      * @return a new string containing the lowercase characters equivalent to
      *         the characters in this string.
      */
@@ -1628,7 +1671,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Converts the characters in this string to lowercase, using the specified
      * Locale.
-     *
+     * 
      * @param locale
      *            the Locale to use.
      * @return a new string containing the lowercase characters equivalent to
@@ -1672,7 +1715,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Converts the characters in this string to uppercase, using the default
      * Locale.
-     *
+     * 
      * @return a new string containing the uppercase characters equivalent to
      *         the characters in this string.
      */
@@ -1746,7 +1789,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Converts the characters in this string to uppercase, using the specified
      * Locale.
-     *
+     * 
      * @param locale
      *            the Locale to use.
      * @return a new string containing the uppercase characters equivalent to
@@ -1811,7 +1854,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Copies this string removing white space characters from the beginning and
      * end of the string.
-     *
+     * 
      * @return a new string with characters <code><= \\u0020</code> removed from
      *         the beginning and the end.
      */
@@ -1834,7 +1877,7 @@ public final class String implements Serializable, Comparable<String>,
      * Creates a new string containing the characters in the specified character
      * array. Modifying the character array after creating the string has no
      * effect on the string.
-     *
+     * 
      * @param data
      *            the array of characters.
      * @return the new string.
@@ -1849,7 +1892,7 @@ public final class String implements Serializable, Comparable<String>,
      * Creates a new string containing the specified characters in the character
      * array. Modifying the character array after creating the string has no
      * effect on the string.
-     *
+     * 
      * @param data
      *            the array of characters.
      * @param start
@@ -1869,7 +1912,7 @@ public final class String implements Serializable, Comparable<String>,
 
     /**
      * Converts the specified character to its string representation.
-     *
+     * 
      * @param value
      *            the character.
      * @return the character converted to a string.
@@ -1887,7 +1930,7 @@ public final class String implements Serializable, Comparable<String>,
 
     /**
      * Converts the specified double to its string representation.
-     *
+     * 
      * @param value
      *            the double.
      * @return the double converted to a string.
@@ -1898,7 +1941,7 @@ public final class String implements Serializable, Comparable<String>,
 
     /**
      * Converts the specified float to its string representation.
-     *
+     * 
      * @param value
      *            the float.
      * @return the float converted to a string.
@@ -1909,7 +1952,7 @@ public final class String implements Serializable, Comparable<String>,
 
     /**
      * Converts the specified integer to its string representation.
-     *
+     * 
      * @param value
      *            the integer.
      * @return the integer converted to a string.
@@ -1920,7 +1963,7 @@ public final class String implements Serializable, Comparable<String>,
 
     /**
      * Converts the specified long to its string representation.
-     *
+     * 
      * @param value
      *            the long.
      * @return the long converted to a string.
@@ -1933,7 +1976,7 @@ public final class String implements Serializable, Comparable<String>,
      * Converts the specified object to its string representation. If the object
      * is null return the string {@code "null"}, otherwise use {@code
      * toString()} to get the string representation.
-     *
+     * 
      * @param value
      *            the object.
      * @return the object converted to a string, or the string {@code "null"}.
@@ -1946,7 +1989,7 @@ public final class String implements Serializable, Comparable<String>,
      * Converts the specified boolean to its string representation. When the
      * boolean is {@code true} return {@code "true"}, otherwise return {@code
      * "false"}.
-     *
+     * 
      * @param value
      *            the boolean.
      * @return the boolean converted to a string.
@@ -1958,7 +2001,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Returns whether the characters in the StringBuffer {@code strbuf} are the
      * same as those in this string.
-     *
+     * 
      * @param strbuf
      *            the StringBuffer to compare this string to.
      * @return {@code true} if the characters in {@code strbuf} are identical to
@@ -2008,7 +2051,7 @@ public final class String implements Serializable, Comparable<String>,
 
     /**
      * Determines whether this string matches a given regular expression.
-     *
+     * 
      * @param expr
      *            the regular expression to be matched.
      * @return {@code true} if the expression matches, otherwise {@code false}.
@@ -2026,7 +2069,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Replace any substrings within this string that match the supplied regular
      * expression {@code expr}, with the string {@code substitute}.
-     *
+     * 
      * @param expr
      *            the regular expression to match.
      * @param substitute
@@ -2045,7 +2088,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Replace the first substring within this string that matches the supplied
      * regular expression {@code expr}, with the string {@code substitute}.
-     *
+     * 
      * @param expr
      *            the regular expression to match.
      * @param substitute
@@ -2065,7 +2108,7 @@ public final class String implements Serializable, Comparable<String>,
 
     /**
      * Splits this string using the supplied regular expression {@code expr}.
-     *
+     * 
      * @param expr
      *            the regular expression used to divide the string.
      * @return an array of Strings created by separating the string along
@@ -2086,7 +2129,7 @@ public final class String implements Serializable, Comparable<String>,
      * Splits this string using the supplied regular expression {@code expr}.
      * The parameter {@code max} controls the behavior how many times the
      * pattern is applied to the string.
-     *
+     * 
      * @param expr
      *            the regular expression used to divide the string.
      * @param max
@@ -2108,7 +2151,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Has the same result as the substring function, but is present so that
      * string may implement the CharSequence interface.
-     *
+     * 
      * @param start
      *            the offset the first character.
      * @param end
@@ -2127,7 +2170,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Retrieves the Unicode code point (character) value at the specified
      * {@code index}.
-     *
+     * 
      * @param index
      *            the index to the {@code char} code unit within this string.
      * @return the Unicode code point value.
@@ -2148,7 +2191,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Retrieves the Unicode code point value that precedes the specified
      * {@code index}.
-     *
+     * 
      * @param index
      *            the index to the {@code char} code unit within this string.
      * @return the Unicode code point value.
@@ -2169,7 +2212,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Calculates the number of Unicode code points between {@code beginIndex}
      * and {@code endIndex}.
-     *
+     * 
      * @param beginIndex
      *            the inclusive beginning index of the subsequence.
      * @param endIndex
@@ -2232,7 +2275,7 @@ public final class String implements Serializable, Comparable<String>,
     /**
      * Returns a formatted string, using the supplied format and arguments,
      * using the default locale.
-     *
+     * 
      * @param format
      *            a format string.
      * @param args
index 0f9dc98..9005647 100644 (file)
@@ -279,9 +279,7 @@ public class Modifier {
      */
     @SuppressWarnings("nls")
     public static java.lang.String toString(int modifiers) {
-        StringBuffer buf;
-
-        buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
 
         if (isPublic(modifiers)) {
             buf.append("public ");
index fc3ad10..99fad3f 100644 (file)
@@ -336,7 +336,7 @@ public class ServerSocket {
      */
     @Override
     public String toString() {
-        StringBuffer result = new StringBuffer(64);
+        StringBuilder result = new StringBuilder(64);
         result.append("ServerSocket["); //$NON-NLS-1$
         if (!isBound()) {
             return result.append("unbound]").toString(); //$NON-NLS-1$
index be13eca..6ac41cd 100644 (file)
@@ -259,7 +259,7 @@ public abstract class SocketImpl implements SocketOptions {
     @SuppressWarnings("nls")
     @Override
     public String toString() {
-        return new StringBuffer(100).append("Socket[addr=").append(
+        return new StringBuilder(100).append("Socket[addr=").append(
                 getInetAddress()).append(",port=").append(port).append(
                 ",localport=").append(getLocalPort()).append("]").toString();
     }
index 25cc43f..4353e2e 100644 (file)
@@ -211,7 +211,7 @@ public final class SocketPermission extends Permission implements Serializable {
         }
         boolean parsing = true;
         String action;
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         int pos = 0, length = actions.length();
         while (parsing) {
             char c;
@@ -360,7 +360,7 @@ public final class SocketPermission extends Permission implements Serializable {
             return actionNames[SP_RESOLVE]; // If none specified return the
         }
         // implied action resolve
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         if ((actionsMask & SP_CONNECT) == SP_CONNECT) {
             sb.append(',');
             sb.append(actionNames[SP_CONNECT]);
index 7fd08a5..85c16eb 100644 (file)
@@ -106,7 +106,7 @@ public final class URI implements Comparable<URI>, Serializable {
      */
     public URI(String scheme, String ssp, String frag)
             throws URISyntaxException {
-        StringBuffer uri = new StringBuffer();
+        StringBuilder uri = new StringBuilder();
         if (scheme != null) {
             uri.append(scheme);
             uri.append(':');
@@ -166,7 +166,7 @@ public final class URI implements Comparable<URI>, Serializable {
             throw new URISyntaxException(path, Msg.getString("K0302")); //$NON-NLS-1$
         }
 
-        StringBuffer uri = new StringBuffer();
+        StringBuilder uri = new StringBuilder();
         if (scheme != null) {
             uri.append(scheme);
             uri.append(':');
@@ -270,7 +270,7 @@ public final class URI implements Comparable<URI>, Serializable {
             throw new URISyntaxException(path, Msg.getString("K0302")); //$NON-NLS-1$
         }
 
-        StringBuffer uri = new StringBuffer();
+        StringBuilder uri = new StringBuilder();
         if (scheme != null) {
             uri.append(scheme);
             uri.append(':');
@@ -994,7 +994,7 @@ public final class URI implements Comparable<URI>, Serializable {
      * converts the hex values following the '%' to lowercase
      */
     private String convertHexToLowerCase(String s) {
-        StringBuffer result = new StringBuffer(""); //$NON-NLS-1$
+        StringBuilder result = new StringBuilder(""); //$NON-NLS-1$
         if (s.indexOf('%') == -1) {
             return s;
         }
@@ -1357,7 +1357,7 @@ public final class URI implements Comparable<URI>, Serializable {
         }
 
         // put the path back together
-        StringBuffer newpath = new StringBuffer();
+        StringBuilder newpath = new StringBuilder();
         if (path.startsWith("/")) { //$NON-NLS-1$
             newpath.append('/');
         }
@@ -1548,7 +1548,7 @@ public final class URI implements Comparable<URI>, Serializable {
      */
     private void setSchemeSpecificPart() {
         // ssp = [//authority][path][?query]
-        StringBuffer ssp = new StringBuffer();
+        StringBuilder ssp = new StringBuilder();
         if (authority != null) {
             ssp.append("//" + authority); //$NON-NLS-1$
         }
@@ -1631,7 +1631,7 @@ public final class URI implements Comparable<URI>, Serializable {
     @Override
     public String toString() {
         if (string == null) {
-            StringBuffer result = new StringBuffer();
+            StringBuilder result = new StringBuilder();
             if (scheme != null) {
                 result.append(scheme);
                 result.append(':');
@@ -1670,7 +1670,7 @@ public final class URI implements Comparable<URI>, Serializable {
      * and converts escaped octets to lowercase.
      */
     private String getHashString() {
-        StringBuffer result = new StringBuffer();
+        StringBuilder result = new StringBuilder();
         if (scheme != null) {
             result.append(scheme.toLowerCase());
             result.append(':');
index 4bf95ab..d2b0044 100644 (file)
@@ -112,7 +112,7 @@ class URIEncoderDecoder {
      */
     static String quoteIllegal(String s, String legal)
             throws UnsupportedEncodingException {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         for (int i = 0; i < s.length(); i++) {
             char ch = s.charAt(i);
             if ((ch >= 'a' && ch <= 'z')
@@ -148,7 +148,7 @@ class URIEncoderDecoder {
      * @return java.lang.String the converted string
      */
     static String encodeOthers(String s) throws UnsupportedEncodingException {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         for (int i = 0; i < s.length(); i++) {
             char ch = s.charAt(i);
             if (ch <= 127) {
@@ -183,7 +183,7 @@ class URIEncoderDecoder {
      */
     static String decode(String s) throws UnsupportedEncodingException {
 
-        StringBuffer result = new StringBuffer();
+        StringBuilder result = new StringBuilder();
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         for (int i = 0; i < s.length();) {
             char c = s.charAt(i);
index dd3c9bf..6dfa385 100644 (file)
@@ -1184,9 +1184,9 @@ public class URLClassLoader extends SecureClassLoader {
             String element = tokenizer.nextToken();
             if (!element.equals("")) { //$NON-NLS-1$
                 try {
-                    URL newURL = new URL(protocol, host, port, file + element
-                            + "!/"); //$NON-NLS-1$
-                    addedURLs.add(newURL);
+                    // Take absolute path case into consideration
+                    URL url = new URL(new URL(file), element);
+                    addedURLs.add(createSearchURL(url));
                 } catch (MalformedURLException e) {
                     // Nothing is added
                 }
@@ -1196,10 +1196,6 @@ public class URLClassLoader extends SecureClassLoader {
     }
 
     Class<?> findClassImpl(String className) {
-        Class<?> loadedClass = findLoadedClass(className);
-        if (null != loadedClass) {
-            return loadedClass;
-        }
         String partialName = className.replace('.', '/');
         final String classFileName = new StringBuilder(partialName).append(".class").toString(); //$NON-NLS-1$
         String packageName = null;
index b87b11a..573a2d2 100644 (file)
@@ -758,7 +758,7 @@ public abstract class URLConnection {
      * @return the string to be parsed
      */
     private String parseTypeString(String typeString) {
-        StringBuffer typeStringBuffer = new StringBuffer(typeString);
+        StringBuilder typeStringBuffer = new StringBuilder(typeString);
         for (int i = 0; i < typeStringBuffer.length(); i++) {
             // if non-alphanumeric, replace it with '_'
             char c = typeStringBuffer.charAt(i);
index 2c21aa6..b764cc7 100644 (file)
@@ -49,7 +49,7 @@ public class URLEncoder {
      */
     @Deprecated
     public static String encode(String s) {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         for (int i = 0; i < s.length(); i++) {
             char ch = s.charAt(i);
             if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
index f039b00..54e550b 100644 (file)
@@ -305,8 +305,7 @@ public abstract class URLStreamHandler {
      * @see URL#toExternalForm()
      */
     protected String toExternalForm(URL url) {
-        StringBuffer answer = new StringBuffer(url.getProtocol().length()
-                + url.getFile().length() + 16);
+        StringBuilder answer = new StringBuilder();
         answer.append(url.getProtocol());
         answer.append(':');
         String authority = url.getAuthority();
@@ -317,8 +316,9 @@ public abstract class URLStreamHandler {
 
         String file = url.getFile();
         String ref = url.getRef();
-        // file is never null
-        answer.append(file);
+        if (file != null) {
+            answer.append(file);
+        }
         if (ref != null) {
             answer.append('#');
             answer.append(ref);
index 899affd..8f1e79f 100644 (file)
@@ -360,7 +360,10 @@ public abstract class AbstractList<E> extends AbstractCollection<E> implements
 
         @Override
         public int size() {
-            return size;
+            if (modCount == fullList.modCount) {
+                return size;
+            }
+            throw new ConcurrentModificationException();
         }
 
         void sizeChanged(boolean increment) {
index ade5d27..b8c7056 100644 (file)
@@ -81,10 +81,11 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>,
      *            the collection of elements to add.
      */
     public ArrayList(Collection<? extends E> collection) {
-        int size = collection.size();
         firstIndex = 0;
+        Object[] objects = collection.toArray();
+        int size = objects.length;
         array = newElementArray(size + (size / 10));
-        collection.toArray(array);
+        System.arraycopy(objects, 0, array, 0, size);
         lastIndex = size;
         modCount = 1;
     }
@@ -187,7 +188,12 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>,
         if (this == collection) {
             collection = (ArrayList)clone();
         }
-        int growSize = collection.size();
+        Object[] dumparray = collection.toArray();
+        int growSize = dumparray.length;
+        if (growSize == 0) {
+            return false;
+        }
+
         if (0 < location && location < size) {
             if (array.length - size < growSize) {
                 growForInsert(location, growSize);
@@ -219,15 +225,10 @@ public class ArrayList<E> extends AbstractList<E> implements List<E>,
             lastIndex += growSize;
         }
 
-        if (growSize > 0) {
-            Object[] dumparray = new Object[growSize];
-            collection.toArray(dumparray);
-            System.arraycopy(dumparray, 0, this.array, location + firstIndex,
-                    growSize);
-            modCount++;
-            return true;
-        }
-        return false;
+        System.arraycopy(dumparray, 0, this.array, location + firstIndex,
+                growSize);
+        modCount++;
+        return true;
     }
 
     /**
index d2d7c0a..4e01cbf 100644 (file)
@@ -818,7 +818,7 @@ public class BitSet implements Serializable, Cloneable {
      */
     @Override
     public String toString() {
-        StringBuffer sb = new StringBuffer(bits.length / 2);
+        StringBuilder sb = new StringBuilder(bits.length / 2);
         int bitCount = 0;
         sb.append('{');
         boolean comma = false;
index 088347d..0ac574c 100644 (file)
@@ -1322,7 +1322,7 @@ public abstract class Calendar implements Serializable, Cloneable,
     @Override
     @SuppressWarnings("nls")
     public String toString() {
-        StringBuffer result = new StringBuffer(getClass().getName() + "[time="
+        StringBuilder result = new StringBuilder(getClass().getName() + "[time="
                 + (isTimeSet ? String.valueOf(time) : "?")
                 + ",areFieldsSet="
                 + areFieldsSet
index 7bd7261..80610d3 100644 (file)
@@ -390,7 +390,7 @@ public class Date implements Serializable, Cloneable, Comparable<Date> {
         int hour = -1, minute = -1, second = -1, zoneOffset = 0, minutesOffset = 0;
         boolean zone = false;
         final int PAD = 0, LETTERS = 1, NUMBERS = 2;
-        StringBuffer buffer = new StringBuffer();
+        StringBuilder buffer = new StringBuilder();
 
         while (offset <= length) {
             char next = offset < length ? string.charAt(offset) : '\r';
index 4ec7a1b..999063d 100644 (file)
@@ -852,11 +852,11 @@ public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>,
 }
 
     static boolean areEqualKeys(Object key1, Object key2) {
-        return key1.equals(key2);
+        return (key1 == key2) || key1.equals(key2);
     }
 
     static boolean areEqualValues(Object value1, Object value2) {
-        return value1.equals(value2);
+        return (value1 == value2) || value1.equals(value2);
     }
 
 
index f1c1f74..b23364d 100644 (file)
@@ -547,10 +547,15 @@ public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>,
         while (it.hasNext()) {
             Map.Entry<K, V> entry = it.next();
             Object key = entry.getKey();
+            if (key == this) {
+                continue;
+            }
             Object value = entry.getValue();
-            int hash = (key != this ? key.hashCode() : 0)
-                    ^ (value != this ? (value != null ? value.hashCode() : 0)
-                            : 0);
+            if (value == this) {
+                continue;
+            }
+            int hash = (key != null ? key.hashCode() : 0)
+                    ^ (value != null ? value.hashCode() : 0);
             result += hash;
         }
         return result;
index 30330b5..053de1d 100644 (file)
@@ -267,7 +267,10 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements
     }
 
     private int computeElementArraySize() {
-        return (int) (((long) threshold * 10000) / loadFactor) * 2;
+        int arraySize = (int) (((long) threshold * 10000) / loadFactor) * 2;
+        // ensure arraySize is positive, the above cast from long to int type
+        // leads to overflow and negative arraySize if threshold is too big
+        return arraySize < 0 ? -arraySize : arraySize;
     }
 
     /**
@@ -748,7 +751,12 @@ public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements
     @Override
     public Object clone() {
         try {
-            return super.clone();
+            IdentityHashMap<K, V> cloneHashMap = (IdentityHashMap<K, V>) super
+                    .clone();
+            cloneHashMap.elementData = newElementArray(elementData.length);
+            System.arraycopy(elementData, 0, cloneHashMap.elementData, 0,
+                    elementData.length);
+            return cloneHashMap;
         } catch (CloneNotSupportedException e) {
             return null;
         }
index b4558aa..b1a1821 100644 (file)
@@ -564,7 +564,7 @@ public final class Locale implements Cloneable, Serializable {
      */
     public String getDisplayName(Locale locale) {
         int count = 0;
-        StringBuffer buffer = new StringBuffer();
+        StringBuilder buffer = new StringBuilder();
         if (languageCode.length() > 0) {
             buffer.append(getDisplayLanguage(locale));
             count++;
index b1fa938..79d7069 100644 (file)
@@ -198,7 +198,7 @@ public class Properties extends Hashtable<Object, Object> {
         if (out == null) {
             throw new NullPointerException();
         }
-        StringBuffer buffer = new StringBuffer(80);
+        StringBuilder buffer = new StringBuilder(80);
         Enumeration<?> keys = propertyNames();
         while (keys.hasMoreElements()) {
             String key = (String) keys.nextElement();
@@ -234,7 +234,7 @@ public class Properties extends Hashtable<Object, Object> {
         if (writer == null) {
             throw new NullPointerException();
         }
-        StringBuffer buffer = new StringBuffer(80);
+        StringBuilder buffer = new StringBuilder(80);
         Enumeration<?> keys = propertyNames();
         while (keys.hasMoreElements()) {
             String key = (String) keys.nextElement();
@@ -392,7 +392,7 @@ public class Properties extends Hashtable<Object, Object> {
                 case '\r':
                     mode = NONE;
                     firstChar = true;
-                    if (offset > 0) {
+                    if (offset > 0 || (offset == 0 && keyLength == 0)) {
                         if (keyLength == -1) {
                             keyLength = offset;
                         }
index b0bcc6b..b4878ca 100644 (file)
@@ -446,7 +446,7 @@ public abstract class TimeZone implements Serializable, Cloneable {
     }
 
     private static String formatTimeZoneName(String name, int offset) {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         int index = offset, length = name.length();
         buf.append(name.substring(0, offset));
 
index 48970be..6090031 100644 (file)
@@ -187,14 +187,10 @@ public class Timer {
 
         /**
          * Starts a new timer.
-         *
-         * @param isDaemon
+         * 
+         * @param name thread's name
+         * @param isDaemon daemon thread or not
          */
-        TimerImpl(boolean isDaemon) {
-            this.setDaemon(isDaemon);
-            this.start();
-        }
-
         TimerImpl(String name, boolean isDaemon) {
             this.setName(name);
             this.setDaemon(isDaemon);
@@ -324,72 +320,78 @@ public class Timer {
         }
 
     }
+    
+       private static final class FinalizerHelper {
+               private final TimerImpl impl;
+               
+               FinalizerHelper(TimerImpl impl) {
+                       super();
+                       this.impl = impl;
+               }
+               
+               @Override
+               protected void finalize() {
+                       synchronized (impl) {
+                               impl.finished = true;
+                               impl.notify();
+                       }
+               }
+       }
+       
+       private static long timerId;
+       
+       private synchronized static long nextId() {
+               return timerId++;
+       }
 
     /* This object will be used in synchronization purposes */
-    private TimerImpl impl;
+    private final TimerImpl impl;
 
     // Used to finalize thread
     @SuppressWarnings("unused")
-    private final Object finalizer;
-
-    /**
-     * Creates a new {@code Timer} which may be specified to be run as a daemon thread.
-     *
-     * @param isDaemon
-     *            {@code true} if the {@code Timer}'s thread should be a daemon thread.
-     */
-    public Timer(boolean isDaemon) {
-        // BEGIN android-changed
-        impl = new TimerImpl("java.util.Timer", isDaemon);
-        // END android-changed
-        finalizer = newFinalizer();
-    }
-
-    /**
-     * Creates a new non-daemon {@code Timer}.
-     */
-    public Timer() {
-        // BEGIN android-changed
-        impl = new TimerImpl("java.util.Timer", false);
-        // END android-changed
-        finalizer = newFinalizer();
-    }
+    private final FinalizerHelper finalizer;
 
     /**
      * Creates a new named {@code Timer} which may be specified to be run as a
      * daemon thread.
      *
-     * @param name
-     *            the name of the {@code Timer}.
-     * @param isDaemon
-     *            true if {@code Timer}'s thread should be a daemon thread.
+     * @param name the name of the {@code Timer}.
+     * @param isDaemon true if {@code Timer}'s thread should be a daemon thread.
+     * @throws NullPointerException is {@code name} is {@code null}
      */
     public Timer(String name, boolean isDaemon) {
-        impl = new TimerImpl(name, isDaemon);
-        finalizer = newFinalizer();
+       super();
+       if (name == null){
+               throw new NullPointerException("name is null");
+       }
+        this.impl = new TimerImpl(name, isDaemon);
+        this.finalizer = new FinalizerHelper(impl);
     }
-
+    
     /**
      * Creates a new named {@code Timer} which does not run as a daemon thread.
      *
-     * @param name
-     *            the name of the Timer.
+     * @param name the name of the Timer.
+     * @throws NullPointerException is {@code name} is {@code null}
      */
     public Timer(String name) {
-        impl = new TimerImpl(name, false);
-        finalizer = newFinalizer();
+        this(name, false);
+    }
+    
+    /**
+     * Creates a new {@code Timer} which may be specified to be run as a daemon thread.
+     *
+     * @param isDaemon {@code true} if the {@code Timer}'s thread should be a daemon thread.
+     */
+    public Timer(boolean isDaemon) {
+        this("Timer-" + Timer.nextId(), isDaemon);
     }
 
-    private Object newFinalizer() {
-        return new Object() { // $NON-LOCK-1$
-            @Override
-            protected void finalize() {
-                synchronized (impl) {
-                    impl.finished = true;
-                    impl.notify();
-                }
-            }
-        };
+    /**
+     * Creates a new non-daemon {@code Timer}.
+     */
+    public Timer() {
+        this(false);
     }
 
     /**
@@ -443,7 +445,7 @@ public class Timer {
      * @param task
      *            the task to schedule.
      * @param delay
-     *            amount of time before execution.
+     *            amount of time in milliseconds before execution.
      * @throws IllegalArgumentException
      *                if {@code delay < 0}.
      * @throws IllegalStateException
@@ -463,9 +465,9 @@ public class Timer {
      * @param task
      *            the task to schedule.
      * @param delay
-     *            amount of time before first execution.
+     *            amount of time in milliseconds before first execution.
      * @param period
-     *            amount of time between subsequent executions.
+     *            amount of time in milliseconds between subsequent executions.
      * @throws IllegalArgumentException
      *                if {@code delay < 0} or {@code period < 0}.
      * @throws IllegalStateException
@@ -488,7 +490,7 @@ public class Timer {
      * @param when
      *            time of first execution.
      * @param period
-     *            amount of time between subsequent executions.
+     *            amount of time in milliseconds between subsequent executions.
      * @throws IllegalArgumentException
      *                if {@code when.getTime() < 0} or {@code period < 0}.
      * @throws IllegalStateException
@@ -510,9 +512,9 @@ public class Timer {
      * @param task
      *            the task to schedule.
      * @param delay
-     *            amount of time before first execution.
+     *            amount of time in milliseconds before first execution.
      * @param period
-     *            amount of time between subsequent executions.
+     *            amount of time in milliseconds between subsequent executions.
      * @throws IllegalArgumentException
      *                if {@code delay < 0} or {@code period < 0}.
      * @throws IllegalStateException
@@ -535,7 +537,7 @@ public class Timer {
      * @param when
      *            time of first execution.
      * @param period
-     *            amount of time between subsequent executions.
+     *            amount of time in milliseconds between subsequent executions.
      * @throws IllegalArgumentException
      *                if {@code when.getTime() < 0} or {@code period < 0}.
      * @throws IllegalStateException
index 8634c13..6a4060a 100644 (file)
@@ -1009,7 +1009,7 @@ public class Vector<E> extends AbstractList<E> implements List<E>,
             return "[]"; //$NON-NLS-1$
         }
         int length = elementCount - 1;
-        StringBuffer buffer = new StringBuffer(elementCount * 16);
+        StringBuilder buffer = new StringBuilder(elementCount * 16);
         buffer.append('[');
         for (int i = 0; i < length; i++) {
             if (elementData[i] == this) {
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/io/FileCanonPathCache.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/io/FileCanonPathCache.java
new file mode 100644 (file)
index 0000000..e3ea7b5
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.luni.internal.io;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+
+/**
+ * A simple cache implementation for file's canonical path. The cache has fixed
+ * size <code> CACHE_SIZE </code> and cached elements would be expired. If
+ * <code>put<code> method is invoked when cache is full, the oldest element will be removed.
+ *
+ */
+public class FileCanonPathCache {
+
+    static private class CacheElement {
+        String canonicalPath;
+
+        long timestamp;
+
+        public CacheElement(String path) {
+            this.canonicalPath = path;
+            this.timestamp = System.currentTimeMillis();
+        }
+    }
+
+    /**
+     * Max elemnts could be hold in the cache.
+     */
+    public static final int CACHE_SIZE = 256;
+
+    private static HashMap<String, CacheElement> cache = new HashMap<String, CacheElement>(
+            CACHE_SIZE);
+
+    /**
+     * FIFO queue for tracking age of elements.
+     */
+    private static LinkedList<String> list = new LinkedList<String>();
+
+    private static Object lock = new Object();
+
+    /**
+     * Expired time.
+     */
+    private static long timeout = 600000;
+
+    /**
+     * Retrieve element from cache.
+     * 
+     * @param path
+     *            absolute path.
+     * @return canonical path of <code>path</code> if it's in cache.
+     * 
+     */
+    public static String get(String path) {
+        CacheElement element = null;
+        synchronized (lock) {
+            element = cache.get(path);
+        }
+
+        if (element == null) {
+            return null;
+        }
+
+        long time = System.currentTimeMillis();
+        if (time - element.timestamp > timeout) {
+            // remove all elements older than this one
+            synchronized (lock) {
+                if (cache.get(path) != null) {
+                    String oldest = null;
+                    do {
+                        oldest = list.removeFirst();
+                        cache.remove(path);
+                    } while (!path.equals(oldest));
+                }
+            }
+            return null;
+        }
+
+        return element.canonicalPath;
+    }
+
+    /**
+     * Put element to cache.
+     * 
+     * @param path
+     *            absolute path.
+     * @param canonicalPath
+     *            the canonical path of <code>path</code>.
+     */
+    public static void put(String path, String canonicalPath) {
+        CacheElement element = new CacheElement(canonicalPath);
+        synchronized (lock) {
+            if (cache.size() >= CACHE_SIZE) {
+                // cache is full
+                String oldest = list.removeFirst();
+                cache.remove(oldest);
+            }
+            cache.put(path, element);
+            list.addLast(path);
+        }
+    }
+
+    /**
+     * Remove all elements from cache.
+     */
+    public static void clear() {
+        synchronized (lock) {
+            cache.clear();
+            list.clear();
+        }
+    }
+
+    public static long getTimeout() {
+        return timeout;
+    }
+
+    public static void setTimeout(long timeout) {
+        FileCanonPathCache.timeout = timeout;
+    }
+}
index 016d5a7..3c361bf 100644 (file)
@@ -399,7 +399,7 @@ public class FtpURLConnection extends URLConnection {
      * Read a line of text and return it for possible parsing
      */
     private String readLine() throws IOException {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         int c;
         while ((c = ctrlInput.read()) != '\n') {
             sb.append((char) c);
index 505c6b2..104a981 100644 (file)
@@ -1174,7 +1174,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
      */
     String readln() throws IOException {
         boolean lastCr = false;
-        StringBuffer result = new StringBuffer(80);
+        StringBuilder result = new StringBuilder(80);
         int c = is.read();
         if (c < 0) {
             return null;
index d299913..4db9910 100644 (file)
@@ -99,7 +99,7 @@ public class Handler extends URLStreamHandler {
      */
     @Override
     protected String toExternalForm(URL url) {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append("jar:"); //$NON-NLS-1$
         sb.append(url.getFile());
         String ref = url.getRef();
index 56c1f3c..34e7d07 100644 (file)
@@ -138,9 +138,9 @@ public class JarURLConnection extends java.net.JarURLConnection {
     JarFile openJarFile() throws IOException {
         JarFile jar = null;
         if (jarFileURL.getProtocol().equals("file")) { //$NON-NLS-1$
-            jar = new JarFile(new File(Util.decode(jarFileURL.getFile(), false)),
-                        true, ZipFile.OPEN_READ);
-        } else{
+            jar = new JarFile(new File(Util.decode(jarFileURL.getFile(), false,
+                    "UTF-8")), true, ZipFile.OPEN_READ);
+        } else {
             final InputStream is = jarFileURL.openConnection().getInputStream();
             try {
                 jar = AccessController
index b765c7d..6e8028a 100644 (file)
@@ -30,10 +30,22 @@ import java.io.IOException;
  */
 public interface IMemorySystem {
 
+    /**
+     * The constant representing read-only access to data in a memory map
+     * request.
+     */
     public final int MMAP_READ_ONLY = 1;
 
+    /**
+     * The constant representing read-write access to data in a memory map
+     * request.
+     */
     public final int MMAP_READ_WRITE = 2;
 
+    /**
+     * The constant representing copy-on-write access to data in a memory map
+     * request.
+     */
     public final int MMAP_WRITE_COPY = 4;
 
     /**
@@ -243,7 +255,17 @@ public interface IMemorySystem {
             throws NullPointerException, IndexOutOfBoundsException;
     // END android-added
 
-    // Primitive get & set methods
+    /**
+     * Returns the value of a single byte at the given address.
+     * <p>
+     * The behavior is unspecified if <code>address</code> is not in the range
+     * that was previously allocated using <code>malloc()</code>.
+     * </p>
+     *
+     * @param address
+     *            the address at which to get the byte value.
+     * @return the value of the byte.
+     */
     public byte getByte(int address);
 
     /**
@@ -275,6 +297,21 @@ public interface IMemorySystem {
      */
     public short getShort(int address);
 
+    /**
+     * Gets the value of the signed two-byte integer stored in the given byte
+     * order at the given address.
+     * <p>
+     * The behavior is unspecified if <code>(address ... address + 2)</code> is
+     * not wholly within the range that was previously allocated using
+     * <code>malloc()</code>.
+     * </p>
+     *
+     * @param address
+     *            the platform address of the start of the two-byte value.
+     * @param endianness
+     *            the required interpretation of the short endianness.
+     * @return the value of the two-byte integer as a Java <code>short</code>.
+     */
     public short getShort(int address, Endianness endianness);
 
     /**
@@ -474,17 +511,25 @@ public interface IMemorySystem {
     public void setAddress(int address, int value);
 
     /**
-     * TODO: JavaDoc
-     * 
+     * Map file content into memory.
+     *
      * @param fileDescriptor
+     *            a handle to the file that is to be memory mapped.
      * @param alignment
+     *            the offset in the file where the mapping should begin.
      * @param size
+     *            the number of bytes that are requested to map.
      * @param mapMode
-     * @return
+     *            the desired access mode as defined by one of the constants
+     *            {@link IMemorySystem#MMAP_READ_ONLY},
+     *            {@link IMemorySystem#MMAP_READ_WRITE},
+     *            {@link IMemorySystem#MMAP_WRITE_COPY}
+     * @return the start address of the mapped memory area.
      * @throws IOException
+     *             if an exception occurs mapping the file into memory.
      */
-    public int mmap(int fileDescriptor, long alignment, long size,
-            int mapMode) throws IOException;
+    public int mmap(int fileDescriptor, long alignment, long size,  int mapMode)
+            throws IOException;
 
     /**
      * TODO: JavaDoc
index 20cf7cb..08bdac6 100644 (file)
@@ -24,6 +24,7 @@ package org.apache.harmony.luni.platform;
 import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 
 /**
  * This is the portable implementation of the file system interface.
@@ -239,7 +240,14 @@ class OSFileSystem implements IFileSystem {
         }
         int handler = openImpl(fileName, mode);
         if (handler < 0) {
-            throw new FileNotFoundException(new String(fileName));
+            try {
+                throw new FileNotFoundException(new String(fileName, "UTF-8"));
+            } catch (java.io.UnsupportedEncodingException e) {
+                // UTF-8 should always be supported, so throw an assertion
+                FileNotFoundException fnfe = new FileNotFoundException(new String(fileName));
+                e.initCause(fnfe);
+                throw new AssertionError(e);
+            }
         }
         return handler;
     }
index 0c9ac8a..1ec6240 100644 (file)
@@ -546,8 +546,8 @@ final class OSNetworkSystem implements INetworkSystem {
      *            all sockets interested in write and connect
      * @param timeout
      *            timeout in milliseconds
-     * @returns each element describes the corresponding state of the descriptor
-     *          in the read and write arrays.
+     * @return each element describes the corresponding state of the descriptor
+     *         in the read and write arrays.
      * @throws SocketException
      */
     public int[] select(FileDescriptor[] readFDs, FileDescriptor[] writeFDs,
index c740ae9..280a8f5 100644 (file)
@@ -325,3 +325,4 @@ KA026=JAR entry {0} not found in {1}
 KA027=Inputstream of the JarURLConnection has been closed
 KA028=Cannot set protocol version when stream in use
 KA029=Can't find resource for bundle {0}, key {1}
+KA030=Write end dead
index 642d309..8734039 100644 (file)
@@ -24,94 +24,94 @@ package org.apache.harmony.luni.util;
  */
 public final class FloatingPointParser {
 
-    private static final class StringExponentPair {
-        String s;
-
-        int e;
-
-        boolean negative;
-
-        StringExponentPair(String s, int e, boolean negative) {
-            this.s = s;
-            this.e = e;
-            this.negative = negative;
-        }
-    }
-
-    /**
-     * Takes a String and an integer exponent. The String should hold a positive
-     * integer value (or zero). The exponent will be used to calculate the
-     * floating point number by taking the positive integer the String
-     * represents and multiplying by 10 raised to the power of the of the
-     * exponent. Returns the closest double value to the real number
-     * 
-     * @param s
-     *            the String that will be parsed to a floating point
-     * @param e
-     *            an int represent the 10 to part
-     * @return the double closest to the real number
-     * 
-     * @exception NumberFormatException
-     *                if the String doesn't represent a positive integer value
-     */
-    private static native double parseDblImpl(String s, int e);
-
-    /**
-     * Takes a String and an integer exponent. The String should hold a positive
-     * integer value (or zero). The exponent will be used to calculate the
-     * floating point number by taking the positive integer the String
-     * represents and multiplying by 10 raised to the power of the of the
-     * exponent. Returns the closest float value to the real number
-     * 
-     * @param s
-     *            the String that will be parsed to a floating point
-     * @param e
-     *            an int represent the 10 to part
-     * @return the float closest to the real number
-     * 
-     * @exception NumberFormatException
-     *                if the String doesn't represent a positive integer value
-     */
-    private static native float parseFltImpl(String s, int e);
-
-    /**
-     * Takes a String and does some initial parsing. Should return a
-     * StringExponentPair containing a String with no leading or trailing white
-     * space and trailing zeroes eliminated. The exponent of the
-     * StringExponentPair will be used to calculate the floating point number by
-     * taking the positive integer the String represents and multiplying by 10
-     * raised to the power of the of the exponent.
-     * 
-     * @param s
-     *            the String that will be parsed to a floating point
-     * @param length
-     *            the length of s
-     * @return a StringExponentPair with necessary values
-     * 
-     * @exception NumberFormatException
-     *                if the String doesn't pass basic tests
-     */
-    private static StringExponentPair initialParse(String s, int length) {
-        boolean negative = false;
-        char c;
-        int start, end, decimal;
-        int e = 0;
-
-        start = 0;
-        if (length == 0)
-            throw new NumberFormatException(s);
-
-        c = s.charAt(length - 1);
-        if (c == 'D' || c == 'd' || c == 'F' || c == 'f') {
-            length--;
-            if (length == 0)
-                throw new NumberFormatException(s);
-        }
-
-        end = Math.max(s.indexOf('E'), s.indexOf('e'));
-        if (end > -1) {
-            if (end + 1 == length)
-                throw new NumberFormatException(s);
+       private static final class StringExponentPair {
+               String s;
+
+               int e;
+
+               boolean negative;
+
+               StringExponentPair(String s, int e, boolean negative) {
+                       this.s = s;
+                       this.e = e;
+                       this.negative = negative;
+               }
+       }
+
+       /**
+        * Takes a String and an integer exponent. The String should hold a positive
+        * integer value (or zero). The exponent will be used to calculate the
+        * floating point number by taking the positive integer the String
+        * represents and multiplying by 10 raised to the power of the of the
+        * exponent. Returns the closest double value to the real number
+        
+        * @param s
+        *            the String that will be parsed to a floating point
+        * @param e
+        *            an int represent the 10 to part
+        * @return the double closest to the real number
+        
+        * @exception NumberFormatException
+        *                if the String doesn't represent a positive integer value
+        */
+       private static native double parseDblImpl(String s, int e);
+
+       /**
+        * Takes a String and an integer exponent. The String should hold a positive
+        * integer value (or zero). The exponent will be used to calculate the
+        * floating point number by taking the positive integer the String
+        * represents and multiplying by 10 raised to the power of the of the
+        * exponent. Returns the closest float value to the real number
+        
+        * @param s
+        *            the String that will be parsed to a floating point
+        * @param e
+        *            an int represent the 10 to part
+        * @return the float closest to the real number
+        
+        * @exception NumberFormatException
+        *                if the String doesn't represent a positive integer value
+        */
+       private static native float parseFltImpl(String s, int e);
+
+       /**
+        * Takes a String and does some initial parsing. Should return a
+        * StringExponentPair containing a String with no leading or trailing white
+        * space and trailing zeroes eliminated. The exponent of the
+        * StringExponentPair will be used to calculate the floating point number by
+        * taking the positive integer the String represents and multiplying by 10
+        * raised to the power of the of the exponent.
+        
+        * @param s
+        *            the String that will be parsed to a floating point
+        * @param length
+        *            the length of s
+        * @return a StringExponentPair with necessary values
+        
+        * @exception NumberFormatException
+        *                if the String doesn't pass basic tests
+        */
+       private static StringExponentPair initialParse(String s, int length) {
+               boolean negative = false;
+               char c;
+               int start, end, decimal;
+               int e = 0;
+
+               start = 0;
+               if (length == 0)
+                       throw new NumberFormatException(s);
+
+               c = s.charAt(length - 1);
+               if (c == 'D' || c == 'd' || c == 'F' || c == 'f') {
+                       length--;
+                       if (length == 0)
+                               throw new NumberFormatException(s);
+               }
+
+               end = Math.max(s.indexOf('E'), s.indexOf('e'));
+               if (end > -1) {
+                       if (end + 1 == length)
+                               throw new NumberFormatException(s);
 
                         int exponent_offset = end + 1;
                         if (s.charAt(exponent_offset) == '+') {
@@ -120,197 +120,208 @@ public final class FloatingPointParser {
                                 }
                                 exponent_offset++; // skip the plus sign
                         }
-            try {
-                e = Integer.parseInt(s.substring(exponent_offset,
+                       try {
+                               e = Integer.parseInt(s.substring(exponent_offset,
                                                                  length));
                         } catch (NumberFormatException ex) {
                                 // ex contains the exponent substring
                                 // only so throw a new exception with
                                 // the correct string
-                throw new NumberFormatException(s);
+                               throw new NumberFormatException(s);
                         }                            
                                     
-        } else {
-            end = length;
-        }
-        if (length == 0)
-            throw new NumberFormatException(s);
-
-        c = s.charAt(start);
-        if (c == '-') {
-            ++start;
-            --length;
-            negative = true;
-        } else if (c == '+') {
-            ++start;
-            --length;
-        }
-        if (length == 0)
-            throw new NumberFormatException(s);
-
-        decimal = s.indexOf('.');
-        if (decimal > -1) {
-            e -= end - decimal - 1;
-            s = s.substring(start, decimal) + s.substring(decimal + 1, end);
-        } else {
-            s = s.substring(start, end);
-        }
-
-        if ((length = s.length()) == 0)
-            throw new NumberFormatException();
-
-        end = length;
-        while (end > 1 && s.charAt(end - 1) == '0')
-            --end;
-
-        start = 0;
-        while (start < end - 1 && s.charAt(start) == '0')
-            start++;
-
-        if (end != length || start != 0) {
-            e += length - end;
-            s = s.substring(start, end);
+               } else {
+                       end = length;
+               }
+               if (length == 0)
+                       throw new NumberFormatException(s);
+
+               c = s.charAt(start);
+               if (c == '-') {
+                       ++start;
+                       --length;
+                       negative = true;
+               } else if (c == '+') {
+                       ++start;
+                       --length;
+               }
+               if (length == 0)
+                       throw new NumberFormatException(s);
+
+               decimal = s.indexOf('.');
+               if (decimal > -1) {
+                       e -= end - decimal - 1;
+                       s = s.substring(start, decimal) + s.substring(decimal + 1, end);
+               } else {
+                       s = s.substring(start, end);
+               }
+
+               if ((length = s.length()) == 0)
+                       throw new NumberFormatException();
+
+               end = length;
+               while (end > 1 && s.charAt(end - 1) == '0')
+                       --end;
+
+               start = 0;
+               while (start < end - 1 && s.charAt(start) == '0')
+                       start++;
+
+               if (end != length || start != 0) {
+                       e += length - end;
+                       s = s.substring(start, end);
+               }
+
+        // Trim the length of very small numbers, natives can only handle down
+        // to E-309
+        final int APPROX_MIN_MAGNITUDE = -359;
+        final int MAX_DIGITS = 52;
+        length = s.length();
+        if (length > MAX_DIGITS && e < APPROX_MIN_MAGNITUDE) {
+            int d = Math.min(APPROX_MIN_MAGNITUDE - e, length - 1);
+            s = s.substring(0, length - d);
+            e += d;
         }
 
-        return new StringExponentPair(s, e, negative);
-    }
-
-    /*
-     * Assumes the string is trimmed.
-     */
-    private static double parseDblName(String namedDouble, int length) {
-        // Valid strings are only +Nan, NaN, -Nan, +Infinity, Infinity,
-        // -Infinity.
-        if ((length != 3) && (length != 4) && (length != 8) && (length != 9)) {
-            throw new NumberFormatException();
-        }
-
-        boolean negative = false;
-        int cmpstart = 0;
-        switch (namedDouble.charAt(0)) {
-        case '-':
-            negative = true; // fall through
-        case '+':
-            cmpstart = 1;
-        default:
-        }
-
-        if (namedDouble.regionMatches(false, cmpstart, "Infinity", 0, 8)) {
-            return negative ? Double.NEGATIVE_INFINITY
-                    : Float.POSITIVE_INFINITY;
-        }
-
-        if (namedDouble.regionMatches(false, cmpstart, "NaN", 0, 3)) {
-            return Double.NaN;
-        }
-
-        throw new NumberFormatException();
-    }
-
-    /*
-     * Assumes the string is trimmed.
-     */
-    private static float parseFltName(String namedFloat, int length) {
-        // Valid strings are only +Nan, NaN, -Nan, +Infinity, Infinity,
-        // -Infinity.
-        if ((length != 3) && (length != 4) && (length != 8) && (length != 9)) {
-            throw new NumberFormatException();
-        }
-
-        boolean negative = false;
-        int cmpstart = 0;
-        switch (namedFloat.charAt(0)) {
-        case '-':
-            negative = true; // fall through
-        case '+':
-            cmpstart = 1;
-        default:
-        }
-
-        if (namedFloat.regionMatches(false, cmpstart, "Infinity", 0, 8)) {
-            return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
-        }
-
-        if (namedFloat.regionMatches(false, cmpstart, "NaN", 0, 3)) {
-            return Float.NaN;
-        }
-
-        throw new NumberFormatException();
-    }
-
-    /**
-     * Returns the closest double value to the real number in the string.
-     * 
-     * @param s
-     *            the String that will be parsed to a floating point
-     * @return the double closest to the real number
-     * 
-     * @exception NumberFormatException
-     *                if the String doesn't represent a double
-     */
-    public static double parseDouble(String s) {
-        s = s.trim();
-        int length = s.length();
-
-        if (length == 0) {
-            throw new NumberFormatException(s);
-        }
-
-        // See if this could be a named double
-        char last = s.charAt(length - 1);
-        if ((last == 'y') || (last == 'N')) {
-            return parseDblName(s, length);
-        }
+               return new StringExponentPair(s, e, negative);
+       }
+
+       /*
+        * Assumes the string is trimmed.
+        */
+       private static double parseDblName(String namedDouble, int length) {
+               // Valid strings are only +Nan, NaN, -Nan, +Infinity, Infinity,
+               // -Infinity.
+               if ((length != 3) && (length != 4) && (length != 8) && (length != 9)) {
+                       throw new NumberFormatException();
+               }
+
+               boolean negative = false;
+               int cmpstart = 0;
+               switch (namedDouble.charAt(0)) {
+               case '-':
+                       negative = true; // fall through
+               case '+':
+                       cmpstart = 1;
+               default:
+               }
+
+               if (namedDouble.regionMatches(false, cmpstart, "Infinity", 0, 8)) {
+                       return negative ? Double.NEGATIVE_INFINITY
+                                       : Float.POSITIVE_INFINITY;
+               }
+
+               if (namedDouble.regionMatches(false, cmpstart, "NaN", 0, 3)) {
+                       return Double.NaN;
+               }
+
+               throw new NumberFormatException();
+       }
+
+       /*
+        * Assumes the string is trimmed.
+        */
+       private static float parseFltName(String namedFloat, int length) {
+               // Valid strings are only +Nan, NaN, -Nan, +Infinity, Infinity,
+               // -Infinity.
+               if ((length != 3) && (length != 4) && (length != 8) && (length != 9)) {
+                       throw new NumberFormatException();
+               }
+
+               boolean negative = false;
+               int cmpstart = 0;
+               switch (namedFloat.charAt(0)) {
+               case '-':
+                       negative = true; // fall through
+               case '+':
+                       cmpstart = 1;
+               default:
+               }
+
+               if (namedFloat.regionMatches(false, cmpstart, "Infinity", 0, 8)) {
+                       return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
+               }
+
+               if (namedFloat.regionMatches(false, cmpstart, "NaN", 0, 3)) {
+                       return Float.NaN;
+               }
+
+               throw new NumberFormatException();
+       }
+
+       /**
+        * Returns the closest double value to the real number in the string.
+        
+        * @param s
+        *            the String that will be parsed to a floating point
+        * @return the double closest to the real number
+        
+        * @exception NumberFormatException
+        *                if the String doesn't represent a double
+        */
+       public static double parseDouble(String s) {
+               s = s.trim();
+               int length = s.length();
+
+               if (length == 0) {
+                       throw new NumberFormatException(s);
+               }
+
+               // See if this could be a named double
+               char last = s.charAt(length - 1);
+               if ((last == 'y') || (last == 'N')) {
+                       return parseDblName(s, length);
+               }
         
         // See if it could be a hexadecimal representation
         if (s.toLowerCase().indexOf("0x") != -1) { //$NON-NLS-1$
             return HexStringParser.parseDouble(s);
         }
         
-        StringExponentPair info = initialParse(s, length);
-
-        double result = parseDblImpl(info.s, info.e);
-        if (info.negative)
-            result = -result;
-
-        return result;
-    }
-
-    /**
-     * Returns the closest float value to the real number in the string.
-     * 
-     * @param s
-     *            the String that will be parsed to a floating point
-     * @return the float closest to the real number
-     * 
-     * @exception NumberFormatException
-     *                if the String doesn't represent a float
-     */
-    public static float parseFloat(String s) {
-        s = s.trim();
-        int length = s.length();
-
-        if (length == 0) {
-            throw new NumberFormatException(s);
-        }
-
-        // See if this could be a named float
-        char last = s.charAt(length - 1);
-        if ((last == 'y') || (last == 'N')) {
-            return parseFltName(s, length);
-        }
+               StringExponentPair info = initialParse(s, length);
+
+               double result = parseDblImpl(info.s, info.e);
+               if (info.negative)
+                       result = -result;
+
+               return result;
+       }
+
+       /**
+        * Returns the closest float value to the real number in the string.
+        
+        * @param s
+        *            the String that will be parsed to a floating point
+        * @return the float closest to the real number
+        
+        * @exception NumberFormatException
+        *                if the String doesn't represent a float
+        */
+       public static float parseFloat(String s) {
+               s = s.trim();
+               int length = s.length();
+
+               if (length == 0) {
+                       throw new NumberFormatException(s);
+               }
+
+               // See if this could be a named float
+               char last = s.charAt(length - 1);
+               if ((last == 'y') || (last == 'N')) {
+                       return parseFltName(s, length);
+               }
         
         // See if it could be a hexadecimal representation
         if (s.toLowerCase().indexOf("0x") != -1) { //$NON-NLS-1$
             return HexStringParser.parseFloat(s);
         }
         
-        StringExponentPair info = initialParse(s, length);
+               StringExponentPair info = initialParse(s, length);
 
-        float result = parseFltImpl(info.s, info.e);
-        if (info.negative)
-            result = -result;
+               float result = parseFltImpl(info.s, info.e);
+               if (info.negative)
+                       result = -result;
 
-        return result;
-    }
+               return result;
+       }
 }
index 0688e7d..e4515ae 100644 (file)
@@ -20,33 +20,34 @@ package org.apache.harmony.luni.util;
 
 import java.io.ByteArrayOutputStream;
 import java.io.UTFDataFormatException;
+import java.io.UnsupportedEncodingException;
 import java.util.Calendar;
 import java.util.TimeZone;
 
 public final class Util {
 
-    private static String[] WEEKDAYS = new String[] { "", "Sunday", "Monday",
-            "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
+       private static String[] WEEKDAYS = new String[] { "", "Sunday", "Monday",
+                       "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
 
-    private static String[] MONTHS = new String[] { "January", "February",
-            "March", "April", "May", "June", "July", "August", "September",
-            "October", "November", "December" };
+       private static String[] MONTHS = new String[] { "January", "February",
+                       "March", "April", "May", "June", "July", "August", "September",
+                       "October", "November", "December" };
 
-    private static final String defaultEncoding;
+       private static final String defaultEncoding;
 
-    static {
+       static {
         // BEGIN android-changed
         String encoding = System.getProperty("file.encoding");
         // END android-changed
-        if (encoding != null) {
-            try {
-                "".getBytes(encoding);
+               if (encoding != null) {
+                       try {
+                               "".getBytes(encoding);
             } catch (Throwable t) {
                 encoding = null;
-            }
-        }
+                       }
+               }
         defaultEncoding = encoding;
-    }
+       }
 
     /**
      * Get bytes from String using default encoding; default encoding can
@@ -55,15 +56,15 @@ public final class Util {
      * @return byte array
      */
     public static byte[] getBytes(String name) {
-        if (defaultEncoding != null) {
-            try {
-                return name.getBytes(defaultEncoding);
-            } catch (java.io.UnsupportedEncodingException e) {
-            }
-        }
+               if (defaultEncoding != null) {
+                       try {
+                               return name.getBytes(defaultEncoding);
+                       } catch (java.io.UnsupportedEncodingException e) {
+                       }
+               }      
         return name.getBytes();
-    }
-
+       }
+    
     /**
      * Get bytes from String with UTF8 encoding
      * @param name
@@ -78,29 +79,29 @@ public final class Util {
         }
     }
 
-    public static String toString(byte[] bytes) {
-        if (defaultEncoding != null) {
-            try {
-                return new String(bytes, 0, bytes.length, defaultEncoding);
-            } catch (java.io.UnsupportedEncodingException e) {
-            }
-        }
-        return new String(bytes, 0, bytes.length);
-    }
+       public static String toString(byte[] bytes) {
+               if (defaultEncoding != null) {
+                       try {
+                               return new String(bytes, 0, bytes.length, defaultEncoding);
+                       } catch (java.io.UnsupportedEncodingException e) {
+                       }
+               }
+               return new String(bytes, 0, bytes.length);
+       }
 
     public static String toUTF8String(byte[] bytes) {
         return toUTF8String(bytes, 0, bytes.length);
-    }
-
-    public static String toString(byte[] bytes, int offset, int length) {
-        if (defaultEncoding != null) {
-            try {
-                return new String(bytes, offset, length, defaultEncoding);
-            } catch (java.io.UnsupportedEncodingException e) {
-            }
-        }
-        return new String(bytes, offset, length);
-    }
+    }    
+    
+       public static String toString(byte[] bytes, int offset, int length) {
+               if (defaultEncoding != null) {
+                       try {
+                               return new String(bytes, offset, length, defaultEncoding);
+                       } catch (java.io.UnsupportedEncodingException e) {
+                       }
+               }
+               return new String(bytes, offset, length);
+       }
 
     public static String toUTF8String(byte[] bytes, int offset, int length) {
         try {
@@ -109,174 +110,189 @@ public final class Util {
             return toString(bytes, offset, length);
         }
     }
+    
+       /**
+        * Answers the millisecond value of the date and time parsed from the
+        * specified String. Many date/time formats are recognized
+        * 
+        * @param string
+        *            the String to parse
+        * @return the millisecond value parsed from the String
+        */
+       public static long parseDate(String string) {
+               int offset = 0, length = string.length(), state = 0;
+               int year = -1, month = -1, date = -1;
+               int hour = -1, minute = -1, second = -1;
+               final int PAD = 0, LETTERS = 1, NUMBERS = 2;
+               StringBuilder buffer = new StringBuilder();
 
-    /**
-     * Returns the millisecond value of the date and time parsed from the
-     * specified String. Many date/time formats are recognized
-     *
-     * @param string
-     *            the String to parse
-     * @return the millisecond value parsed from the String
-     */
-    public static long parseDate(String string) {
-        int offset = 0, length = string.length(), state = 0;
-        int year = -1, month = -1, date = -1;
-        int hour = -1, minute = -1, second = -1;
-        final int PAD = 0, LETTERS = 1, NUMBERS = 2;
-        StringBuffer buffer = new StringBuffer();
-
-        while (offset <= length) {
-            char next = offset < length ? string.charAt(offset) : '\r';
-            offset++;
+               while (offset <= length) {
+                       char next = offset < length ? string.charAt(offset) : '\r';
+                       offset++;
 
-            int nextState;
-            if ((next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))
-                nextState = LETTERS;
-            else if (next >= '0' && next <= '9')
-                nextState = NUMBERS;
-            else if (" ,-:\r\t".indexOf(next) == -1)
-                throw new IllegalArgumentException();
-            else
-                nextState = PAD;
+                       int nextState;
+                       if ((next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))
+                               nextState = LETTERS;
+                       else if (next >= '0' && next <= '9')
+                               nextState = NUMBERS;
+                       else if (" ,-:\r\t".indexOf(next) == -1)
+                               throw new IllegalArgumentException();
+                       else
+                               nextState = PAD;
 
-            if (state == NUMBERS && nextState != NUMBERS) {
-                int digit = Integer.parseInt(buffer.toString());
-                buffer.setLength(0);
-                if (digit >= 70) {
-                    if (year != -1
-                            || (next != ' ' && next != ',' && next != '\r'))
-                        throw new IllegalArgumentException();
-                    year = digit;
-                } else if (next == ':') {
-                    if (hour == -1)
-                        hour = digit;
-                    else if (minute == -1)
-                        minute = digit;
-                    else
-                        throw new IllegalArgumentException();
-                } else if (next == ' ' || next == ',' || next == '-'
-                        || next == '\r') {
-                    if (hour != -1 && minute == -1)
-                        minute = digit;
-                    else if (minute != -1 && second == -1)
-                        second = digit;
-                    else if (date == -1)
-                        date = digit;
-                    else if (year == -1)
-                        year = digit;
-                    else
-                        throw new IllegalArgumentException();
-                } else if (year == -1 && month != -1 && date != -1)
-                    year = digit;
-                else
-                    throw new IllegalArgumentException();
-            } else if (state == LETTERS && nextState != LETTERS) {
-                String text = buffer.toString().toUpperCase();
-                buffer.setLength(0);
-                if (text.length() < 3)
-                    throw new IllegalArgumentException();
-                if (parse(text, WEEKDAYS) != -1) {
-                } else if (month == -1 && (month = parse(text, MONTHS)) != -1) {
-                } else if (text.equals("GMT")) {
-                } else
-                    throw new IllegalArgumentException();
-            }
+                       if (state == NUMBERS && nextState != NUMBERS) {
+                               int digit = Integer.parseInt(buffer.toString());
+                               buffer.setLength(0);
+                               if (digit >= 70) {
+                                       if (year != -1
+                                                       || (next != ' ' && next != ',' && next != '\r'))
+                                               throw new IllegalArgumentException();
+                                       year = digit;
+                               } else if (next == ':') {
+                                       if (hour == -1)
+                                               hour = digit;
+                                       else if (minute == -1)
+                                               minute = digit;
+                                       else
+                                               throw new IllegalArgumentException();
+                               } else if (next == ' ' || next == ',' || next == '-'
+                                               || next == '\r') {
+                                       if (hour != -1 && minute == -1)
+                                               minute = digit;
+                                       else if (minute != -1 && second == -1)
+                                               second = digit;
+                                       else if (date == -1)
+                                               date = digit;
+                                       else if (year == -1)
+                                               year = digit;
+                                       else
+                                               throw new IllegalArgumentException();
+                               } else if (year == -1 && month != -1 && date != -1)
+                                       year = digit;
+                               else
+                                       throw new IllegalArgumentException();
+                       } else if (state == LETTERS && nextState != LETTERS) {
+                               String text = buffer.toString().toUpperCase();
+                               buffer.setLength(0);
+                               if (text.length() < 3)
+                                       throw new IllegalArgumentException();
+                               if (parse(text, WEEKDAYS) != -1) {
+                               } else if (month == -1 && (month = parse(text, MONTHS)) != -1) {
+                               } else if (text.equals("GMT")) {
+                               } else
+                                       throw new IllegalArgumentException();
+                       }
 
-            if (nextState == LETTERS || nextState == NUMBERS)
-                buffer.append(next);
-            state = nextState;
-        }
+                       if (nextState == LETTERS || nextState == NUMBERS)
+                               buffer.append(next);
+                       state = nextState;
+               }
 
-        if (year != -1 && month != -1 && date != -1) {
-            if (hour == -1)
-                hour = 0;
-            if (minute == -1)
-                minute = 0;
-            if (second == -1)
-                second = 0;
-            Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
-            int current = cal.get(Calendar.YEAR) - 80;
-            if (year < 100) {
-                year += current / 100 * 100;
-                if (year < current)
-                    year += 100;
-            }
-            cal.set(Calendar.YEAR, year);
-            cal.set(Calendar.MONTH, month);
-            cal.set(Calendar.DATE, date);
-            cal.set(Calendar.HOUR_OF_DAY, hour);
-            cal.set(Calendar.MINUTE, minute);
-            cal.set(Calendar.SECOND, second);
-            cal.set(Calendar.MILLISECOND, 0);
-            return cal.getTime().getTime();
-        }
-        throw new IllegalArgumentException();
-    }
+               if (year != -1 && month != -1 && date != -1) {
+                       if (hour == -1)
+                               hour = 0;
+                       if (minute == -1)
+                               minute = 0;
+                       if (second == -1)
+                               second = 0;
+                       Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+                       int current = cal.get(Calendar.YEAR) - 80;
+                       if (year < 100) {
+                               year += current / 100 * 100;
+                               if (year < current)
+                                       year += 100;
+                       }
+                       cal.set(Calendar.YEAR, year);
+                       cal.set(Calendar.MONTH, month);
+                       cal.set(Calendar.DATE, date);
+                       cal.set(Calendar.HOUR_OF_DAY, hour);
+                       cal.set(Calendar.MINUTE, minute);
+                       cal.set(Calendar.SECOND, second);
+                       cal.set(Calendar.MILLISECOND, 0);
+                       return cal.getTime().getTime();
+               }
+               throw new IllegalArgumentException();
+       }
 
-    private static int parse(String string, String[] array) {
-        int length = string.length();
-        for (int i = 0; i < array.length; i++) {
-            if (string.regionMatches(true, 0, array[i], 0, length))
-                return i;
-        }
-        return -1;
-    }
+       private static int parse(String string, String[] array) {
+               int length = string.length();
+               for (int i = 0; i < array.length; i++) {
+                       if (string.regionMatches(true, 0, array[i], 0, length))
+                               return i;
+               }
+               return -1;
+       }
 
-    public static String convertFromUTF8(byte[] buf, int offset, int utfSize)
-            throws UTFDataFormatException {
-        return convertUTF8WithBuf(buf, new char[utfSize], offset, utfSize);
-    }
+       public static String convertFromUTF8(byte[] buf, int offset, int utfSize)
+                       throws UTFDataFormatException {
+               return convertUTF8WithBuf(buf, new char[utfSize], offset, utfSize);
+       }
 
-    public static String convertUTF8WithBuf(byte[] buf, char[] out, int offset,
-            int utfSize) throws UTFDataFormatException {
-        int count = 0, s = 0, a;
-        while (count < utfSize) {
-            if ((out[s] = (char) buf[offset + count++]) < '\u0080')
-                s++;
-            else if (((a = out[s]) & 0xe0) == 0xc0) {
-                if (count >= utfSize)
-                    throw new UTFDataFormatException(Msg.getString("K0062",
-                            count));
+       public static String convertUTF8WithBuf(byte[] buf, char[] out, int offset,
+                       int utfSize) throws UTFDataFormatException {
+               int count = 0, s = 0, a;
+               while (count < utfSize) {
+                       if ((out[s] = (char) buf[offset + count++]) < '\u0080')
+                               s++;
+                       else if (((a = out[s]) & 0xe0) == 0xc0) {
+                               if (count >= utfSize)
+                                       throw new UTFDataFormatException(Msg.getString("K0062",
+                                                       count));
                 // BEGIN android-changed
                 int b = buf[offset + count++];
                 // END android-changed
-                if ((b & 0xC0) != 0x80)
-                    throw new UTFDataFormatException(Msg.getString("K0062",
-                            (count - 1)));
-                out[s++] = (char) (((a & 0x1F) << 6) | (b & 0x3F));
-            } else if ((a & 0xf0) == 0xe0) {
-                if (count + 1 >= utfSize)
-                    throw new UTFDataFormatException(Msg.getString("K0063",
-                            (count + 1)));
+                               if ((b & 0xC0) != 0x80)
+                                       throw new UTFDataFormatException(Msg.getString("K0062",
+                                                       (count - 1)));
+                               out[s++] = (char) (((a & 0x1F) << 6) | (b & 0x3F));
+                       } else if ((a & 0xf0) == 0xe0) {
+                               if (count + 1 >= utfSize)
+                                       throw new UTFDataFormatException(Msg.getString("K0063",
+                                                       (count + 1)));
                 // BEGIN android-changed
                 int b = buf[offset + count++];
                 int c = buf[offset + count++];
                 // END android-changed
-                if (((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80))
-                    throw new UTFDataFormatException(Msg.getString("K0064",
-                            (count - 2)));
-                out[s++] = (char) (((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F));
-            } else {
-                throw new UTFDataFormatException(Msg.getString("K0065",
-                        (count - 1)));
-            }
-        }
-        return new String(out, 0, s);
+                               if (((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80))
+                                       throw new UTFDataFormatException(Msg.getString("K0064",
+                                                       (count - 2)));
+                               out[s++] = (char) (((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F));
+                       } else {
+                               throw new UTFDataFormatException(Msg.getString("K0065",
+                                               (count - 1)));
+                       }
+               }
+               return new String(out, 0, s);
+       }
+
+       /**
+        * '%' and two following hex digit characters are converted to the
+        * equivalent byte value. All other characters are passed through
+        * unmodified. e.g. "ABC %24%25" -> "ABC $%"
+        * 
+        * @param s
+        *            java.lang.String The encoded string.
+        * @return java.lang.String The decoded version.
+        */
+    public static String decode(String s, boolean convertPlus) {
+        return decode(s, convertPlus, null);
     }
 
     /**
      * '%' and two following hex digit characters are converted to the
      * equivalent byte value. All other characters are passed through
      * unmodified. e.g. "ABC %24%25" -> "ABC $%"
-     *
+     * 
      * @param s
      *            java.lang.String The encoded string.
+     * @param encoding
+     *            the specified encoding
      * @return java.lang.String The decoded version.
      */
-    public static String decode(String s, boolean convertPlus) {
+    public static String decode(String s, boolean convertPlus, String encoding) {
         if (!convertPlus && s.indexOf('%') == -1)
             return s;
-        StringBuffer result = new StringBuffer(s.length());
+        StringBuilder result = new StringBuilder(s.length());
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         for (int i = 0; i < s.length();) {
             char c = s.charAt(i);
@@ -297,7 +313,15 @@ public final class Util {
                     out.write((byte) ((d1 << 4) + d2));
                     i += 3;
                 } while (i < s.length() && s.charAt(i) == '%');
-                result.append(out.toString());
+                if (encoding == null) {
+                    result.append(out.toString());
+                } else {
+                    try {
+                        result.append(out.toString(encoding));
+                    } catch (UnsupportedEncodingException e) {
+                        throw new IllegalArgumentException(e);
+                    }
+                }
                 continue;
             } else
                 result.append(c);
@@ -305,32 +329,32 @@ public final class Util {
         }
         return result.toString();
     }
-
-    public static String toASCIILowerCase(String s) {
+       
+       public static String toASCIILowerCase(String s) {
         int len = s.length();
-        StringBuilder buffer = new StringBuilder(len);
-        for (int i = 0; i < len; i++) {
-            char c = s.charAt(i);
-            if ('A' <= c && c <= 'Z') {
-                buffer.append((char) (c + ('a' - 'A')));
-            } else {
-                buffer.append(c);
-            }
-        }
-        return buffer.toString();
-    }
-
-    public static String toASCIIUpperCase(String s) {
+               StringBuilder buffer = new StringBuilder(len);
+               for (int i = 0; i < len; i++) {
+                       char c = s.charAt(i);
+                       if ('A' <= c && c <= 'Z') {
+                               buffer.append((char) (c + ('a' - 'A')));
+                       } else {
+                               buffer.append(c);
+                       }
+               }
+               return buffer.toString();
+       }
+       
+       public static String toASCIIUpperCase(String s) {
         int len = s.length();
         StringBuilder buffer = new StringBuilder(len);
         for (int i = 0; i < len; i++) {
-            char c = s.charAt(i);
-            if ('a' <= c && c <= 'z') {
-                buffer.append((char) (c - ('a' - 'A')));
-            } else {
-                buffer.append(c);
-            }
-        }
-        return buffer.toString();
-    }
+                       char c = s.charAt(i);
+               if ('a' <= c && c <= 'z') {
+                       buffer.append((char) (c - ('a' - 'A')));
+               } else {
+                               buffer.append(c);
+                       }
+               }
+               return buffer.toString();
+       }
 }
index 77ee0f8..d327940 100644 (file)
@@ -18,7 +18,7 @@
 #include <string.h>
 #include "cbigint.h"
 
-#if defined(LINUX) || defined(FREEBSD) || defined(ZOS)
+#if defined(LINUX) || defined(FREEBSD) || defined(ZOS) || defined(MACOSX) || defined(AIX)
 #define USE_LL
 #endif
 
@@ -665,7 +665,7 @@ tenToTheEHighPrecision (U_64 * result, IDATA length, jint e)
      do {
      overflow = simpleAppendDecimalDigitHighPrecision(result, length, 0);
      if (overflow)
-     result[length++] = overflow; 
+     result[length++] = overflow;
      } while (--e);
    */
   return length;
@@ -686,7 +686,7 @@ timesTenToTheEHighPrecision (U_64 * result, IDATA length, jint e)
      do {
      overflow = simpleAppendDecimalDigitHighPrecision(result, length, 0);
      if (overflow)
-     result[length++] = overflow; 
+     result[length++] = overflow;
      } while (--e);
    */
   /* Replace the current implementaion which performs a
index 778e527..056b521 100644 (file)
@@ -34,6 +34,7 @@ public class AllTests
         TestSuite suite = tests.TestSuiteFactory.createTestSuite("Tests for java.io");
 
         suite.addTestSuite(BufferedReaderTest.class);
+        suite.addTestSuite(FileCanonPathCacheTest.class);
         suite.addTestSuite(FilePermissionTest.class);
         suite.addTestSuite(FileTest.class);
         suite.addTestSuite(InputStreamReaderTest.class);
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileCanonPathCacheTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileCanonPathCacheTest.java
new file mode 100644 (file)
index 0000000..f2ac7f3
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.harmony.luni.tests.java.io;
+
+import java.io.File;
+
+import org.apache.harmony.luni.internal.io.FileCanonPathCache;
+
+import junit.framework.TestCase;
+
+public class FileCanonPathCacheTest extends TestCase {
+
+    private static int DEFAULT_TIMEOUT = 600000;
+
+    @Override
+    public void setUp() throws Exception {
+        FileCanonPathCache.clear();
+        FileCanonPathCache.setTimeout(DEFAULT_TIMEOUT);
+    }
+
+    public void testGetSet() throws Exception {
+        File file1 = new File("test/hello~1");
+        assertNull(FileCanonPathCache.get(file1.getAbsolutePath()));
+        FileCanonPathCache.put(file1.getAbsolutePath(), file1
+                .getCanonicalPath());
+        assertEquals(file1.getCanonicalPath(), FileCanonPathCache.get(file1
+                .getAbsolutePath()));
+
+        File file2 = new File("test/world~1");
+        assertNull(FileCanonPathCache.get(file2.getAbsolutePath()));
+        FileCanonPathCache.put(file2.getAbsolutePath(), file2
+                .getCanonicalPath());
+        assertEquals(file2.getCanonicalPath(), FileCanonPathCache.get(file2
+                .getAbsolutePath()));
+
+        assertNull(FileCanonPathCache.get("notexist"));
+    }
+
+    public void testGetTimeout01() throws Exception {
+        FileCanonPathCache.setTimeout(10);
+
+        File file1 = new File("test/hello~1");
+        assertNull(FileCanonPathCache.get(file1.getAbsolutePath()));
+        FileCanonPathCache.put(file1.getAbsolutePath(), file1
+                .getCanonicalPath());
+        Thread.sleep(50);
+        assertNull(FileCanonPathCache.get(file1.getAbsolutePath()));
+    }
+
+    public void testGetTimeout02() throws Exception {
+        FileCanonPathCache.setTimeout(10);
+
+        File file1 = new File("test/hello~1");
+        assertNull(FileCanonPathCache.get(file1.getAbsolutePath()));
+        FileCanonPathCache.put(file1.getAbsolutePath(), file1
+                .getCanonicalPath());
+        File file2 = new File("test/hello~2");
+        assertNull(FileCanonPathCache.get(file2.getAbsolutePath()));
+        FileCanonPathCache.put(file2.getAbsolutePath(), file2
+                .getCanonicalPath());
+        File file3 = new File("test/hello~3");
+        assertNull(FileCanonPathCache.get(file3.getAbsolutePath()));
+        FileCanonPathCache.put(file3.getAbsolutePath(), file3
+                .getCanonicalPath());
+        File file4 = new File("test/hello~4");
+        assertNull(FileCanonPathCache.get(file4.getAbsolutePath()));
+        FileCanonPathCache.put(file4.getAbsolutePath(), file4
+                .getCanonicalPath());
+        File file5 = new File("test/hello~5");
+        assertNull(FileCanonPathCache.get(file5.getAbsolutePath()));
+        FileCanonPathCache.put(file5.getAbsolutePath(), file5
+                .getCanonicalPath());
+
+        Thread.sleep(50);
+
+        assertNull(FileCanonPathCache.get(file1.getAbsolutePath()));
+        assertNull(FileCanonPathCache.get(file2.getAbsolutePath()));
+        assertNull(FileCanonPathCache.get(file3.getAbsolutePath()));
+        assertNull(FileCanonPathCache.get(file4.getAbsolutePath()));
+        assertNull(FileCanonPathCache.get(file5.getAbsolutePath()));
+    }
+
+    public void testCacheFull() throws Exception {
+        int cacheSize = FileCanonPathCache.CACHE_SIZE;
+        File[] files = new File[cacheSize];
+        for (int i = 0; i < cacheSize; ++i) {
+            files[i] = new File("test/world" + i);
+            FileCanonPathCache.put(files[i].getAbsolutePath(), files[i]
+                    .getCanonicalPath());
+        }
+
+        for (int i = cacheSize; i < files.length; ++i) {
+            assertEquals(files[i - cacheSize].getCanonicalPath(),
+                    FileCanonPathCache.get(files[i - cacheSize]
+                            .getAbsolutePath()));
+            files[i] = new File("test/world" + i);
+            FileCanonPathCache.put(files[i].getAbsolutePath(), files[i]
+                    .getCanonicalPath());
+            assertEquals(files[i].getCanonicalPath(), FileCanonPathCache
+                    .get(files[i].getAbsolutePath()));
+            assertNull(FileCanonPathCache.get(files[i - cacheSize]
+                    .getAbsolutePath()));
+        }
+    }
+}